diff --git a/crates/collab/src/api/billing.rs b/crates/collab/src/api/billing.rs index d3c9c1cad1..0c39383ef1 100644 --- a/crates/collab/src/api/billing.rs +++ b/crates/collab/src/api/billing.rs @@ -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>, - Query(params): Query, -) -> Result> { - 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, diff --git a/crates/collab/src/llm.rs b/crates/collab/src/llm.rs index 0a5b5bbf5a..5e385fae36 100644 --- a/crates/collab/src/llm.rs +++ b/crates/collab/src/llm.rs @@ -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. /// diff --git a/crates/collab/src/llm/db/queries/usages.rs b/crates/collab/src/llm/db/queries/usages.rs index 6313e7572c..a917703f96 100644 --- a/crates/collab/src/llm/db/queries/usages.rs +++ b/crates/collab/src/llm/db/queries/usages.rs @@ -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 { - 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) } diff --git a/crates/collab/src/llm/db/tables.rs b/crates/collab/src/llm/db/tables.rs index d178fb10d3..75ea8f5140 100644 --- a/crates/collab/src/llm/db/tables.rs +++ b/crates/collab/src/llm/db/tables.rs @@ -1,5 +1,4 @@ pub mod model; -pub mod monthly_usage; pub mod provider; pub mod subscription_usage; pub mod subscription_usage_meter; diff --git a/crates/collab/src/llm/db/tables/monthly_usage.rs b/crates/collab/src/llm/db/tables/monthly_usage.rs deleted file mode 100644 index 1e849f6aef..0000000000 --- a/crates/collab/src/llm/db/tables/monthly_usage.rs +++ /dev/null @@ -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 {}