diff --git a/src/headless.rs b/src/headless.rs index bc900eb..e56bac7 100644 --- a/src/headless.rs +++ b/src/headless.rs @@ -195,6 +195,10 @@ fn execute_once(configs: Vec) -> Result<(), String> { let all: Vec = (0..agents.len()).collect(); let path = save_session(1, &agents, &decision, &all); eprintln!(" saved: {path}"); + + // Write done marker for background monitoring + atomic_write(&format!("{STATE_DIR}/done"), b"1"); + Ok(()) } @@ -297,6 +301,7 @@ fn run_once(configs: &[config::AgentConfig]) -> Result<(), String> { return run_with_configs(next); } + atomic_write(&format!("{STATE_DIR}/done"), b"1"); Ok(()) } @@ -804,6 +809,32 @@ pub fn remember() { } } +/// Wait for background run to complete, then show summary. +pub fn wait_done() { + let done_path = format!("{STATE_DIR}/done"); + eprint!(" waiting..."); + loop { + if std::path::Path::new(&done_path).exists() { + eprintln!(" done"); + let _ = std::fs::remove_file(&done_path); + // Show compact summary + status(false); + if let Ok(content) = std::fs::read_to_string(format!("{STATE_DIR}/decision.json")) { + if let Ok(d) = serde_json::from_str::(&content) { + let text = d["decision"].as_str().unwrap_or(""); + let first: String = text.lines() + .filter(|l| !l.starts_with('#') && !l.is_empty()) + .take(3).collect::>().join("\n"); + if !first.is_empty() { println!("\n{first}"); } + } + } + return; + } + std::thread::sleep(std::time::Duration::from_millis(500)); + eprint!("."); + } +} + pub fn signal_next(save: Vec) { let save_val = if save.is_empty() { serde_json::json!(null) diff --git a/src/main.rs b/src/main.rs index 3c4d6b1..7e4ddcf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -120,6 +120,7 @@ fn main() { std::process::exit(1); } } + Some("wait") => aishell::headless::wait_done(), Some("next") => { let save: Vec = env::args().skip(2) .filter_map(|s| s.parse().ok())