systemprompt_cli/commands/analytics/costs/
mod.rs1mod breakdown;
12pub mod summary;
13mod trends;
14
15use anyhow::Result;
16use clap::{Args, Subcommand};
17use schemars::JsonSchema;
18use serde::{Deserialize, Serialize};
19
20use crate::context::CommandContext;
21use crate::shared::render_result;
22
23#[derive(Debug, Args)]
29pub struct CostsArgs {
30 #[command(subcommand)]
31 pub cmd: Option<CostsCommands>,
32
33 #[command(flatten)]
34 pub summary: summary::SummaryArgs,
35}
36
37#[derive(Debug, Subcommand)]
38pub enum CostsCommands {
39 #[command(about = "Cost summary", alias = "list")]
40 Summary(summary::SummaryArgs),
41
42 #[command(about = "Cost trends over time")]
43 Trends(trends::TrendsArgs),
44
45 #[command(about = "Cost breakdown by model/agent")]
46 Breakdown(breakdown::BreakdownArgs),
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
50pub struct CostSummaryOutput {
51 pub period: String,
52 pub total_cost_microdollars: i64,
53 pub total_requests: i64,
54 pub total_tokens: i64,
55 pub reasoning_tokens: i64,
56 pub cache_read_tokens: i64,
57 pub cache_creation_tokens: i64,
58 pub avg_cost_per_request_microdollars: f64,
59 pub change_percent: Option<f64>,
60 pub auto_widened_to: Option<String>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
64pub struct CostTrendPoint {
65 pub timestamp: String,
66 pub cost_microdollars: i64,
67 pub request_count: i64,
68 pub tokens: i64,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
72pub struct CostTrendsOutput {
73 pub period: String,
74 pub group_by: String,
75 pub points: Vec<CostTrendPoint>,
76 pub total_cost_microdollars: i64,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
80pub struct CostBreakdownItem {
81 pub name: String,
82 pub cost_microdollars: i64,
83 pub request_count: i64,
84 pub tokens: i64,
85 pub percentage: f64,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
89pub struct CostBreakdownOutput {
90 pub period: String,
91 pub breakdown_by: String,
92 pub items: Vec<CostBreakdownItem>,
93 pub total_cost_microdollars: i64,
94}
95
96pub async fn execute(args: CostsArgs, ctx: &CommandContext) -> Result<()> {
97 let db_ctx = ctx.database().await?;
98 match args.cmd.unwrap_or(CostsCommands::Summary(args.summary)) {
99 CostsCommands::Summary(args) => {
100 let result = summary::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
101 render_result(&result, &ctx.cli);
102 Ok(())
103 },
104 CostsCommands::Trends(args) => {
105 let result = trends::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
106 render_result(&result, &ctx.cli);
107 Ok(())
108 },
109 CostsCommands::Breakdown(args) => {
110 let result = breakdown::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
111 render_result(&result, &ctx.cli);
112 Ok(())
113 },
114 }
115}