// cli/agent.rs — agent subcommand handlers use crate::store; use crate::store::StoreView; pub fn cmd_consolidate_batch(count: usize, auto: bool, agent: Option) -> Result<(), String> { let store = store::Store::load()?; if let Some(agent_name) = agent { let batch = crate::agents::prompts::agent_prompt(&store, &agent_name, count)?; println!("{}", batch.prompt); Ok(()) } else { crate::agents::prompts::consolidation_batch(&store, count, auto) } } pub fn cmd_replay_queue(count: usize) -> Result<(), String> { let store = store::Store::load()?; let queue = crate::neuro::replay_queue(&store, count); println!("Replay queue ({} items):", queue.len()); for (i, item) in queue.iter().enumerate() { println!(" {:2}. [{:.3}] {:>10} {} (interval={}d, emotion={:.1}, spectral={:.1})", i + 1, item.priority, item.classification, item.key, item.interval_days, item.emotion, item.outlier_score); } Ok(()) } pub fn cmd_consolidate_session() -> Result<(), String> { let store = store::Store::load()?; let plan = crate::neuro::consolidation_plan(&store); println!("{}", crate::neuro::format_plan(&plan)); Ok(()) } pub fn cmd_consolidate_full() -> Result<(), String> { let mut store = store::Store::load()?; crate::consolidate::consolidate_full(&mut store) } pub fn cmd_digest_links(do_apply: bool) -> Result<(), String> { let store = store::Store::load()?; let links = crate::digest::parse_all_digest_links(&store); drop(store); println!("Found {} unique links from digest nodes", links.len()); if !do_apply { for (i, link) in links.iter().enumerate() { println!(" {:3}. {} → {}", i + 1, link.source, link.target); if !link.reason.is_empty() { println!(" ({})", &link.reason[..link.reason.len().min(80)]); } } println!("\nTo apply: poc-memory digest-links --apply"); return Ok(()); } let mut store = store::Store::load()?; let (applied, skipped, fallbacks) = crate::digest::apply_digest_links(&mut store, &links); println!("\nApplied: {} ({} file-level fallbacks) Skipped: {}", applied, fallbacks, skipped); Ok(()) } pub fn cmd_journal_enrich(jsonl_path: &str, entry_text: &str, grep_line: usize) -> Result<(), String> { if !std::path::Path::new(jsonl_path).is_file() { return Err(format!("JSONL not found: {}", jsonl_path)); } let mut store = store::Store::load()?; crate::enrich::journal_enrich(&mut store, jsonl_path, entry_text, grep_line) } pub fn cmd_apply_consolidation(do_apply: bool, report_file: Option<&str>) -> Result<(), String> { let mut store = store::Store::load()?; crate::consolidate::apply_consolidation(&mut store, do_apply, report_file) } pub fn cmd_knowledge_loop(max_cycles: usize, batch_size: usize, window: usize, max_depth: i32) -> Result<(), String> { let config = crate::knowledge::KnowledgeLoopConfig { max_cycles, batch_size, window, max_depth, ..Default::default() }; let results = crate::knowledge::run_knowledge_loop(&config)?; eprintln!("\nCompleted {} cycles, {} total actions applied", results.len(), results.iter().map(|r| r.total_applied).sum::()); Ok(()) } pub fn cmd_fact_mine(path: &str, batch: bool, dry_run: bool, output_file: Option<&str>, min_messages: usize) -> Result<(), String> { let p = std::path::Path::new(path); let paths: Vec = if batch { if !p.is_dir() { return Err(format!("Not a directory: {}", path)); } let mut files: Vec<_> = std::fs::read_dir(p) .map_err(|e| format!("read dir: {}", e))? .filter_map(|e| e.ok()) .map(|e| e.path()) .filter(|p| p.extension().map(|x| x == "jsonl").unwrap_or(false)) .collect(); files.sort(); eprintln!("Found {} transcripts", files.len()); files } else { vec![p.to_path_buf()] }; let path_refs: Vec<&std::path::Path> = paths.iter().map(|p| p.as_path()).collect(); let facts = crate::fact_mine::mine_batch(&path_refs, min_messages, dry_run)?; if !dry_run { let json = serde_json::to_string_pretty(&facts) .map_err(|e| format!("serialize: {}", e))?; if let Some(out) = output_file { std::fs::write(out, &json).map_err(|e| format!("write: {}", e))?; eprintln!("\nWrote {} facts to {}", facts.len(), out); } else { println!("{}", json); } } eprintln!("\nTotal: {} facts from {} transcripts", facts.len(), paths.len()); Ok(()) } pub fn cmd_fact_mine_store(path: &str) -> Result<(), String> { let path = std::path::Path::new(path); if !path.exists() { return Err(format!("File not found: {}", path.display())); } let count = crate::fact_mine::mine_and_store(path, None)?; eprintln!("Stored {} facts", count); Ok(()) }