feat(headless): add --once flag for single-cycle multi-agent execution
This commit is contained in:
@@ -12,6 +12,9 @@ pub fn run(config_or_task: &str, cwd_override: Option<&str>, name_override: Opti
|
||||
let _ = std::fs::remove_dir_all(STATE_DIR);
|
||||
create_state_dir();
|
||||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let once = args.iter().any(|a| a == "--once");
|
||||
|
||||
let is_multi = config_or_task.ends_with(".json") || std::path::Path::new(config_or_task).is_dir();
|
||||
let (configs, interval) = if is_multi {
|
||||
let loaded = config::load_full(config_or_task);
|
||||
@@ -34,6 +37,42 @@ pub fn run(config_or_task: &str, cwd_override: Option<&str>, name_override: Opti
|
||||
return run_once(&configs);
|
||||
}
|
||||
|
||||
// --once: run multi-agent once with AI integration, no loop
|
||||
if once {
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
setup_ctrlc(running.clone());
|
||||
let agents = spawn_and_wait(&configs, &running);
|
||||
if agents.is_empty() { return Ok(()); }
|
||||
write_state(&agents);
|
||||
|
||||
if agents.len() > 1 {
|
||||
eprintln!("\n ◐ AI integrating...");
|
||||
match integrate_results(&agents, "", 1) {
|
||||
Ok(d) => {
|
||||
let data = serde_json::json!({
|
||||
"cycle": 1,
|
||||
"agents": agents.iter().map(|a| a.to_ai_json()).collect::<Vec<_>>(),
|
||||
"decision": &d,
|
||||
});
|
||||
atomic_write(
|
||||
&format!("{STATE_DIR}/decision.json"),
|
||||
serde_json::to_string_pretty(&data).unwrap_or_default().as_bytes(),
|
||||
);
|
||||
eprintln!(" ✓ Done\n");
|
||||
println!("{d}");
|
||||
}
|
||||
Err(e) => eprintln!(" ✗ {e}"),
|
||||
}
|
||||
} else {
|
||||
println!("{}", strip_dir_listing(&agents[0].output));
|
||||
}
|
||||
|
||||
let all: Vec<usize> = (0..agents.len()).collect();
|
||||
let path = save_session(1, &agents, "", &all);
|
||||
eprintln!(" saved: {path}");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
setup_ctrlc(running.clone());
|
||||
|
||||
@@ -142,7 +181,49 @@ pub fn run(config_or_task: &str, cwd_override: Option<&str>, name_override: Opti
|
||||
pub fn run_preset(preset_name: &str) -> Result<(), String> {
|
||||
let configs = config::preset(preset_name)
|
||||
.ok_or_else(|| format!("unknown preset: {preset_name}"))?;
|
||||
let once = std::env::args().any(|a| a == "--once");
|
||||
if once {
|
||||
run_once_multi(configs)
|
||||
} else {
|
||||
run_with_configs(configs)
|
||||
}
|
||||
}
|
||||
|
||||
fn run_once_multi(configs: Vec<config::AgentConfig>) -> Result<(), String> {
|
||||
let _ = std::fs::remove_dir_all(STATE_DIR);
|
||||
create_state_dir();
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
setup_ctrlc(running.clone());
|
||||
let agents = spawn_and_wait(&configs, &running);
|
||||
if agents.is_empty() { return Ok(()); }
|
||||
write_state(&agents);
|
||||
|
||||
if agents.len() > 1 {
|
||||
eprintln!("\n ◐ AI integrating...");
|
||||
match integrate_results(&agents, "", 1) {
|
||||
Ok(d) => {
|
||||
let data = serde_json::json!({
|
||||
"cycle": 1,
|
||||
"agents": agents.iter().map(|a| a.to_ai_json()).collect::<Vec<_>>(),
|
||||
"decision": &d,
|
||||
});
|
||||
atomic_write(
|
||||
&format!("{STATE_DIR}/decision.json"),
|
||||
serde_json::to_string_pretty(&data).unwrap_or_default().as_bytes(),
|
||||
);
|
||||
eprintln!(" ✓ Done\n");
|
||||
println!("{d}");
|
||||
}
|
||||
Err(e) => eprintln!(" ✗ {e}"),
|
||||
}
|
||||
} else {
|
||||
println!("{}", strip_dir_listing(&agents[0].output));
|
||||
}
|
||||
|
||||
let all: Vec<usize> = (0..agents.len()).collect();
|
||||
let path = save_session(1, &agents, "", &all);
|
||||
eprintln!(" saved: {path}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_with_configs(configs: Vec<config::AgentConfig>) -> Result<(), String> {
|
||||
|
||||
Reference in New Issue
Block a user