Add a standalone codex-exec-server executable (#57589)

## What changed

Extract executor startup into `codex-exec-server-cli`, shared by `codex exec-server` and the new standalone binary. Preserve executor arguments, authentication, configuration overrides, and sandbox helper dispatch across both entry points.

Build the standalone binary with `cargo build -p codex-exec-server-cli --bin codex-exec-server` and run it with `codex-exec-server --listen stdio`.

## Testing

Add standalone CLI parsing and help coverage, plus an integration test for version reporting, stdio initialization, filesystem reads, process execution, and sandbox helper re-execution when supported.

GitOrigin-RevId: ab3a81c6b91b6f45e4d72d8add2e01af8372e97f
This commit is contained in:
Dmitriy Kovalenko
2026-10-27 23:13:53 +00:00
committed by copyberry
parent 37f199dab1
commit a9ea49e78b
25 changed files with 1090 additions and 579 deletions
@@ -0,0 +1,33 @@
#![cfg(test)]
use std::time::Duration;
use super::ShutdownBehavior;
use super::run_until_shutdown_with_signals;
#[tokio::test]
async fn parent_disconnect_still_stops_executor_after_signal_listener_error() {
let (parent_sender, parent_receiver) = tokio::sync::oneshot::channel();
let (shutdown_sender, shutdown_receiver) = tokio::sync::oneshot::channel();
let run = async move {
let _ = shutdown_receiver.await;
Ok::<(), std::io::Error>(())
};
let task = tokio::spawn(run_until_shutdown_with_signals(
run,
async move {
let _ = parent_receiver.await;
},
std::future::ready(Err(std::io::Error::other("signal listener failed"))),
ShutdownBehavior::Graceful(shutdown_sender),
));
tokio::task::yield_now().await;
parent_sender.send(()).expect("parent lifetime receiver");
tokio::time::timeout(Duration::from_secs(1), task)
.await
.expect("parent disconnect should stop the executor")
.expect("shutdown task should not panic")
.expect("executor should shut down successfully");
}