@@ -1,4 +1,5 @@
use anyhow::{Context as _, bail};
+use axum::routing::put;
use axum::{
Extension, Json, Router,
extract::{self, Query},
@@ -27,8 +28,8 @@ use crate::api::events::SnowflakeRow;
use crate::db::billing_subscription::{
StripeCancellationReason, StripeSubscriptionStatus, SubscriptionKind,
};
+use crate::llm::AGENT_EXTENDED_TRIAL_FEATURE_FLAG;
use crate::llm::db::subscription_usage_meter::{self, CompletionMode};
-use crate::llm::{AGENT_EXTENDED_TRIAL_FEATURE_FLAG, DEFAULT_MAX_MONTHLY_SPEND};
use crate::rpc::{ResultExt as _, Server};
use crate::stripe_client::{
StripeCancellationDetailsReason, StripeClient, StripeCustomerId, StripeSubscription,
@@ -47,10 +48,7 @@ use crate::{
pub fn router() -> Router {
Router::new()
- .route(
- "/billing/preferences",
- get(get_billing_preferences).put(update_billing_preferences),
- )
+ .route("/billing/preferences", put(update_billing_preferences))
.route(
"/billing/subscriptions",
get(list_billing_subscriptions).post(create_billing_subscription),
@@ -66,11 +64,6 @@ pub fn router() -> Router {
.route("/billing/usage", get(get_current_usage))
}
-#[derive(Debug, Deserialize)]
-struct GetBillingPreferencesParams {
- github_user_id: i32,
-}
-
#[derive(Debug, Serialize)]
struct BillingPreferencesResponse {
trial_started_at: Option<String>,
@@ -79,43 +72,6 @@ struct BillingPreferencesResponse {
model_request_overages_spend_limit_in_cents: i32,
}
-async fn get_billing_preferences(
- Extension(app): Extension<Arc<AppState>>,
- Query(params): Query<GetBillingPreferencesParams>,
-) -> Result<Json<BillingPreferencesResponse>> {
- let user = app
- .db
- .get_user_by_github_user_id(params.github_user_id)
- .await?
- .context("user not found")?;
-
- let billing_customer = app.db.get_billing_customer_by_user_id(user.id).await?;
- let preferences = app.db.get_billing_preferences(user.id).await?;
-
- Ok(Json(BillingPreferencesResponse {
- trial_started_at: billing_customer
- .and_then(|billing_customer| billing_customer.trial_started_at)
- .map(|trial_started_at| {
- trial_started_at
- .and_utc()
- .to_rfc3339_opts(SecondsFormat::Millis, true)
- }),
- max_monthly_llm_usage_spending_in_cents: preferences
- .as_ref()
- .map_or(DEFAULT_MAX_MONTHLY_SPEND.0 as i32, |preferences| {
- preferences.max_monthly_llm_usage_spending_in_cents
- }),
- model_request_overages_enabled: preferences.as_ref().map_or(false, |preferences| {
- preferences.model_request_overages_enabled
- }),
- model_request_overages_spend_limit_in_cents: preferences
- .as_ref()
- .map_or(0, |preferences| {
- preferences.model_request_overages_spend_limit_in_cents
- }),
- }))
-}
-
#[derive(Debug, Deserialize)]
struct UpdateBillingPreferencesBody {
github_user_id: i32,
@@ -1,83 +0,0 @@
-use serde::Serialize;
-
-/// A number of cents.
-#[derive(
- Debug,
- PartialEq,
- Eq,
- PartialOrd,
- Ord,
- Hash,
- Clone,
- Copy,
- derive_more::Add,
- derive_more::AddAssign,
- derive_more::Sub,
- derive_more::SubAssign,
- Serialize,
-)]
-pub struct Cents(pub u32);
-
-impl Cents {
- pub const ZERO: Self = Self(0);
-
- pub const fn new(cents: u32) -> Self {
- Self(cents)
- }
-
- pub const fn from_dollars(dollars: u32) -> Self {
- Self(dollars * 100)
- }
-
- pub fn saturating_sub(self, other: Cents) -> Self {
- Self(self.0.saturating_sub(other.0))
- }
-}
-
-#[cfg(test)]
-mod tests {
- use pretty_assertions::assert_eq;
-
- use super::*;
-
- #[test]
- fn test_cents_new() {
- assert_eq!(Cents::new(50), Cents(50));
- }
-
- #[test]
- fn test_cents_from_dollars() {
- assert_eq!(Cents::from_dollars(1), Cents(100));
- assert_eq!(Cents::from_dollars(5), Cents(500));
- }
-
- #[test]
- fn test_cents_zero() {
- assert_eq!(Cents::ZERO, Cents(0));
- }
-
- #[test]
- fn test_cents_add() {
- assert_eq!(Cents(50) + Cents(30), Cents(80));
- }
-
- #[test]
- fn test_cents_add_assign() {
- let mut cents = Cents(50);
- cents += Cents(30);
- assert_eq!(cents, Cents(80));
- }
-
- #[test]
- fn test_cents_saturating_sub() {
- assert_eq!(Cents(50).saturating_sub(Cents(30)), Cents(20));
- assert_eq!(Cents(30).saturating_sub(Cents(50)), Cents(0));
- }
-
- #[test]
- fn test_cents_ordering() {
- assert!(Cents(50) > Cents(30));
- assert!(Cents(30) < Cents(50));
- assert_eq!(Cents(50), Cents(50));
- }
-}
@@ -1,6 +1,5 @@
pub mod api;
pub mod auth;
-mod cents;
pub mod db;
pub mod env;
pub mod executor;
@@ -21,7 +20,6 @@ use axum::{
http::{HeaderMap, StatusCode},
response::IntoResponse,
};
-pub use cents::*;
use db::{ChannelId, Database};
use executor::Executor;
use llm::db::LlmDatabase;
@@ -1,8 +1,6 @@
pub mod db;
mod token;
-use crate::Cents;
-
pub use token::*;
pub const AGENT_EXTENDED_TRIAL_FEATURE_FLAG: &str = "agent-extended-trial";
@@ -12,9 +10,3 @@ pub const BYPASS_ACCOUNT_AGE_CHECK_FEATURE_FLAG: &str = "bypass-account-age-chec
/// The minimum account age an account must have in order to use the LLM service.
pub const MIN_ACCOUNT_AGE_FOR_LLM_USE: chrono::Duration = chrono::Duration::days(30);
-
-/// The default value to use for maximum spend per month if the user did not
-/// explicitly set a maximum spend.
-///
-/// Used to prevent surprise bills.
-pub const DEFAULT_MAX_MONTHLY_SPEND: Cents = Cents::from_dollars(10);