Skip to main content

systemprompt_cli/commands/admin/agents/
logs.rs

1use std::path::PathBuf;
2
3use anyhow::{Context, Result};
4use clap::Args;
5
6use super::logs_db::execute_db_mode;
7use super::logs_disk::{execute_disk_mode, execute_follow_mode};
8use crate::CliConfig;
9use crate::interactive::Prompter;
10use crate::shared::CommandOutput;
11
12#[derive(Debug, Args)]
13pub struct LogsArgs {
14    #[arg(help = "Agent name (optional - shows all agent logs if not specified)")]
15    pub agent: Option<String>,
16
17    #[arg(
18        long,
19        short = 'n',
20        default_value = "50",
21        help = "Number of lines to show"
22    )]
23    pub lines: usize,
24
25    #[arg(long, short, help = "Follow log output continuously (disk only)")]
26    pub follow: bool,
27
28    #[arg(long, help = "Force reading from disk files instead of database")]
29    pub disk: bool,
30
31    #[arg(long, help = "Custom logs directory path")]
32    pub logs_dir: Option<String>,
33}
34
35pub(super) async fn execute(
36    args: LogsArgs,
37    prompter: &dyn Prompter,
38    config: &CliConfig,
39) -> Result<CommandOutput> {
40    let logs_path = match args.logs_dir.as_deref() {
41        Some(dir) => PathBuf::from(dir),
42        None => PathBuf::from(
43            systemprompt_models::Config::get()
44                .context("agent log directory requires an initialised profile")?
45                .logs_path(),
46        ),
47    };
48
49    if args.follow {
50        return execute_follow_mode(&args, prompter, config, &logs_path);
51    }
52
53    if args.disk {
54        return execute_disk_mode(&args, prompter, config, &logs_path);
55    }
56
57    match execute_db_mode(&args, config).await {
58        Ok(result) => Ok(result),
59        Err(e) => {
60            tracing::debug!(error = %e, "DB log query failed, falling back to disk");
61            execute_disk_mode(&args, prompter, config, &logs_path)
62        },
63    }
64}