Detailed changes
@@ -27,11 +27,9 @@ use crate::db::billing_subscription::{
StripeCancellationReason, StripeSubscriptionStatus, SubscriptionKind,
};
use crate::llm::db::subscription_usage_meter::CompletionMode;
-use crate::llm::{
- AGENT_EXTENDED_TRIAL_FEATURE_FLAG, DEFAULT_MAX_MONTHLY_SPEND, FREE_TIER_MONTHLY_SPENDING_LIMIT,
-};
+use crate::llm::{AGENT_EXTENDED_TRIAL_FEATURE_FLAG, DEFAULT_MAX_MONTHLY_SPEND};
use crate::rpc::{ResultExt as _, Server};
-use crate::{AppState, Cents, Error, Result};
+use crate::{AppState, Error, Result};
use crate::{db::UserId, llm::db::LlmDatabase};
use crate::{
db::{
@@ -64,7 +62,6 @@ pub fn router() -> Router {
"/billing/subscriptions/sync",
post(sync_billing_subscription),
)
- .route("/billing/monthly_spend", get(get_monthly_spend))
.route("/billing/usage", get(get_current_usage))
}
@@ -1223,54 +1220,6 @@ async fn handle_customer_subscription_event(
Ok(())
}
-#[derive(Debug, Deserialize)]
-struct GetMonthlySpendParams {
- github_user_id: i32,
-}
-
-#[derive(Debug, Serialize)]
-struct GetMonthlySpendResponse {
- monthly_free_tier_spend_in_cents: u32,
- monthly_free_tier_allowance_in_cents: u32,
- monthly_spend_in_cents: u32,
-}
-
-async fn get_monthly_spend(
- Extension(app): Extension<Arc<AppState>>,
- Query(params): Query<GetMonthlySpendParams>,
-) -> Result<Json<GetMonthlySpendResponse>> {
- let user = app
- .db
- .get_user_by_github_user_id(params.github_user_id)
- .await?
- .context("user not found")?;
-
- let Some(llm_db) = app.llm_db.clone() else {
- return Err(Error::http(
- StatusCode::NOT_IMPLEMENTED,
- "LLM database not available".into(),
- ));
- };
-
- let free_tier = user
- .custom_llm_monthly_allowance_in_cents
- .map(|allowance| Cents(allowance as u32))
- .unwrap_or(FREE_TIER_MONTHLY_SPENDING_LIMIT);
-
- let spending_for_month = llm_db
- .get_user_spending_for_month(user.id, Utc::now())
- .await?;
-
- let free_tier_spend = Cents::min(spending_for_month, free_tier);
- let monthly_spend = spending_for_month.saturating_sub(free_tier);
-
- Ok(Json(GetMonthlySpendResponse {
- monthly_free_tier_spend_in_cents: free_tier_spend.0,
- monthly_free_tier_allowance_in_cents: free_tier.0,
- monthly_spend_in_cents: monthly_spend.0,
- }))
-}
-
#[derive(Debug, Deserialize)]
struct GetCurrentUsageParams {
github_user_id: i32,
@@ -7,10 +7,6 @@ pub use token::*;
pub const AGENT_EXTENDED_TRIAL_FEATURE_FLAG: &str = "agent-extended-trial";
-/// The maximum monthly spending an individual user can reach on the free tier
-/// before they have to pay.
-pub const FREE_TIER_MONTHLY_SPENDING_LIMIT: Cents = Cents::from_dollars(10);
-
/// The default value to use for maximum spend per month if the user did not
/// explicitly set a maximum spend.
///
@@ -1,7 +1,3 @@
-use crate::db::UserId;
-use crate::llm::Cents;
-use chrono::Datelike;
-use futures::StreamExt as _;
use std::str::FromStr;
use strum::IntoEnumIterator as _;
@@ -45,68 +41,4 @@ impl LlmDatabase {
.collect();
Ok(())
}
-
- pub async fn get_user_spending_for_month(
- &self,
- user_id: UserId,
- now: DateTimeUtc,
- ) -> Result<Cents> {
- self.transaction(|tx| async move {
- let month = now.date_naive().month() as i32;
- let year = now.date_naive().year();
-
- let mut monthly_usages = monthly_usage::Entity::find()
- .filter(
- monthly_usage::Column::UserId
- .eq(user_id)
- .and(monthly_usage::Column::Month.eq(month))
- .and(monthly_usage::Column::Year.eq(year)),
- )
- .stream(&*tx)
- .await?;
- let mut monthly_spending = Cents::ZERO;
-
- while let Some(usage) = monthly_usages.next().await {
- let usage = usage?;
- let Ok(model) = self.model_by_id(usage.model_id) else {
- continue;
- };
-
- monthly_spending += calculate_spending(
- model,
- usage.input_tokens as usize,
- usage.cache_creation_input_tokens as usize,
- usage.cache_read_input_tokens as usize,
- usage.output_tokens as usize,
- );
- }
-
- Ok(monthly_spending)
- })
- .await
- }
-}
-
-fn calculate_spending(
- model: &model::Model,
- input_tokens_this_month: usize,
- cache_creation_input_tokens_this_month: usize,
- cache_read_input_tokens_this_month: usize,
- output_tokens_this_month: usize,
-) -> Cents {
- let input_token_cost =
- input_tokens_this_month * model.price_per_million_input_tokens as usize / 1_000_000;
- let cache_creation_input_token_cost = cache_creation_input_tokens_this_month
- * model.price_per_million_cache_creation_input_tokens as usize
- / 1_000_000;
- let cache_read_input_token_cost = cache_read_input_tokens_this_month
- * model.price_per_million_cache_read_input_tokens as usize
- / 1_000_000;
- let output_token_cost =
- output_tokens_this_month * model.price_per_million_output_tokens as usize / 1_000_000;
- let spending = input_token_cost
- + cache_creation_input_token_cost
- + cache_read_input_token_cost
- + output_token_cost;
- Cents::new(spending as u32)
}
@@ -1,5 +1,4 @@
pub mod model;
-pub mod monthly_usage;
pub mod provider;
pub mod subscription_usage;
pub mod subscription_usage_meter;
@@ -1,22 +0,0 @@
-use crate::{db::UserId, llm::db::ModelId};
-use sea_orm::entity::prelude::*;
-
-#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
-#[sea_orm(table_name = "monthly_usages")]
-pub struct Model {
- #[sea_orm(primary_key)]
- pub id: i32,
- pub user_id: UserId,
- pub model_id: ModelId,
- pub month: i32,
- pub year: i32,
- pub input_tokens: i64,
- pub cache_creation_input_tokens: i64,
- pub cache_read_input_tokens: i64,
- pub output_tokens: i64,
-}
-
-#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
-pub enum Relation {}
-
-impl ActiveModelBehavior for ActiveModel {}