agent-tools-interface 0.7.11

Agent Tools Interface — secure CLI for AI agent tool execution
Documentation
use crate::core::audit;
use crate::{AuditCommands, Cli, OutputFormat};

pub fn execute(cli: &Cli, subcmd: &AuditCommands) -> Result<(), Box<dyn std::error::Error>> {
    match subcmd {
        AuditCommands::Tail { n } => tail(cli, *n),
        AuditCommands::Search { tool, since } => search(cli, tool.as_deref(), since.as_deref()),
    }
}

fn tail(cli: &Cli, n: usize) -> Result<(), Box<dyn std::error::Error>> {
    let entries = audit::tail(n)?;
    if entries.is_empty() {
        tracing::info!("no audit entries found");
        return Ok(());
    }
    output_entries(cli, &entries);
    Ok(())
}

fn search(
    cli: &Cli,
    tool: Option<&str>,
    since: Option<&str>,
) -> Result<(), Box<dyn std::error::Error>> {
    let entries = audit::search(tool, since)?;
    if entries.is_empty() {
        tracing::info!("no matching audit entries found");
        return Ok(());
    }
    tracing::info!(count = entries.len(), "found audit entries");
    output_entries(cli, &entries);
    Ok(())
}

fn output_entries(cli: &Cli, entries: &[audit::AuditEntry]) {
    match cli.output {
        OutputFormat::Json => {
            let json = serde_json::to_string(&entries).unwrap_or_default();
            println!("{json}");
        }
        _ => {
            for entry in entries {
                let status_marker = if entry.status == audit::AuditStatus::Ok {
                    "OK"
                } else {
                    "ERR"
                };
                let error_info = entry.error.as_deref().unwrap_or("");
                println!(
                    "{} [{}] {} ({}ms) agent={} {}",
                    entry.ts,
                    status_marker,
                    entry.tool,
                    entry.duration_ms,
                    entry.agent_sub,
                    error_info
                );
            }
        }
    }
}