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