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