systemprompt_cli/commands/analytics/agents/
mod.rs1mod list;
9mod show;
10mod stats;
11mod trends;
12
13use anyhow::Result;
14use clap::Subcommand;
15use schemars::JsonSchema;
16use serde::{Deserialize, Serialize};
17use systemprompt_runtime::DatabaseContext;
18
19use crate::CliConfig;
20use crate::shared::render_result;
21
22#[derive(Debug, Subcommand)]
23pub enum AgentsCommands {
24 #[command(about = "Aggregate agent statistics")]
25 Stats(stats::StatsArgs),
26
27 #[command(about = "List agents with metrics")]
28 List(list::ListArgs),
29
30 #[command(about = "Agent usage trends over time")]
31 Trends(trends::TrendsArgs),
32
33 #[command(about = "Deep dive into specific agent")]
34 Show(show::ShowArgs),
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
38pub struct AgentStatsOutput {
39 pub period: String,
40 pub total_agents: i64,
41 pub total_tasks: i64,
42 pub completed_tasks: i64,
43 pub failed_tasks: i64,
44 pub success_rate: f64,
45 pub avg_execution_time_ms: i64,
46 pub total_ai_requests: i64,
47 pub total_cost_microdollars: i64,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
51pub struct AgentListRow {
52 pub agent_name: String,
53 pub task_count: i64,
54 pub success_rate: f64,
55 pub avg_execution_time_ms: i64,
56 pub total_cost_microdollars: i64,
57 pub last_active: String,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
61pub struct AgentListOutput {
62 pub agents: Vec<AgentListRow>,
63 pub total: i64,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
67pub struct AgentTrendPoint {
68 pub timestamp: String,
69 pub task_count: i64,
70 pub success_rate: f64,
71 pub avg_execution_time_ms: i64,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
75pub struct AgentTrendsOutput {
76 pub agent: Option<String>,
77 pub period: String,
78 pub group_by: String,
79 pub points: Vec<AgentTrendPoint>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
83pub struct AgentShowOutput {
84 pub agent_name: String,
85 pub period: String,
86 pub summary: AgentStatsOutput,
87 pub status_breakdown: Vec<StatusBreakdownItem>,
88 pub top_errors: Vec<ErrorBreakdownItem>,
89 pub hourly_distribution: Vec<HourlyDistributionItem>,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
93pub struct StatusBreakdownItem {
94 pub status: String,
95 pub count: i64,
96 pub percentage: f64,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
100pub struct ErrorBreakdownItem {
101 pub error_type: String,
102 pub count: i64,
103}
104
105#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
106pub struct HourlyDistributionItem {
107 pub hour: i32,
108 pub count: i64,
109}
110
111pub async fn execute(command: AgentsCommands, config: &CliConfig) -> Result<()> {
112 match command {
113 AgentsCommands::Stats(args) => {
114 let result = stats::execute(args, config).await?;
115 render_result(&result);
116 Ok(())
117 },
118 AgentsCommands::List(args) => {
119 let result = list::execute(args, config).await?;
120 render_result(&result);
121 Ok(())
122 },
123 AgentsCommands::Trends(args) => {
124 let result = trends::execute(args, config).await?;
125 render_result(&result);
126 Ok(())
127 },
128 AgentsCommands::Show(args) => {
129 let result = show::execute(args, config).await?;
130 render_result(&result);
131 Ok(())
132 },
133 }
134}
135
136pub async fn execute_with_pool(
137 command: AgentsCommands,
138 db_ctx: &DatabaseContext,
139 config: &CliConfig,
140) -> Result<()> {
141 match command {
142 AgentsCommands::Stats(args) => {
143 let result = stats::execute_with_pool(args, db_ctx, config).await?;
144 render_result(&result);
145 Ok(())
146 },
147 AgentsCommands::List(args) => {
148 let result = list::execute_with_pool(args, db_ctx, config).await?;
149 render_result(&result);
150 Ok(())
151 },
152 AgentsCommands::Trends(args) => {
153 let result = trends::execute_with_pool(args, db_ctx, config).await?;
154 render_result(&result);
155 Ok(())
156 },
157 AgentsCommands::Show(args) => {
158 let result = show::execute_with_pool(args, db_ctx, config).await?;
159 render_result(&result);
160 Ok(())
161 },
162 }
163}