cli: proper clap subcommands for daemon + expanded help
Convert daemon from hand-rolled string dispatch to proper clap Subcommand enum with typed args. Add custom top-level help that expands nested subcommands (same pattern as bcachefs-tools), so `poc-memory --help` shows full paths like `agent daemon run`.
This commit is contained in:
parent
bcf13c564a
commit
c22a7a72e1
1 changed files with 87 additions and 33 deletions
|
|
@ -408,15 +408,42 @@ enum GraphCmd {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
enum DaemonCmd {
|
||||||
|
/// Start the daemon (default)
|
||||||
|
Start,
|
||||||
|
/// Show daemon status
|
||||||
|
Status,
|
||||||
|
/// Show daemon log
|
||||||
|
Log {
|
||||||
|
/// Job name to filter by
|
||||||
|
job: Option<String>,
|
||||||
|
/// Number of lines to show
|
||||||
|
#[arg(long, default_value_t = 20)]
|
||||||
|
lines: usize,
|
||||||
|
},
|
||||||
|
/// Install systemd service
|
||||||
|
Install,
|
||||||
|
/// Trigger consolidation via daemon
|
||||||
|
Consolidate,
|
||||||
|
/// Run an agent via the daemon
|
||||||
|
Run {
|
||||||
|
/// Agent name (e.g. organize, replay, linker)
|
||||||
|
#[arg(default_value = "replay")]
|
||||||
|
agent: String,
|
||||||
|
/// Batch size
|
||||||
|
#[arg(default_value_t = 1)]
|
||||||
|
count: usize,
|
||||||
|
},
|
||||||
|
/// Interactive TUI
|
||||||
|
Tui,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
enum AgentCmd {
|
enum AgentCmd {
|
||||||
/// Background job daemon
|
/// Background job daemon
|
||||||
Daemon {
|
#[command(subcommand)]
|
||||||
/// Subcommand: status, log, install
|
Daemon(DaemonCmd),
|
||||||
sub: Option<String>,
|
|
||||||
/// Additional arguments
|
|
||||||
args: Vec<String>,
|
|
||||||
},
|
|
||||||
/// Run knowledge agents to convergence
|
/// Run knowledge agents to convergence
|
||||||
#[command(name = "knowledge-loop")]
|
#[command(name = "knowledge-loop")]
|
||||||
KnowledgeLoop {
|
KnowledgeLoop {
|
||||||
|
|
@ -596,7 +623,52 @@ enum DigestLevel {
|
||||||
Auto,
|
Auto,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Print help with subcommands expanded to show nested commands.
|
||||||
|
fn print_help() {
|
||||||
|
use clap::CommandFactory;
|
||||||
|
let cmd = Cli::command();
|
||||||
|
|
||||||
|
println!("poc-memory - graph-structured memory store");
|
||||||
|
println!("usage: poc-memory <command> [<args>]\n");
|
||||||
|
|
||||||
|
for sub in cmd.get_subcommands() {
|
||||||
|
if sub.get_name() == "help" { continue }
|
||||||
|
let children: Vec<_> = sub.get_subcommands()
|
||||||
|
.filter(|c| c.get_name() != "help")
|
||||||
|
.collect();
|
||||||
|
if !children.is_empty() {
|
||||||
|
for child in &children {
|
||||||
|
let about = child.get_about().map(|s| s.to_string()).unwrap_or_default();
|
||||||
|
let full = format!("{} {}", sub.get_name(), child.get_name());
|
||||||
|
// Recurse one more level for daemon subcommands etc.
|
||||||
|
let grandchildren: Vec<_> = child.get_subcommands()
|
||||||
|
.filter(|c| c.get_name() != "help")
|
||||||
|
.collect();
|
||||||
|
if !grandchildren.is_empty() {
|
||||||
|
for gc in grandchildren {
|
||||||
|
let gc_about = gc.get_about().map(|s| s.to_string()).unwrap_or_default();
|
||||||
|
let gc_full = format!("{} {}", full, gc.get_name());
|
||||||
|
println!(" {:<34}{gc_about}", gc_full);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!(" {:<34}{about}", full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let about = sub.get_about().map(|s| s.to_string()).unwrap_or_default();
|
||||||
|
println!(" {:<34}{about}", sub.get_name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// Handle --help ourselves for expanded subcommand display
|
||||||
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
if args.len() <= 1 || args.iter().any(|a| a == "--help" || a == "-h") && args.len() == 2 {
|
||||||
|
print_help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
let result = match cli.command {
|
let result = match cli.command {
|
||||||
|
|
@ -660,7 +732,7 @@ fn main() {
|
||||||
|
|
||||||
// Agent
|
// Agent
|
||||||
Command::Agent(sub) => match sub {
|
Command::Agent(sub) => match sub {
|
||||||
AgentCmd::Daemon { sub, args } => cmd_daemon(sub.as_deref(), &args),
|
AgentCmd::Daemon(sub) => cmd_daemon(sub),
|
||||||
AgentCmd::KnowledgeLoop { max_cycles, batch_size, window, max_depth }
|
AgentCmd::KnowledgeLoop { max_cycles, batch_size, window, max_depth }
|
||||||
=> cmd_knowledge_loop(max_cycles, batch_size, window, max_depth),
|
=> cmd_knowledge_loop(max_cycles, batch_size, window, max_depth),
|
||||||
AgentCmd::ConsolidateBatch { count, auto, agent }
|
AgentCmd::ConsolidateBatch { count, auto, agent }
|
||||||
|
|
@ -2681,33 +2753,15 @@ fn cmd_lookups(date: Option<&str>) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd_daemon(sub: Option<&str>, args: &[String]) -> Result<(), String> {
|
fn cmd_daemon(sub: DaemonCmd) -> Result<(), String> {
|
||||||
match sub {
|
match sub {
|
||||||
None => daemon::run_daemon(),
|
DaemonCmd::Start => daemon::run_daemon(),
|
||||||
Some("status") => daemon::show_status(),
|
DaemonCmd::Status => daemon::show_status(),
|
||||||
Some("log") => {
|
DaemonCmd::Log { job, lines } => daemon::show_log(job.as_deref(), lines),
|
||||||
let (job, lines) = match args.first() {
|
DaemonCmd::Install => daemon::install_service(),
|
||||||
None => (None, 20),
|
DaemonCmd::Consolidate => daemon::rpc_consolidate(),
|
||||||
Some(s) => {
|
DaemonCmd::Run { agent, count } => daemon::rpc_run_agent(&agent, count),
|
||||||
if let Ok(n) = s.parse::<usize>() {
|
DaemonCmd::Tui => tui::run_tui(),
|
||||||
(None, n)
|
|
||||||
} else {
|
|
||||||
let n = args.get(1).and_then(|s| s.parse().ok()).unwrap_or(20);
|
|
||||||
(Some(s.as_str()), n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
daemon::show_log(job, lines)
|
|
||||||
}
|
|
||||||
Some("install") => daemon::install_service(),
|
|
||||||
Some("consolidate") => daemon::rpc_consolidate(),
|
|
||||||
Some("run-agent") | Some("run") => {
|
|
||||||
let agent = args.first().map(|s| s.as_str()).unwrap_or("replay");
|
|
||||||
let count: usize = args.get(1).and_then(|s| s.parse().ok()).unwrap_or(1);
|
|
||||||
daemon::rpc_run_agent(agent, count)
|
|
||||||
}
|
|
||||||
Some("tui") => tui::run_tui(),
|
|
||||||
Some(other) => Err(format!("unknown daemon subcommand: {}", other)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue