//! Billing — delegates to agent crate. use crate::AppService; use crate::error::AppError; use sea_orm::*; use uuid::Uuid; impl AppService { /// Record AI usage against a project or workspace. /// /// `model_id` is an `ai_model.id`. The active/default model version is resolved /// internally so callers do not need to distinguish ModelId from ModelVersionId. pub async fn record_ai_usage( &self, project_uid: Uuid, model_id: Uuid, input_tokens: i64, output_tokens: i64, ) -> Result { use agent::billing::BillingResult; use models::agents::model_version; let version_id = model_version::Entity::find() .filter(model_version::Column::ModelId.eq(model_id)) .filter(model_version::Column::Status.eq("active")) .order_by_desc(model_version::Column::IsDefault) .order_by_desc(model_version::Column::ReleaseDate) .one(&self.db) .await? .map(|v| v.id) .unwrap_or(model_id); match agent::billing::record_ai_usage( &self.db, project_uid, version_id, input_tokens, output_tokens, ) .await? { BillingResult::Success(record) => Ok(record), BillingResult::InsufficientBalance { message } => { Err(AppError::BadRequest(message)) } } } }