mirror of
https://github.com/openai/codex.git
synced 2026-05-02 04:11:39 +03:00
adding best-of-n
This commit is contained in:
@@ -44,6 +44,11 @@ struct MultitoolCli {
|
||||
#[arg(long = "automerge", default_value_t = true, action = clap::ArgAction::Set)]
|
||||
pub automerge: bool,
|
||||
|
||||
/// Run the same --concurrent prompt N times in separate worktrees and keep them all.
|
||||
/// Intended to generate multiple candidate solutions without auto-merging.
|
||||
#[arg(long = "best-of-n", value_name = "N", default_value_t = 1)]
|
||||
pub best_of_n: usize,
|
||||
|
||||
#[clap(flatten)]
|
||||
interactive: TuiCli,
|
||||
|
||||
@@ -134,16 +139,81 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
eprintln!("--concurrent cannot be used together with a subcommand");
|
||||
std::process::exit(2);
|
||||
}
|
||||
concurrent::run_concurrent_flow(
|
||||
prompt,
|
||||
cli.config_overrides,
|
||||
codex_linux_sandbox_exe,
|
||||
cli.automerge,
|
||||
)
|
||||
.await?;
|
||||
let runs = if cli.best_of_n == 0 { 1 } else { cli.best_of_n };
|
||||
if runs > 1 {
|
||||
println!(
|
||||
"Running best-of-n with {runs} runs; auto-merge will be disabled and worktrees kept."
|
||||
);
|
||||
|
||||
// Launch all runs concurrently and collect results as they finish.
|
||||
let mut join_set = tokio::task::JoinSet::new();
|
||||
for _ in 0..runs {
|
||||
let prompt = prompt.clone();
|
||||
let overrides = cli.config_overrides.clone();
|
||||
let sandbox = codex_linux_sandbox_exe.clone();
|
||||
join_set.spawn(async move {
|
||||
concurrent::run_concurrent_flow_quiet_no_automerge(prompt, overrides, sandbox)
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
let mut results: Vec<concurrent::ConcurrentRunResult> = Vec::with_capacity(runs);
|
||||
while let Some(join_result) = join_set.join_next().await {
|
||||
match join_result {
|
||||
Ok(Ok(res)) => {
|
||||
println!(
|
||||
"task finished for branch: {}\n, directory: {}",
|
||||
res.branch,
|
||||
res.worktree_dir.display()
|
||||
);
|
||||
results.push(res);
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
eprintln!("concurrent task failed: {err}");
|
||||
}
|
||||
Err(join_err) => {
|
||||
eprintln!("failed to join concurrent task: {join_err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nBest-of-n summary:");
|
||||
for r in &results {
|
||||
let status = match r.exec_exit_code {
|
||||
Some(0) => "OK",
|
||||
Some(_code) => "FAIL",
|
||||
None => "OK",
|
||||
};
|
||||
let log = r
|
||||
.log_file
|
||||
.as_ref()
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_else(|| "<no log>".to_string());
|
||||
println!(
|
||||
"[{status}] branch={} worktree={} log={}",
|
||||
r.branch,
|
||||
r.worktree_dir.display(),
|
||||
log
|
||||
);
|
||||
}
|
||||
} else {
|
||||
concurrent::run_concurrent_flow(
|
||||
prompt,
|
||||
cli.config_overrides,
|
||||
codex_linux_sandbox_exe,
|
||||
cli.automerge,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if cli.best_of_n > 1 {
|
||||
eprintln!("--best-of-n requires --concurrent <PROMPT>");
|
||||
std::process::exit(2);
|
||||
}
|
||||
|
||||
match cli.subcommand {
|
||||
None => {
|
||||
let mut tui_cli = cli.interactive;
|
||||
|
||||
Reference in New Issue
Block a user