use anyhow::Result;
use clap::ArgMatches;
use dakera_client::DakeraClient;
use serde::Serialize;
use crate::output;
use crate::OutputFormat;
#[derive(Debug, Serialize)]
pub struct AgentRow {
pub agent_id: String,
pub memory_count: i64,
pub session_count: i64,
pub active_sessions: i64,
}
#[derive(Debug, Serialize)]
pub struct AgentMemoryRow {
pub id: String,
pub content: String,
pub memory_type: String,
pub importance: f32,
}
#[derive(Debug, Serialize)]
pub struct AgentSessionRow {
pub id: String,
pub started_at: u64,
pub ended_at: String,
}
pub async fn execute(url: &str, matches: &ArgMatches, format: OutputFormat) -> Result<()> {
let client = DakeraClient::new(url)?;
match matches.subcommand() {
Some(("list", _)) => {
let agents = client.list_agents().await?;
if agents.is_empty() {
output::info("No agents found");
} else {
let rows: Vec<AgentRow> = agents
.into_iter()
.map(|a| AgentRow {
agent_id: a.agent_id,
memory_count: a.memory_count,
session_count: a.session_count,
active_sessions: a.active_sessions,
})
.collect();
output::print_data(&rows, format);
}
}
Some(("memories", sub_matches)) => {
let agent_id = sub_matches.get_one::<String>("agent_id").unwrap();
let memory_type = sub_matches.get_one::<String>("type").map(|s| s.as_str());
let limit = sub_matches.get_one::<u32>("limit").copied();
let memories = client.agent_memories(agent_id, memory_type, limit).await?;
if memories.is_empty() {
output::info(&format!("No memories found for agent '{}'", agent_id));
} else {
output::info(&format!(
"Found {} memories for agent '{}'",
memories.len(),
agent_id
));
let rows: Vec<AgentMemoryRow> = memories
.into_iter()
.map(|m| AgentMemoryRow {
id: m.id,
content: m.content,
memory_type: format!("{:?}", m.memory_type),
importance: m.importance,
})
.collect();
output::print_data(&rows, format);
}
}
Some(("stats", sub_matches)) => {
let agent_id = sub_matches.get_one::<String>("agent_id").unwrap();
let stats = client.agent_stats(agent_id).await?;
let pairs = [
("Agent ID", stats.agent_id),
("Total Memories", stats.total_memories.to_string()),
("Total Sessions", stats.total_sessions.to_string()),
("Active Sessions", stats.active_sessions.to_string()),
(
"Avg Importance",
stats
.avg_importance
.map(|v| format!("{:.3}", v))
.unwrap_or_else(|| "-".to_string()),
),
(
"Oldest Memory",
stats.oldest_memory_at.unwrap_or_else(|| "-".to_string()),
),
(
"Newest Memory",
stats.newest_memory_at.unwrap_or_else(|| "-".to_string()),
),
];
output::print_kv(
&pairs
.iter()
.map(|(k, v)| (*k, v.clone()))
.collect::<Vec<_>>(),
format,
);
if !stats.memories_by_type.is_empty() {
println!();
output::info("Memories by type:");
for (mem_type, count) in &stats.memories_by_type {
println!(" {}: {}", mem_type, count);
}
}
}
Some(("sessions", sub_matches)) => {
let agent_id = sub_matches.get_one::<String>("agent_id").unwrap();
let active_only = sub_matches.get_flag("active-only");
let limit = sub_matches.get_one::<u32>("limit").copied();
let active_filter = if active_only { Some(true) } else { None };
let sessions = client
.agent_sessions(agent_id, active_filter, limit)
.await?;
if sessions.is_empty() {
output::info(&format!("No sessions found for agent '{}'", agent_id));
} else {
output::info(&format!(
"Found {} sessions for agent '{}'",
sessions.len(),
agent_id
));
let rows: Vec<AgentSessionRow> = sessions
.into_iter()
.map(|s| AgentSessionRow {
id: s.id,
started_at: s.started_at,
ended_at: s
.ended_at
.map(|t| t.to_string())
.unwrap_or_else(|| "active".to_string()),
})
.collect();
output::print_data(&rows, format);
}
}
_ => {
output::error("Unknown agent subcommand. Use --help for usage.");
std::process::exit(1);
}
}
Ok(())
}