systemprompt_cli/commands/analytics/conversations/
mod.rs1mod list;
12mod stats;
13mod trends;
14
15use anyhow::Result;
16use clap::Subcommand;
17use schemars::JsonSchema;
18use serde::{Deserialize, Serialize};
19use systemprompt_identifiers::UserId;
20
21use crate::context::CommandContext;
22use crate::shared::render_result;
23
24#[derive(Debug, Subcommand)]
25pub enum ConversationsCommands {
26 #[command(about = "Conversation statistics")]
27 Stats(stats::StatsArgs),
28
29 #[command(about = "Conversation trends over time")]
30 Trends(trends::TrendsArgs),
31
32 #[command(about = "List conversations")]
33 List(list::ListArgs),
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
37pub struct ConversationStatsOutput {
38 pub period: String,
39 pub total_contexts: i64,
40 pub total_tasks: i64,
41 pub total_messages: i64,
42 pub avg_messages_per_task: f64,
43 pub avg_task_duration_ms: i64,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
47pub struct ConversationTrendPoint {
48 pub timestamp: String,
49 pub context_count: i64,
50 pub task_count: i64,
51 pub message_count: i64,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
55pub struct ConversationTrendsOutput {
56 pub period: String,
57 pub group_by: String,
58 pub points: Vec<ConversationTrendPoint>,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
62pub struct ConversationListRow {
63 #[serde(rename = "context_id")]
64 pub context: String,
65 pub source: String,
66 pub user_id: UserId,
67 pub name: Option<String>,
68 pub task_count: i64,
69 pub message_count: i64,
70 pub created_at: String,
71 pub updated_at: String,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
75pub struct ConversationListOutput {
76 pub conversations: Vec<ConversationListRow>,
77 pub total: i64,
78}
79
80pub async fn execute(command: ConversationsCommands, ctx: &CommandContext) -> Result<()> {
81 let db_ctx = ctx.database().await?;
82 match command {
83 ConversationsCommands::Stats(args) => {
84 let result = stats::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
85 render_result(&result, &ctx.cli);
86 Ok(())
87 },
88 ConversationsCommands::Trends(args) => {
89 let result = trends::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
90 render_result(&result, &ctx.cli);
91 Ok(())
92 },
93 ConversationsCommands::List(args) => {
94 let result = list::execute_with_pool(args, &db_ctx, &ctx.cli).await?;
95 render_result(&result, &ctx.cli);
96 Ok(())
97 },
98 }
99}