systemprompt-cli 0.2.1

Unified CLI for systemprompt.io AI governance: agent orchestration, MCP governance, analytics, profiles, cloud deploy, and self-hosted operations.
Documentation
use anyhow::{Result, anyhow};
use clap::Args;
use systemprompt_database::DbPool;
use systemprompt_runtime::AppContext;
use systemprompt_users::{UserAdminService, UserService};

use crate::CliConfig;
use crate::commands::admin::users::types::{SessionListOutput, SessionSummary};
use crate::shared::CommandResult;

#[derive(Debug, Args)]
pub struct ListArgs {
    #[arg(value_name = "USER_ID")]
    pub user: String,

    #[arg(long)]
    pub active: bool,

    #[arg(long, default_value = "20")]
    pub limit: i64,
}

pub async fn execute(
    args: ListArgs,
    config: &CliConfig,
) -> Result<CommandResult<SessionListOutput>> {
    let ctx = AppContext::new().await?;
    execute_with_pool(args, ctx.db_pool(), config).await
}

pub async fn execute_with_pool(
    args: ListArgs,
    pool: &DbPool,
    _config: &CliConfig,
) -> Result<CommandResult<SessionListOutput>> {
    let user_service = UserService::new(pool)?;
    let admin_service = UserAdminService::new(user_service.clone());

    let existing = admin_service.find_user(&args.user).await?;
    let Some(user) = existing else {
        return Err(anyhow!("User not found: {}", args.user));
    };

    let sessions = if args.active {
        user_service.list_active_sessions(&user.id).await?
    } else {
        user_service
            .list_recent_sessions(&user.id, args.limit)
            .await?
    };

    let summaries: Vec<SessionSummary> = sessions
        .into_iter()
        .map(|s| SessionSummary {
            session_id: s.session_id.clone(),
            ip_address: s.ip_address,
            user_agent: s.user_agent,
            device_type: s.device_type,
            started_at: s.started_at,
            last_activity_at: s.last_activity_at,
            is_active: s.ended_at.is_none(),
        })
        .collect();

    let output = SessionListOutput {
        total: summaries.len(),
        sessions: summaries,
    };

    Ok(CommandResult::table(output)
        .with_title("User Sessions")
        .with_columns(vec![
            "session_id".to_string(),
            "ip_address".to_string(),
            "device_type".to_string(),
            "started_at".to_string(),
            "is_active".to_string(),
        ]))
}