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