systemprompt-cli 0.1.22

systemprompt.io OS - CLI for agent orchestration, AI operations, and system management
Documentation
mod list;
mod show;
mod stats;
mod trends;

use anyhow::Result;
use clap::Subcommand;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use systemprompt_runtime::DatabaseContext;

use crate::CliConfig;
use crate::shared::render_result;

#[derive(Debug, Subcommand)]
pub enum AgentsCommands {
    #[command(about = "Aggregate agent statistics")]
    Stats(stats::StatsArgs),

    #[command(about = "List agents with metrics")]
    List(list::ListArgs),

    #[command(about = "Agent usage trends over time")]
    Trends(trends::TrendsArgs),

    #[command(about = "Deep dive into specific agent")]
    Show(show::ShowArgs),
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentStatsOutput {
    pub period: String,
    pub total_agents: i64,
    pub total_tasks: i64,
    pub completed_tasks: i64,
    pub failed_tasks: i64,
    pub success_rate: f64,
    pub avg_execution_time_ms: i64,
    pub total_ai_requests: i64,
    pub total_cost_microdollars: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentListRow {
    pub agent_name: String,
    pub task_count: i64,
    pub success_rate: f64,
    pub avg_execution_time_ms: i64,
    pub total_cost_microdollars: i64,
    pub last_active: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentListOutput {
    pub agents: Vec<AgentListRow>,
    pub total: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentTrendPoint {
    pub timestamp: String,
    pub task_count: i64,
    pub success_rate: f64,
    pub avg_execution_time_ms: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentTrendsOutput {
    pub agent: Option<String>,
    pub period: String,
    pub group_by: String,
    pub points: Vec<AgentTrendPoint>,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentShowOutput {
    pub agent_name: String,
    pub period: String,
    pub summary: AgentStatsOutput,
    pub status_breakdown: Vec<StatusBreakdownItem>,
    pub top_errors: Vec<ErrorBreakdownItem>,
    pub hourly_distribution: Vec<HourlyDistributionItem>,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct StatusBreakdownItem {
    pub status: String,
    pub count: i64,
    pub percentage: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ErrorBreakdownItem {
    pub error_type: String,
    pub count: i64,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
pub struct HourlyDistributionItem {
    pub hour: i32,
    pub count: i64,
}

pub async fn execute(command: AgentsCommands, config: &CliConfig) -> Result<()> {
    match command {
        AgentsCommands::Stats(args) => {
            let result = stats::execute(args, config).await?;
            render_result(&result);
            Ok(())
        },
        AgentsCommands::List(args) => {
            let result = list::execute(args, config).await?;
            render_result(&result);
            Ok(())
        },
        AgentsCommands::Trends(args) => {
            let result = trends::execute(args, config).await?;
            render_result(&result);
            Ok(())
        },
        AgentsCommands::Show(args) => {
            let result = show::execute(args, config).await?;
            render_result(&result);
            Ok(())
        },
    }
}

pub async fn execute_with_pool(
    command: AgentsCommands,
    db_ctx: &DatabaseContext,
    config: &CliConfig,
) -> Result<()> {
    match command {
        AgentsCommands::Stats(args) => {
            let result = stats::execute_with_pool(args, db_ctx, config).await?;
            render_result(&result);
            Ok(())
        },
        AgentsCommands::List(args) => {
            let result = list::execute_with_pool(args, db_ctx, config).await?;
            render_result(&result);
            Ok(())
        },
        AgentsCommands::Trends(args) => {
            let result = trends::execute_with_pool(args, db_ctx, config).await?;
            render_result(&result);
            Ok(())
        },
        AgentsCommands::Show(args) => {
            let result = show::execute_with_pool(args, db_ctx, config).await?;
            render_result(&result);
            Ok(())
        },
    }
}