feat: pass helper executable paths via Arg0DispatchPaths (#12719)
## 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`
This commit is contained in:
parent
448fb6ac22
commit
e88f74d140
19 changed files with 184 additions and 112 deletions
|
|
@ -168,6 +168,7 @@ use codex_app_server_protocol::WindowsSandboxSetupMode;
|
|||
use codex_app_server_protocol::WindowsSandboxSetupStartParams;
|
||||
use codex_app_server_protocol::WindowsSandboxSetupStartResponse;
|
||||
use codex_app_server_protocol::build_turns_from_rollout_items;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_backend_client::Client as BackendClient;
|
||||
use codex_chatgpt::connectors;
|
||||
use codex_cloud_requirements::cloud_requirements_loader;
|
||||
|
|
@ -338,7 +339,7 @@ pub(crate) struct CodexMessageProcessor {
|
|||
auth_manager: Arc<AuthManager>,
|
||||
thread_manager: Arc<ThreadManager>,
|
||||
outgoing: Arc<OutgoingMessageSender>,
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
config: Arc<Config>,
|
||||
single_client_mode: bool,
|
||||
cli_overrides: Vec<(String, TomlValue)>,
|
||||
|
|
@ -362,7 +363,7 @@ pub(crate) struct CodexMessageProcessorArgs {
|
|||
pub(crate) auth_manager: Arc<AuthManager>,
|
||||
pub(crate) thread_manager: Arc<ThreadManager>,
|
||||
pub(crate) outgoing: Arc<OutgoingMessageSender>,
|
||||
pub(crate) codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
pub(crate) arg0_paths: Arg0DispatchPaths,
|
||||
pub(crate) config: Arc<Config>,
|
||||
pub(crate) cli_overrides: Vec<(String, TomlValue)>,
|
||||
pub(crate) cloud_requirements: Arc<RwLock<CloudRequirementsLoader>>,
|
||||
|
|
@ -399,7 +400,7 @@ impl CodexMessageProcessor {
|
|||
auth_manager,
|
||||
thread_manager,
|
||||
outgoing,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
config,
|
||||
cli_overrides,
|
||||
cloud_requirements,
|
||||
|
|
@ -410,7 +411,7 @@ impl CodexMessageProcessor {
|
|||
auth_manager,
|
||||
thread_manager,
|
||||
outgoing: outgoing.clone(),
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
config,
|
||||
single_client_mode,
|
||||
cli_overrides,
|
||||
|
|
@ -426,7 +427,7 @@ impl CodexMessageProcessor {
|
|||
|
||||
async fn load_latest_config(&self) -> Result<Config, JSONRPCErrorError> {
|
||||
let cloud_requirements = self.current_cloud_requirements();
|
||||
codex_core::config::ConfigBuilder::default()
|
||||
let mut config = codex_core::config::ConfigBuilder::default()
|
||||
.cli_overrides(self.cli_overrides.clone())
|
||||
.cloud_requirements(cloud_requirements)
|
||||
.build()
|
||||
|
|
@ -435,7 +436,10 @@ impl CodexMessageProcessor {
|
|||
code: INTERNAL_ERROR_CODE,
|
||||
message: format!("failed to reload config: {err}"),
|
||||
data: None,
|
||||
})
|
||||
})?;
|
||||
config.codex_linux_sandbox_exe = self.arg0_paths.codex_linux_sandbox_exe.clone();
|
||||
config.main_execve_wrapper_exe = self.arg0_paths.main_execve_wrapper_exe.clone();
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn current_cloud_requirements(&self) -> CloudRequirementsLoader {
|
||||
|
|
@ -1792,7 +1796,7 @@ impl CodexMessageProcessor {
|
|||
None => self.config.permissions.sandbox_policy.get().clone(),
|
||||
};
|
||||
|
||||
let codex_linux_sandbox_exe = self.config.codex_linux_sandbox_exe.clone();
|
||||
let codex_linux_sandbox_exe = self.arg0_paths.codex_linux_sandbox_exe.clone();
|
||||
let outgoing = self.outgoing.clone();
|
||||
let request_for_task = request;
|
||||
let sandbox_cwd = self.config.cwd.clone();
|
||||
|
|
@ -1857,7 +1861,8 @@ impl CodexMessageProcessor {
|
|||
approval_policy,
|
||||
sandbox_mode,
|
||||
model_provider,
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(),
|
||||
codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
base_instructions,
|
||||
developer_instructions,
|
||||
compact_prompt,
|
||||
|
|
@ -2111,7 +2116,8 @@ impl CodexMessageProcessor {
|
|||
approval_policy: approval_policy
|
||||
.map(codex_app_server_protocol::AskForApproval::to_core),
|
||||
sandbox_mode: sandbox.map(SandboxMode::to_core),
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(),
|
||||
codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
base_instructions,
|
||||
developer_instructions,
|
||||
personality,
|
||||
|
|
@ -4325,7 +4331,8 @@ impl CodexMessageProcessor {
|
|||
approval_policy,
|
||||
sandbox_mode,
|
||||
model_provider,
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(),
|
||||
codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
base_instructions,
|
||||
developer_instructions,
|
||||
compact_prompt,
|
||||
|
|
@ -4336,7 +4343,8 @@ impl CodexMessageProcessor {
|
|||
}
|
||||
None => (
|
||||
ConfigOverrides {
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(),
|
||||
codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
|
|
@ -4520,7 +4528,8 @@ impl CodexMessageProcessor {
|
|||
approval_policy,
|
||||
sandbox_mode,
|
||||
model_provider,
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(),
|
||||
codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
base_instructions,
|
||||
developer_instructions,
|
||||
compact_prompt,
|
||||
|
|
@ -4532,7 +4541,8 @@ impl CodexMessageProcessor {
|
|||
}
|
||||
None => (
|
||||
ConfigOverrides {
|
||||
codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(),
|
||||
codex_linux_sandbox_exe: self.arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: self.arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
None,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![deny(clippy::print_stdout, clippy::print_stderr)]
|
||||
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_cloud_requirements::cloud_requirements_loader;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::config::Config;
|
||||
|
|
@ -12,7 +13,6 @@ use std::collections::HashMap;
|
|||
use std::collections::HashSet;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Result as IoResult;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
|
@ -291,13 +291,13 @@ fn log_format_from_env() -> LogFormat {
|
|||
}
|
||||
|
||||
pub async fn run_main(
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
cli_config_overrides: CliConfigOverrides,
|
||||
loader_overrides: LoaderOverrides,
|
||||
default_analytics_enabled: bool,
|
||||
) -> IoResult<()> {
|
||||
run_main_with_transport(
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
cli_config_overrides,
|
||||
loader_overrides,
|
||||
default_analytics_enabled,
|
||||
|
|
@ -307,7 +307,7 @@ pub async fn run_main(
|
|||
}
|
||||
|
||||
pub async fn run_main_with_transport(
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
cli_config_overrides: CliConfigOverrides,
|
||||
loader_overrides: LoaderOverrides,
|
||||
default_analytics_enabled: bool,
|
||||
|
|
@ -548,7 +548,7 @@ pub async fn run_main_with_transport(
|
|||
let loader_overrides = loader_overrides_for_config_api;
|
||||
let mut processor = MessageProcessor::new(MessageProcessorArgs {
|
||||
outgoing: outgoing_message_sender,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
config: Arc::new(config),
|
||||
single_client_mode,
|
||||
cli_overrides,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use clap::Parser;
|
||||
use codex_app_server::AppServerTransport;
|
||||
use codex_app_server::run_main_with_transport;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_arg0::arg0_dispatch_or_else;
|
||||
use codex_core::config_loader::LoaderOverrides;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
|
|
@ -23,7 +24,7 @@ struct AppServerArgs {
|
|||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
||||
arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {
|
||||
let args = AppServerArgs::parse();
|
||||
let managed_config_path = managed_config_path_from_debug_env();
|
||||
let loader_overrides = LoaderOverrides {
|
||||
|
|
@ -33,7 +34,7 @@ fn main() -> anyhow::Result<()> {
|
|||
let transport = args.listen;
|
||||
|
||||
run_main_with_transport(
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
CliConfigOverrides::default(),
|
||||
loader_overrides,
|
||||
false,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
|
@ -32,6 +31,7 @@ use codex_app_server_protocol::JSONRPCResponse;
|
|||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_app_server_protocol::ServerRequestPayload;
|
||||
use codex_app_server_protocol::experimental_required_message;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::ThreadManager;
|
||||
use codex_core::auth::ExternalAuthRefreshContext;
|
||||
|
|
@ -139,7 +139,7 @@ pub(crate) struct ConnectionSessionState {
|
|||
|
||||
pub(crate) struct MessageProcessorArgs {
|
||||
pub(crate) outgoing: Arc<OutgoingMessageSender>,
|
||||
pub(crate) codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
pub(crate) arg0_paths: Arg0DispatchPaths,
|
||||
pub(crate) config: Arc<Config>,
|
||||
pub(crate) single_client_mode: bool,
|
||||
pub(crate) cli_overrides: Vec<(String, TomlValue)>,
|
||||
|
|
@ -155,7 +155,7 @@ impl MessageProcessor {
|
|||
pub(crate) fn new(args: MessageProcessorArgs) -> Self {
|
||||
let MessageProcessorArgs {
|
||||
outgoing,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
config,
|
||||
single_client_mode,
|
||||
cli_overrides,
|
||||
|
|
@ -184,7 +184,7 @@ impl MessageProcessor {
|
|||
auth_manager,
|
||||
thread_manager,
|
||||
outgoing: outgoing.clone(),
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
config: Arc::clone(&config),
|
||||
cli_overrides: cli_overrides.clone(),
|
||||
cloud_requirements: cloud_requirements.clone(),
|
||||
|
|
|
|||
|
|
@ -17,19 +17,31 @@ const EXECVE_WRAPPER_ARG0: &str = "codex-execve-wrapper";
|
|||
const LOCK_FILENAME: &str = ".lock";
|
||||
const TOKIO_WORKER_STACK_SIZE_BYTES: usize = 16 * 1024 * 1024;
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct Arg0DispatchPaths {
|
||||
pub codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
pub main_execve_wrapper_exe: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Keeps the per-session PATH entry alive and locked for the process lifetime.
|
||||
pub struct Arg0PathEntryGuard {
|
||||
_temp_dir: TempDir,
|
||||
_lock_file: File,
|
||||
paths: Arg0DispatchPaths,
|
||||
}
|
||||
|
||||
impl Arg0PathEntryGuard {
|
||||
fn new(temp_dir: TempDir, lock_file: File) -> Self {
|
||||
fn new(temp_dir: TempDir, lock_file: File, paths: Arg0DispatchPaths) -> Self {
|
||||
Self {
|
||||
_temp_dir: temp_dir,
|
||||
_lock_file: lock_file,
|
||||
paths,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn paths(&self) -> &Arg0DispatchPaths {
|
||||
&self.paths
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg0_dispatch() -> Option<Arg0PathEntryGuard> {
|
||||
|
|
@ -124,33 +136,43 @@ pub fn arg0_dispatch() -> Option<Arg0PathEntryGuard> {
|
|||
/// 3. Derive the path to the current executable (so children can re-invoke the
|
||||
/// sandbox) when running on Linux.
|
||||
/// 4. Execute the provided async `main_fn` inside that runtime, forwarding any
|
||||
/// error. Note that `main_fn` receives `codex_linux_sandbox_exe:
|
||||
/// Option<PathBuf>`, as an argument, which is generally needed as part of
|
||||
/// constructing [`codex_core::config::Config`].
|
||||
/// error. Note that `main_fn` receives [`Arg0DispatchPaths`], which
|
||||
/// contains the helper executable paths needed to construct
|
||||
/// [`codex_core::config::Config`].
|
||||
///
|
||||
/// This function should be used to wrap any `main()` function in binary crates
|
||||
/// in this workspace that depends on these helper CLIs.
|
||||
pub fn arg0_dispatch_or_else<F, Fut>(main_fn: F) -> anyhow::Result<()>
|
||||
where
|
||||
F: FnOnce(Option<PathBuf>) -> Fut,
|
||||
F: FnOnce(Arg0DispatchPaths) -> Fut,
|
||||
Fut: Future<Output = anyhow::Result<()>>,
|
||||
{
|
||||
// Retain the TempDir so it exists for the lifetime of the invocation of
|
||||
// this executable. Admittedly, we could invoke `keep()` on it, but it
|
||||
// would be nice to avoid leaving temporary directories behind, if possible.
|
||||
let _path_entry = arg0_dispatch();
|
||||
let path_entry = arg0_dispatch();
|
||||
|
||||
// Regular invocation – create a Tokio runtime and execute the provided
|
||||
// async entry-point.
|
||||
let runtime = build_runtime()?;
|
||||
runtime.block_on(async move {
|
||||
let codex_linux_sandbox_exe: Option<PathBuf> = if cfg!(target_os = "linux") {
|
||||
std::env::current_exe().ok()
|
||||
} else {
|
||||
None
|
||||
let current_exe = std::env::current_exe().ok();
|
||||
let paths = Arg0DispatchPaths {
|
||||
codex_linux_sandbox_exe: if cfg!(target_os = "linux") {
|
||||
current_exe.or_else(|| {
|
||||
path_entry
|
||||
.as_ref()
|
||||
.and_then(|path_entry| path_entry.paths().codex_linux_sandbox_exe.clone())
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
main_execve_wrapper_exe: path_entry
|
||||
.as_ref()
|
||||
.and_then(|path_entry| path_entry.paths().main_execve_wrapper_exe.clone()),
|
||||
};
|
||||
|
||||
main_fn(codex_linux_sandbox_exe).await
|
||||
main_fn(paths).await
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -301,7 +323,30 @@ pub fn prepend_path_entry_for_codex_aliases() -> std::io::Result<Arg0PathEntryGu
|
|||
std::env::set_var("PATH", updated_path_env_var);
|
||||
}
|
||||
|
||||
Ok(Arg0PathEntryGuard::new(temp_dir, lock_file))
|
||||
let paths = Arg0DispatchPaths {
|
||||
codex_linux_sandbox_exe: {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
Some(path.join(LINUX_SANDBOX_ARG0))
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
None
|
||||
}
|
||||
},
|
||||
main_execve_wrapper_exe: {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
Some(path.join(EXECVE_WRAPPER_ARG0))
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
None
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Ok(Arg0PathEntryGuard::new(temp_dir, lock_file, paths))
|
||||
}
|
||||
|
||||
fn janitor_cleanup(temp_root: &Path) -> std::io::Result<()> {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use clap::CommandFactory;
|
|||
use clap::Parser;
|
||||
use clap_complete::Shell;
|
||||
use clap_complete::generate;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_arg0::arg0_dispatch_or_else;
|
||||
use codex_chatgpt::apply_command::ApplyCommand;
|
||||
use codex_chatgpt::apply_command::run_apply_command;
|
||||
|
|
@ -543,13 +544,13 @@ fn stage_str(stage: codex_core::features::Stage) -> &'static str {
|
|||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
||||
cli_main(codex_linux_sandbox_exe).await?;
|
||||
arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {
|
||||
cli_main(arg0_paths).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()> {
|
||||
async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
|
||||
let MultitoolCli {
|
||||
config_overrides: mut root_config_overrides,
|
||||
feature_toggles,
|
||||
|
|
@ -567,7 +568,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
&mut interactive.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
let exit_info = run_interactive_tui(interactive, codex_linux_sandbox_exe).await?;
|
||||
let exit_info = run_interactive_tui(interactive, arg0_paths.clone()).await?;
|
||||
handle_app_exit(exit_info)?;
|
||||
}
|
||||
Some(Subcommand::Exec(mut exec_cli)) => {
|
||||
|
|
@ -575,7 +576,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
&mut exec_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_exec::run_main(exec_cli, codex_linux_sandbox_exe).await?;
|
||||
codex_exec::run_main(exec_cli, arg0_paths.clone()).await?;
|
||||
}
|
||||
Some(Subcommand::Review(review_args)) => {
|
||||
let mut exec_cli = ExecCli::try_parse_from(["codex", "exec"])?;
|
||||
|
|
@ -584,10 +585,10 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
&mut exec_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_exec::run_main(exec_cli, codex_linux_sandbox_exe).await?;
|
||||
codex_exec::run_main(exec_cli, arg0_paths.clone()).await?;
|
||||
}
|
||||
Some(Subcommand::McpServer) => {
|
||||
codex_mcp_server::run_main(codex_linux_sandbox_exe, root_config_overrides).await?;
|
||||
codex_mcp_server::run_main(arg0_paths.clone(), root_config_overrides).await?;
|
||||
}
|
||||
Some(Subcommand::Mcp(mut mcp_cli)) => {
|
||||
// Propagate any root-level config overrides (e.g. `-c key=value`).
|
||||
|
|
@ -598,7 +599,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
None => {
|
||||
let transport = app_server_cli.listen;
|
||||
codex_app_server::run_main_with_transport(
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths.clone(),
|
||||
root_config_overrides,
|
||||
codex_core::config_loader::LoaderOverrides::default(),
|
||||
app_server_cli.analytics_default_enabled,
|
||||
|
|
@ -642,7 +643,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
all,
|
||||
config_overrides,
|
||||
);
|
||||
let exit_info = run_interactive_tui(interactive, codex_linux_sandbox_exe).await?;
|
||||
let exit_info = run_interactive_tui(interactive, arg0_paths.clone()).await?;
|
||||
handle_app_exit(exit_info)?;
|
||||
}
|
||||
Some(Subcommand::Fork(ForkCommand {
|
||||
|
|
@ -659,7 +660,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
all,
|
||||
config_overrides,
|
||||
);
|
||||
let exit_info = run_interactive_tui(interactive, codex_linux_sandbox_exe).await?;
|
||||
let exit_info = run_interactive_tui(interactive, arg0_paths.clone()).await?;
|
||||
handle_app_exit(exit_info)?;
|
||||
}
|
||||
Some(Subcommand::Login(mut login_cli)) => {
|
||||
|
|
@ -708,7 +709,8 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
&mut cloud_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_cloud_tasks::run_main(cloud_cli, codex_linux_sandbox_exe).await?;
|
||||
codex_cloud_tasks::run_main(cloud_cli, arg0_paths.codex_linux_sandbox_exe.clone())
|
||||
.await?;
|
||||
}
|
||||
Some(Subcommand::Sandbox(sandbox_args)) => match sandbox_args.cmd {
|
||||
SandboxCommand::Macos(mut seatbelt_cli) => {
|
||||
|
|
@ -718,7 +720,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
);
|
||||
codex_cli::debug_sandbox::run_command_under_seatbelt(
|
||||
seatbelt_cli,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
|
@ -729,7 +731,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
);
|
||||
codex_cli::debug_sandbox::run_command_under_landlock(
|
||||
landlock_cli,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
|
@ -740,7 +742,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
|||
);
|
||||
codex_cli::debug_sandbox::run_command_under_windows(
|
||||
windows_cli,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
|
@ -887,7 +889,7 @@ fn prepend_config_flags(
|
|||
|
||||
async fn run_interactive_tui(
|
||||
mut interactive: TuiCli,
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
) -> std::io::Result<AppExitInfo> {
|
||||
if let Some(prompt) = interactive.prompt.take() {
|
||||
// Normalize CRLF/CR to LF so CLI-provided text can't leak `\r` into TUI state.
|
||||
|
|
@ -912,7 +914,7 @@ async fn run_interactive_tui(
|
|||
}
|
||||
}
|
||||
|
||||
codex_tui::run_main(interactive, codex_linux_sandbox_exe).await
|
||||
codex_tui::run_main(interactive, arg0_paths).await
|
||||
}
|
||||
|
||||
fn confirm(prompt: &str) -> std::io::Result<bool> {
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ pub(crate) async fn apply_role_to_config(
|
|||
ConfigOverrides {
|
||||
cwd: Some(config.cwd.clone()),
|
||||
codex_linux_sandbox_exe: config.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: config.main_execve_wrapper_exe.clone(),
|
||||
js_repl_node_path: config.js_repl_node_path.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
|
|
@ -340,6 +341,8 @@ mod tests {
|
|||
TomlValue::String("base-model".to_string()),
|
||||
)])
|
||||
.await;
|
||||
config.codex_linux_sandbox_exe = Some(PathBuf::from("/tmp/codex-linux-sandbox"));
|
||||
config.main_execve_wrapper_exe = Some(PathBuf::from("/tmp/codex-execve-wrapper"));
|
||||
let role_path = write_role_config(
|
||||
&home,
|
||||
"effort-only.toml",
|
||||
|
|
@ -360,6 +363,14 @@ mod tests {
|
|||
|
||||
assert_eq!(config.model.as_deref(), Some("base-model"));
|
||||
assert_eq!(config.model_reasoning_effort, Some(ReasoningEffort::High));
|
||||
assert_eq!(
|
||||
config.codex_linux_sandbox_exe,
|
||||
Some(PathBuf::from("/tmp/codex-linux-sandbox"))
|
||||
);
|
||||
assert_eq!(
|
||||
config.main_execve_wrapper_exe,
|
||||
Some(PathBuf::from("/tmp/codex-execve-wrapper"))
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
|||
|
|
@ -1331,6 +1331,7 @@ impl Session {
|
|||
config.background_terminal_max_timeout,
|
||||
),
|
||||
shell_zsh_path: config.zsh_path.clone(),
|
||||
main_execve_wrapper_exe: config.main_execve_wrapper_exe.clone(),
|
||||
analytics_events_client: AnalyticsEventsClient::new(
|
||||
Arc::clone(&config),
|
||||
Arc::clone(&auth_manager),
|
||||
|
|
@ -8201,6 +8202,7 @@ mod tests {
|
|||
config.background_terminal_max_timeout,
|
||||
),
|
||||
shell_zsh_path: None,
|
||||
main_execve_wrapper_exe: config.main_execve_wrapper_exe.clone(),
|
||||
analytics_events_client: AnalyticsEventsClient::new(
|
||||
Arc::clone(&config),
|
||||
Arc::clone(&auth_manager),
|
||||
|
|
@ -8356,6 +8358,7 @@ mod tests {
|
|||
config.background_terminal_max_timeout,
|
||||
),
|
||||
shell_zsh_path: None,
|
||||
main_execve_wrapper_exe: config.main_execve_wrapper_exe.clone(),
|
||||
analytics_events_client: AnalyticsEventsClient::new(
|
||||
Arc::clone(&config),
|
||||
Arc::clone(&auth_manager),
|
||||
|
|
|
|||
|
|
@ -399,6 +399,11 @@ pub struct Config {
|
|||
/// When this program is invoked, arg0 will be set to `codex-linux-sandbox`.
|
||||
pub codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
|
||||
/// Path to the `codex-execve-wrapper` executable used for shell
|
||||
/// escalation. This cannot be set in the config file: it must be set in
|
||||
/// code via [`ConfigOverrides`].
|
||||
pub main_execve_wrapper_exe: Option<PathBuf>,
|
||||
|
||||
/// Optional absolute path to the Node runtime used by `js_repl`.
|
||||
pub js_repl_node_path: Option<PathBuf>,
|
||||
|
||||
|
|
@ -646,7 +651,8 @@ impl Config {
|
|||
/// designed to use [AskForApproval::Never] exclusively.
|
||||
///
|
||||
/// Further, [ConfigOverrides] contains some options that are not supported
|
||||
/// in [ConfigToml], such as `cwd` and `codex_linux_sandbox_exe`.
|
||||
/// in [ConfigToml], such as `cwd`, `codex_linux_sandbox_exe`, and
|
||||
/// `main_execve_wrapper_exe`.
|
||||
pub async fn load_with_cli_overrides_and_harness_overrides(
|
||||
cli_overrides: Vec<(String, TomlValue)>,
|
||||
harness_overrides: ConfigOverrides,
|
||||
|
|
@ -1536,6 +1542,7 @@ pub struct ConfigOverrides {
|
|||
pub model_provider: Option<String>,
|
||||
pub config_profile: Option<String>,
|
||||
pub codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
pub main_execve_wrapper_exe: Option<PathBuf>,
|
||||
pub js_repl_node_path: Option<PathBuf>,
|
||||
pub js_repl_node_module_dirs: Option<Vec<PathBuf>>,
|
||||
pub zsh_path: Option<PathBuf>,
|
||||
|
|
@ -1665,6 +1672,7 @@ impl Config {
|
|||
model_provider,
|
||||
config_profile: config_profile_key,
|
||||
codex_linux_sandbox_exe,
|
||||
main_execve_wrapper_exe,
|
||||
js_repl_node_path: js_repl_node_path_override,
|
||||
js_repl_node_module_dirs: js_repl_node_module_dirs_override,
|
||||
zsh_path: zsh_path_override,
|
||||
|
|
@ -2151,6 +2159,7 @@ impl Config {
|
|||
ephemeral: ephemeral.unwrap_or_default(),
|
||||
file_opener: cfg.file_opener.unwrap_or(UriBasedFileOpener::VsCode),
|
||||
codex_linux_sandbox_exe,
|
||||
main_execve_wrapper_exe,
|
||||
js_repl_node_path,
|
||||
js_repl_node_module_dirs,
|
||||
zsh_path,
|
||||
|
|
@ -4765,6 +4774,7 @@ model_verbosity = "high"
|
|||
ephemeral: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_linux_sandbox_exe: None,
|
||||
main_execve_wrapper_exe: None,
|
||||
js_repl_node_path: None,
|
||||
js_repl_node_module_dirs: Vec::new(),
|
||||
zsh_path: None,
|
||||
|
|
@ -4891,6 +4901,7 @@ model_verbosity = "high"
|
|||
ephemeral: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_linux_sandbox_exe: None,
|
||||
main_execve_wrapper_exe: None,
|
||||
js_repl_node_path: None,
|
||||
js_repl_node_module_dirs: Vec::new(),
|
||||
zsh_path: None,
|
||||
|
|
@ -5015,6 +5026,7 @@ model_verbosity = "high"
|
|||
ephemeral: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_linux_sandbox_exe: None,
|
||||
main_execve_wrapper_exe: None,
|
||||
js_repl_node_path: None,
|
||||
js_repl_node_module_dirs: Vec::new(),
|
||||
zsh_path: None,
|
||||
|
|
@ -5125,6 +5137,7 @@ model_verbosity = "high"
|
|||
ephemeral: false,
|
||||
file_opener: UriBasedFileOpener::VsCode,
|
||||
codex_linux_sandbox_exe: None,
|
||||
main_execve_wrapper_exe: None,
|
||||
js_repl_node_path: None,
|
||||
js_repl_node_module_dirs: Vec::new(),
|
||||
zsh_path: None,
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ pub(crate) struct SessionServices {
|
|||
pub(crate) unified_exec_manager: UnifiedExecProcessManager,
|
||||
#[cfg_attr(not(unix), allow(dead_code))]
|
||||
pub(crate) shell_zsh_path: Option<PathBuf>,
|
||||
#[cfg_attr(not(unix), allow(dead_code))]
|
||||
pub(crate) main_execve_wrapper_exe: Option<PathBuf>,
|
||||
pub(crate) analytics_events_client: AnalyticsEventsClient,
|
||||
pub(crate) hooks: Hooks,
|
||||
pub(crate) rollout: Mutex<Option<RolloutRecorder>>,
|
||||
|
|
|
|||
|
|
@ -106,15 +106,22 @@ pub(super) async fn try_run_zsh_fork(
|
|||
justification,
|
||||
arg0,
|
||||
};
|
||||
|
||||
let main_execve_wrapper_exe = ctx
|
||||
.session
|
||||
.services
|
||||
.main_execve_wrapper_exe
|
||||
.clone()
|
||||
.ok_or_else(|| {
|
||||
ToolError::Rejected(
|
||||
"zsh fork feature enabled, but execve wrapper is not configured".to_string(),
|
||||
)
|
||||
})?;
|
||||
let exec_params = ExecParams {
|
||||
command: script,
|
||||
workdir: req.cwd.to_string_lossy().to_string(),
|
||||
timeout_ms: Some(effective_timeout.as_millis() as u64),
|
||||
login: Some(login),
|
||||
};
|
||||
let execve_wrapper =
|
||||
shell_execve_wrapper().map_err(|err| ToolError::Rejected(format!("{err}")))?;
|
||||
|
||||
// Note that Stopwatch starts immediately upon creation, so currently we try
|
||||
// to minimize the time between creating the Stopwatch and starting the
|
||||
|
|
@ -132,8 +139,11 @@ pub(super) async fn try_run_zsh_fork(
|
|||
stopwatch: stopwatch.clone(),
|
||||
};
|
||||
|
||||
let escalate_server =
|
||||
EscalateServer::new(shell_zsh_path.clone(), execve_wrapper, escalation_policy);
|
||||
let escalate_server = EscalateServer::new(
|
||||
shell_zsh_path.clone(),
|
||||
main_execve_wrapper_exe,
|
||||
escalation_policy,
|
||||
);
|
||||
|
||||
let exec_result = escalate_server
|
||||
.exec(exec_params, cancel_token, &command_executor)
|
||||
|
|
@ -342,34 +352,6 @@ impl ShellCommandExecutor for CoreShellCommandExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(mbolin): This should be passed down from codex-arg0 like codex_linux_sandbox_exe.
|
||||
fn shell_execve_wrapper() -> anyhow::Result<PathBuf> {
|
||||
const EXECVE_WRAPPER: &str = "codex-execve-wrapper";
|
||||
|
||||
if let Some(path) = std::env::var_os("PATH") {
|
||||
for dir in std::env::split_paths(&path) {
|
||||
let candidate = dir.join(EXECVE_WRAPPER);
|
||||
if candidate.is_file() {
|
||||
return Ok(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let exe = std::env::current_exe()?;
|
||||
let sibling = exe
|
||||
.parent()
|
||||
.map(|parent| parent.join(EXECVE_WRAPPER))
|
||||
.ok_or_else(|| anyhow::anyhow!("failed to determine codex-execve-wrapper path"))?;
|
||||
if sibling.is_file() {
|
||||
return Ok(sibling);
|
||||
}
|
||||
|
||||
Err(anyhow::anyhow!(
|
||||
"failed to locate {EXECVE_WRAPPER} in PATH or next to current executable ({})",
|
||||
exe.display()
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
struct ParsedShellCommand {
|
||||
script: String,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub mod exec_events;
|
|||
pub use cli::Cli;
|
||||
pub use cli::Command;
|
||||
pub use cli::ReviewArgs;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_cloud_requirements::cloud_requirements_loader;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::LMSTUDIO_OSS_PROVIDER_ID;
|
||||
|
|
@ -90,7 +91,7 @@ struct ThreadEventEnvelope {
|
|||
suppress_output: bool,
|
||||
}
|
||||
|
||||
pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()> {
|
||||
pub async fn run_main(cli: Cli, arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
|
||||
if let Err(err) = set_default_originator("codex_exec".to_string()) {
|
||||
tracing::warn!(?err, "Failed to set codex exec originator override {err:?}");
|
||||
}
|
||||
|
|
@ -271,7 +272,8 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> any
|
|||
sandbox_mode,
|
||||
cwd: resolved_cwd,
|
||||
model_provider: model_provider.clone(),
|
||||
codex_linux_sandbox_exe,
|
||||
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
js_repl_node_path: None,
|
||||
js_repl_node_module_dirs: None,
|
||||
zsh_path: None,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
//! 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;
|
||||
|
|
@ -25,7 +26,7 @@ struct TopCli {
|
|||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
||||
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;
|
||||
|
|
@ -34,7 +35,7 @@ fn main() -> anyhow::Result<()> {
|
|||
.raw_overrides
|
||||
.splice(0..0, top_cli.config_overrides.raw_overrides);
|
||||
|
||||
run_main(inner, codex_linux_sandbox_exe).await?;
|
||||
run_main(inner, arg0_paths).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//! Configuration object accepted by the `codex` MCP tool-call.
|
||||
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_protocol::ThreadId;
|
||||
|
|
@ -153,7 +154,7 @@ impl CodexToolCallParam {
|
|||
/// effective Config object generated from the supplied parameters.
|
||||
pub async fn into_config(
|
||||
self,
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
) -> std::io::Result<(String, Config)> {
|
||||
let Self {
|
||||
prompt,
|
||||
|
|
@ -175,7 +176,8 @@ impl CodexToolCallParam {
|
|||
cwd: cwd.map(PathBuf::from),
|
||||
approval_policy: approval_policy.map(Into::into),
|
||||
sandbox_mode: sandbox.map(Into::into),
|
||||
codex_linux_sandbox_exe,
|
||||
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
base_instructions,
|
||||
developer_instructions,
|
||||
compact_prompt,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Result as IoResult;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::config::Config;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ const CHANNEL_CAPACITY: usize = 128;
|
|||
type IncomingMessage = JsonRpcMessage<ClientRequest, Value, ClientNotification>;
|
||||
|
||||
pub async fn run_main(
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
cli_config_overrides: CliConfigOverrides,
|
||||
) -> IoResult<()> {
|
||||
// Install a simple subscriber so `tracing` output is visible. Users can
|
||||
|
|
@ -105,7 +105,7 @@ pub async fn run_main(
|
|||
let outgoing_message_sender = OutgoingMessageSender::new(outgoing_tx);
|
||||
let mut processor = MessageProcessor::new(
|
||||
outgoing_message_sender,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
std::sync::Arc::new(config),
|
||||
);
|
||||
async move {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_arg0::arg0_dispatch_or_else;
|
||||
use codex_mcp_server::run_main;
|
||||
use codex_utils_cli::CliConfigOverrides;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
||||
run_main(codex_linux_sandbox_exe, CliConfigOverrides::default()).await?;
|
||||
arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {
|
||||
run_main(arg0_paths, CliConfigOverrides::default()).await?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::ThreadManager;
|
||||
use codex_core::config::Config;
|
||||
|
|
@ -38,7 +38,7 @@ use crate::outgoing_message::OutgoingMessageSender;
|
|||
pub(crate) struct MessageProcessor {
|
||||
outgoing: Arc<OutgoingMessageSender>,
|
||||
initialized: bool,
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
thread_manager: Arc<ThreadManager>,
|
||||
running_requests_id_to_codex_uuid: Arc<Mutex<HashMap<RequestId, ThreadId>>>,
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@ impl MessageProcessor {
|
|||
/// `Sender` so handlers can enqueue messages to be written to stdout.
|
||||
pub(crate) fn new(
|
||||
outgoing: OutgoingMessageSender,
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
arg0_paths: Arg0DispatchPaths,
|
||||
config: Arc<Config>,
|
||||
) -> Self {
|
||||
let outgoing = Arc::new(outgoing);
|
||||
|
|
@ -66,7 +66,7 @@ impl MessageProcessor {
|
|||
Self {
|
||||
outgoing,
|
||||
initialized: false,
|
||||
codex_linux_sandbox_exe,
|
||||
arg0_paths,
|
||||
thread_manager,
|
||||
running_requests_id_to_codex_uuid: Arc::new(Mutex::new(HashMap::new())),
|
||||
}
|
||||
|
|
@ -352,10 +352,7 @@ impl MessageProcessor {
|
|||
let arguments = arguments.map(serde_json::Value::Object);
|
||||
let (initial_prompt, config): (String, Config) = match arguments {
|
||||
Some(json_val) => match serde_json::from_value::<CodexToolCallParam>(json_val) {
|
||||
Ok(tool_cfg) => match tool_cfg
|
||||
.into_config(self.codex_linux_sandbox_exe.clone())
|
||||
.await
|
||||
{
|
||||
Ok(tool_cfg) => match tool_cfg.into_config(self.arg0_paths.clone()).await {
|
||||
Ok(cfg) => cfg,
|
||||
Err(e) => {
|
||||
let result = CallToolResult {
|
||||
|
|
|
|||
|
|
@ -216,15 +216,13 @@ use crate::onboarding::onboarding_screen::OnboardingScreenArgs;
|
|||
use crate::onboarding::onboarding_screen::run_onboarding_app;
|
||||
use crate::tui::Tui;
|
||||
pub use cli::Cli;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
pub use markdown_render::render_markdown_text;
|
||||
pub use public_widgets::composer_input::ComposerAction;
|
||||
pub use public_widgets::composer_input::ComposerInput;
|
||||
// (tests access modules directly within the crate)
|
||||
|
||||
pub async fn run_main(
|
||||
mut cli: Cli,
|
||||
codex_linux_sandbox_exe: Option<PathBuf>,
|
||||
) -> std::io::Result<AppExitInfo> {
|
||||
pub async fn run_main(mut cli: Cli, arg0_paths: Arg0DispatchPaths) -> std::io::Result<AppExitInfo> {
|
||||
let (sandbox_mode, approval_policy) = if cli.full_auto {
|
||||
(
|
||||
Some(SandboxMode::WorkspaceWrite),
|
||||
|
|
@ -373,7 +371,8 @@ pub async fn run_main(
|
|||
cwd,
|
||||
model_provider: model_provider_override.clone(),
|
||||
config_profile: cli.config_profile.clone(),
|
||||
codex_linux_sandbox_exe,
|
||||
codex_linux_sandbox_exe: arg0_paths.codex_linux_sandbox_exe.clone(),
|
||||
main_execve_wrapper_exe: arg0_paths.main_execve_wrapper_exe.clone(),
|
||||
show_raw_agent_reasoning: cli.oss.then_some(true),
|
||||
additional_writable_roots: additional_dirs,
|
||||
..Default::default()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use clap::Parser;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_arg0::arg0_dispatch_or_else;
|
||||
use codex_tui::Cli;
|
||||
use codex_tui::run_main;
|
||||
|
|
@ -14,14 +15,14 @@ struct TopCli {
|
|||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
arg0_dispatch_or_else(|codex_linux_sandbox_exe| async move {
|
||||
arg0_dispatch_or_else(|arg0_paths: Arg0DispatchPaths| async move {
|
||||
let top_cli = TopCli::parse();
|
||||
let mut inner = top_cli.inner;
|
||||
inner
|
||||
.config_overrides
|
||||
.raw_overrides
|
||||
.splice(0..0, top_cli.config_overrides.raw_overrides);
|
||||
let exit_info = run_main(inner, codex_linux_sandbox_exe).await?;
|
||||
let exit_info = run_main(inner, arg0_paths).await?;
|
||||
let token_usage = exit_info.token_usage;
|
||||
if !token_usage.is_zero() {
|
||||
println!(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue