Skip to main content

systemprompt_cli/commands/infrastructure/logs/request/
mod.rs

1mod list;
2mod show;
3mod stats;
4
5use anyhow::Result;
6use clap::Subcommand;
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use systemprompt_runtime::DatabaseContext;
10
11use super::types::{MessageRow, ToolCallRow};
12use crate::CliConfig;
13
14#[derive(Debug, Subcommand)]
15pub enum RequestCommands {
16    #[command(
17        about = "List recent AI requests",
18        after_help = "EXAMPLES:\n  systemprompt infra logs request list\n  systemprompt infra \
19                      logs request list --model gpt-4 --since 1h"
20    )]
21    List(list::ListArgs),
22
23    #[command(
24        about = "Show AI request details",
25        after_help = "EXAMPLES:\n  systemprompt infra logs request show abc123\n  systemprompt \
26                      infra logs request show abc123 --messages --tools"
27    )]
28    Show(show::ShowArgs),
29
30    #[command(
31        about = "Show aggregate AI request statistics",
32        after_help = "EXAMPLES:\n  systemprompt infra logs request stats\n  systemprompt infra \
33                      logs request stats --since 24h"
34    )]
35    Stats(stats::StatsArgs),
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
39pub struct RequestListRow {
40    pub request_id: String,
41    pub timestamp: String,
42    pub provider: String,
43    pub model: String,
44    pub tokens: String,
45    pub cost: String,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub latency_ms: Option<i64>,
48    pub status: String,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
52pub struct RequestListOutput {
53    pub requests: Vec<RequestListRow>,
54    pub total: u64,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
58pub struct RequestShowOutput {
59    pub request_id: String,
60    pub provider: String,
61    pub model: String,
62    pub input_tokens: i32,
63    pub output_tokens: i32,
64    pub cost_dollars: f64,
65    pub latency_ms: i64,
66    pub status: String,
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub error_message: Option<String>,
69    pub messages: Vec<MessageRow>,
70    pub linked_mcp_calls: Vec<ToolCallRow>,
71}
72
73pub async fn execute(command: RequestCommands, config: &CliConfig) -> Result<()> {
74    match command {
75        RequestCommands::List(args) => list::execute(args, config).await,
76        RequestCommands::Show(args) => show::execute(args, config).await,
77        RequestCommands::Stats(args) => stats::execute(args, config).await,
78    }
79}
80
81pub async fn execute_with_pool(
82    command: RequestCommands,
83    db_ctx: &DatabaseContext,
84    config: &CliConfig,
85) -> Result<()> {
86    match command {
87        RequestCommands::List(args) => list::execute_with_pool(args, db_ctx, config).await,
88        RequestCommands::Show(args) => show::execute_with_pool(args, db_ctx, config).await,
89        RequestCommands::Stats(args) => stats::execute_with_pool(args, db_ctx, config).await,
90    }
91}