## Why `codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs` previously located `codex-execve-wrapper` by scanning `PATH` and sibling directories. That lookup is brittle and can select the wrong binary when the runtime environment differs from startup assumptions. We already pass `codex-linux-sandbox` from `codex-arg0`; `codex-execve-wrapper` should use the same startup-driven path plumbing. ## What changed - Introduced `Arg0DispatchPaths` in `codex-arg0` to carry both helper executable paths: - `codex_linux_sandbox_exe` - `main_execve_wrapper_exe` - Updated `arg0_dispatch_or_else()` to pass `Arg0DispatchPaths` to top-level binaries and preserve helper paths created in `prepend_path_entry_for_codex_aliases()`. - Threaded `Arg0DispatchPaths` through entrypoints in `cli`, `exec`, `tui`, `app-server`, and `mcp-server`. - Added `main_execve_wrapper_exe` to core configuration plumbing (`Config`, `ConfigOverrides`, and `SessionServices`). - Updated zsh-fork shell escalation to consume the configured `main_execve_wrapper_exe` and removed path-sniffing fallback logic. - Updated app-server config reload paths so reloaded configs keep the same startup-provided helper executable paths. ## References - [`Arg0DispatchPaths` definition](e355b43d5c/codex-rs/arg0/src/lib.rs (L20-L24)) - [`arg0_dispatch_or_else()` forwarding both paths](e355b43d5c/codex-rs/arg0/src/lib.rs (L145-L176)) - [zsh-fork escalation using configured wrapper path](e355b43d5c/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs (L109-L150)) ## Testing - `cargo check -p codex-arg0 -p codex-core -p codex-exec -p codex-tui -p codex-mcp-server -p codex-app-server` - `cargo test -p codex-arg0` - `cargo test -p codex-core tools::runtimes:🐚:unix_escalation:: -- --nocapture`
82 lines
2.5 KiB
Rust
82 lines
2.5 KiB
Rust
//! Entry-point for the `codex-exec` binary.
|
|
//!
|
|
//! When this CLI is invoked normally, it parses the standard `codex-exec` CLI
|
|
//! options and launches the non-interactive Codex agent. However, if it is
|
|
//! invoked with arg0 as `codex-linux-sandbox`, we instead treat the invocation
|
|
//! as a request to run the logic for the standalone `codex-linux-sandbox`
|
|
//! executable (i.e., parse any -s args and then run a *sandboxed* command under
|
|
//! Landlock + seccomp.
|
|
//!
|
|
//! This allows us to ship a completely separate set of functionality as part
|
|
//! of the `codex-exec` binary.
|
|
use clap::Parser;
|
|
use codex_arg0::Arg0DispatchPaths;
|
|
use codex_arg0::arg0_dispatch_or_else;
|
|
use codex_exec::Cli;
|
|
use codex_exec::run_main;
|
|
use codex_utils_cli::CliConfigOverrides;
|
|
|
|
#[derive(Parser, Debug)]
|
|
struct TopCli {
|
|
#[clap(flatten)]
|
|
config_overrides: CliConfigOverrides,
|
|
|
|
#[clap(flatten)]
|
|
inner: Cli,
|
|
}
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {
|
|
let top_cli = TopCli::parse();
|
|
// Merge root-level overrides into inner CLI struct so downstream logic remains unchanged.
|
|
let mut inner = top_cli.inner;
|
|
inner
|
|
.config_overrides
|
|
.raw_overrides
|
|
.splice(0..0, top_cli.config_overrides.raw_overrides);
|
|
|
|
run_main(inner, arg0_paths).await?;
|
|
Ok(())
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn top_cli_parses_resume_prompt_after_config_flag() {
|
|
const PROMPT: &str = "echo resume-with-global-flags-after-subcommand";
|
|
let cli = TopCli::parse_from([
|
|
"codex-exec",
|
|
"resume",
|
|
"--last",
|
|
"--json",
|
|
"--model",
|
|
"gpt-5.2-codex",
|
|
"--config",
|
|
"reasoning_level=xhigh",
|
|
"--dangerously-bypass-approvals-and-sandbox",
|
|
"--skip-git-repo-check",
|
|
PROMPT,
|
|
]);
|
|
|
|
let Some(codex_exec::Command::Resume(args)) = cli.inner.command else {
|
|
panic!("expected resume command");
|
|
};
|
|
let effective_prompt = args.prompt.clone().or_else(|| {
|
|
if args.last {
|
|
args.session_id.clone()
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
assert_eq!(effective_prompt.as_deref(), Some(PROMPT));
|
|
assert_eq!(cli.config_overrides.raw_overrides.len(), 1);
|
|
assert_eq!(
|
|
cli.config_overrides.raw_overrides[0],
|
|
"reasoning_level=xhigh"
|
|
);
|
|
}
|
|
}
|