mirror of
https://github.com/openai/codex.git
synced 2026-11-03 19:53:25 +00:00
feat: include NetworkConfig through ExecParams
This commit is contained in:
@@ -6658,6 +6658,7 @@ mod tests {
|
||||
cwd: turn_context.cwd.clone(),
|
||||
expiration: timeout_ms.into(),
|
||||
env: HashMap::new(),
|
||||
network: None,
|
||||
sandbox_permissions,
|
||||
windows_sandbox_level: turn_context.windows_sandbox_level,
|
||||
justification: Some("test".to_string()),
|
||||
@@ -6670,6 +6671,7 @@ mod tests {
|
||||
cwd: params.cwd.clone(),
|
||||
expiration: timeout_ms.into(),
|
||||
env: HashMap::new(),
|
||||
network: None,
|
||||
windows_sandbox_level: turn_context.windows_sandbox_level,
|
||||
justification: params.justification.clone(),
|
||||
arg0: None,
|
||||
|
||||
@@ -47,6 +47,7 @@ use crate::protocol::SandboxPolicy;
|
||||
use crate::windows_sandbox::WindowsSandboxLevelExt;
|
||||
use codex_app_server_protocol::Tools;
|
||||
use codex_app_server_protocol::UserSavedConfig;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::config_types::AltScreenMode;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::ModeKind;
|
||||
@@ -152,6 +153,9 @@ pub struct Config {
|
||||
/// using backend-specific headers or URLs to enforce this.
|
||||
pub enforce_residency: Constrained<Option<ResidencyRequirement>>,
|
||||
|
||||
/// Effective network configuration applied to all spawned processes.
|
||||
pub network: Option<NetworkProxy>,
|
||||
|
||||
/// True if the user passed in an override or set a value in config.toml
|
||||
/// for either of approval_policy or sandbox_mode.
|
||||
pub did_user_set_custom_approval_policy_or_sandbox_mode: bool,
|
||||
@@ -1690,6 +1694,7 @@ impl Config {
|
||||
approval_policy: constrained_approval_policy.value,
|
||||
sandbox_policy: constrained_sandbox_policy.value,
|
||||
enforce_residency: enforce_residency.value,
|
||||
network: None,
|
||||
did_user_set_custom_approval_policy_or_sandbox_mode,
|
||||
forced_auto_mode_downgraded_on_windows,
|
||||
shell_environment_policy,
|
||||
@@ -4003,6 +4008,7 @@ model_verbosity = "high"
|
||||
approval_policy: Constrained::allow_any(AskForApproval::Never),
|
||||
sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()),
|
||||
enforce_residency: Constrained::allow_any(None),
|
||||
network: None,
|
||||
did_user_set_custom_approval_policy_or_sandbox_mode: true,
|
||||
forced_auto_mode_downgraded_on_windows: false,
|
||||
shell_environment_policy: ShellEnvironmentPolicy::default(),
|
||||
@@ -4091,6 +4097,7 @@ model_verbosity = "high"
|
||||
approval_policy: Constrained::allow_any(AskForApproval::UnlessTrusted),
|
||||
sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()),
|
||||
enforce_residency: Constrained::allow_any(None),
|
||||
network: None,
|
||||
did_user_set_custom_approval_policy_or_sandbox_mode: true,
|
||||
forced_auto_mode_downgraded_on_windows: false,
|
||||
shell_environment_policy: ShellEnvironmentPolicy::default(),
|
||||
@@ -4194,6 +4201,7 @@ model_verbosity = "high"
|
||||
approval_policy: Constrained::allow_any(AskForApproval::OnFailure),
|
||||
sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()),
|
||||
enforce_residency: Constrained::allow_any(None),
|
||||
network: None,
|
||||
did_user_set_custom_approval_policy_or_sandbox_mode: true,
|
||||
forced_auto_mode_downgraded_on_windows: false,
|
||||
shell_environment_policy: ShellEnvironmentPolicy::default(),
|
||||
@@ -4283,6 +4291,7 @@ model_verbosity = "high"
|
||||
approval_policy: Constrained::allow_any(AskForApproval::OnFailure),
|
||||
sandbox_policy: Constrained::allow_any(SandboxPolicy::new_read_only_policy()),
|
||||
enforce_residency: Constrained::allow_any(None),
|
||||
network: None,
|
||||
did_user_set_custom_approval_policy_or_sandbox_mode: true,
|
||||
forced_auto_mode_downgraded_on_windows: false,
|
||||
shell_environment_policy: ShellEnvironmentPolicy::default(),
|
||||
|
||||
@@ -32,6 +32,7 @@ use crate::sandboxing::SandboxPermissions;
|
||||
use crate::spawn::StdioPolicy;
|
||||
use crate::spawn::spawn_child_async;
|
||||
use crate::text_encoding::bytes_to_string_smart;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_utils_pty::process_group::kill_child_process_group;
|
||||
|
||||
pub const DEFAULT_EXEC_COMMAND_TIMEOUT_MS: u64 = 10_000;
|
||||
@@ -63,6 +64,7 @@ pub struct ExecParams {
|
||||
pub cwd: PathBuf,
|
||||
pub expiration: ExecExpiration,
|
||||
pub env: HashMap<String, String>,
|
||||
pub network: Option<NetworkProxy>,
|
||||
pub sandbox_permissions: SandboxPermissions,
|
||||
pub windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel,
|
||||
pub justification: Option<String>,
|
||||
@@ -170,12 +172,16 @@ pub async fn process_exec_tool_call(
|
||||
command,
|
||||
cwd,
|
||||
expiration,
|
||||
env,
|
||||
mut env,
|
||||
network,
|
||||
sandbox_permissions,
|
||||
windows_sandbox_level,
|
||||
justification,
|
||||
arg0: _,
|
||||
} = params;
|
||||
if let Some(network) = network.as_ref() {
|
||||
network.apply_to_env(&mut env);
|
||||
}
|
||||
|
||||
let (program, args) = command.split_first().ok_or_else(|| {
|
||||
CodexErr::Io(io::Error::new(
|
||||
@@ -233,6 +239,7 @@ pub(crate) async fn execute_exec_env(
|
||||
cwd,
|
||||
expiration,
|
||||
env,
|
||||
network: None,
|
||||
sandbox_permissions,
|
||||
windows_sandbox_level,
|
||||
justification,
|
||||
@@ -324,11 +331,15 @@ async fn exec_windows_sandbox(
|
||||
let ExecParams {
|
||||
command,
|
||||
cwd,
|
||||
env,
|
||||
mut env,
|
||||
network,
|
||||
expiration,
|
||||
windows_sandbox_level,
|
||||
..
|
||||
} = params;
|
||||
if let Some(network) = network.as_ref() {
|
||||
network.apply_to_env(&mut env);
|
||||
}
|
||||
// TODO(iceweasel-oai): run_windows_sandbox_capture should support all
|
||||
// variants of ExecExpiration, not just timeout.
|
||||
let timeout_ms = expiration.timeout_ms();
|
||||
@@ -677,12 +688,16 @@ async fn exec(
|
||||
let ExecParams {
|
||||
command,
|
||||
cwd,
|
||||
env,
|
||||
mut env,
|
||||
network,
|
||||
arg0,
|
||||
expiration,
|
||||
windows_sandbox_level: _,
|
||||
..
|
||||
} = params;
|
||||
if let Some(network) = network.as_ref() {
|
||||
network.apply_to_env(&mut env);
|
||||
}
|
||||
|
||||
let (program, args) = command.split_first().ok_or_else(|| {
|
||||
CodexErr::Io(io::Error::new(
|
||||
@@ -1061,6 +1076,7 @@ mod tests {
|
||||
cwd: std::env::current_dir()?,
|
||||
expiration: 500.into(),
|
||||
env,
|
||||
network: None,
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled,
|
||||
justification: None,
|
||||
@@ -1107,6 +1123,7 @@ mod tests {
|
||||
cwd: cwd.clone(),
|
||||
expiration: ExecExpiration::Cancellation(cancel_token),
|
||||
env,
|
||||
network: None,
|
||||
sandbox_permissions: SandboxPermissions::UseDefault,
|
||||
windows_sandbox_level: codex_protocol::config_types::WindowsSandboxLevel::Disabled,
|
||||
justification: None,
|
||||
|
||||
@@ -430,8 +430,20 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn can_bind_loopback_port() -> bool {
|
||||
match std::net::TcpListener::bind(("127.0.0.1", 0)) {
|
||||
Ok(_listener) => true,
|
||||
Err(err) if err.kind() == std::io::ErrorKind::PermissionDenied => false,
|
||||
Err(err) => panic!("unexpected error probing loopback listen permissions: {err}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_available_models_sorts_by_priority() {
|
||||
if !can_bind_loopback_port() {
|
||||
return;
|
||||
}
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let remote_models = vec![
|
||||
remote_model("priority-low", "Low", 1),
|
||||
@@ -489,6 +501,10 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_available_models_uses_cache_when_fresh() {
|
||||
if !can_bind_loopback_port() {
|
||||
return;
|
||||
}
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let remote_models = vec![remote_model("cached", "Cached", 5)];
|
||||
let models_mock = mount_models_once(
|
||||
@@ -536,6 +552,10 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_available_models_refetches_when_cache_stale() {
|
||||
if !can_bind_loopback_port() {
|
||||
return;
|
||||
}
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let initial_models = vec![remote_model("stale", "Stale", 1)];
|
||||
let initial_mock = mount_models_once(
|
||||
@@ -605,6 +625,10 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_available_models_refetches_when_version_mismatch() {
|
||||
if !can_bind_loopback_port() {
|
||||
return;
|
||||
}
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let initial_models = vec![remote_model("old", "Old", 1)];
|
||||
let initial_mock = mount_models_once(
|
||||
@@ -674,6 +698,10 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_available_models_drops_removed_remote_models() {
|
||||
if !can_bind_loopback_port() {
|
||||
return;
|
||||
}
|
||||
|
||||
let server = MockServer::start().await;
|
||||
let initial_models = vec![remote_model("remote-old", "Remote Old", 1)];
|
||||
let initial_mock = mount_models_once(
|
||||
|
||||
@@ -53,6 +53,7 @@ impl ShellHandler {
|
||||
cwd: turn_context.resolve_path(params.workdir.clone()),
|
||||
expiration: params.timeout_ms.into(),
|
||||
env: create_env(&turn_context.shell_environment_policy, Some(thread_id)),
|
||||
network: turn_context.config.network.clone(),
|
||||
sandbox_permissions: params.sandbox_permissions.unwrap_or_default(),
|
||||
windows_sandbox_level: turn_context.windows_sandbox_level,
|
||||
justification: params.justification.clone(),
|
||||
@@ -81,6 +82,7 @@ impl ShellCommandHandler {
|
||||
cwd: turn_context.resolve_path(params.workdir.clone()),
|
||||
expiration: params.timeout_ms.into(),
|
||||
env: create_env(&turn_context.shell_environment_policy, Some(thread_id)),
|
||||
network: turn_context.config.network.clone(),
|
||||
sandbox_permissions: params.sandbox_permissions.unwrap_or_default(),
|
||||
windows_sandbox_level: turn_context.windows_sandbox_level,
|
||||
justification: params.justification.clone(),
|
||||
@@ -311,6 +313,7 @@ impl ShellHandler {
|
||||
cwd: exec_params.cwd.clone(),
|
||||
timeout_ms: exec_params.expiration.timeout_ms(),
|
||||
env: exec_params.env.clone(),
|
||||
network: exec_params.network.clone(),
|
||||
sandbox_permissions: exec_params.sandbox_permissions,
|
||||
justification: exec_params.justification.clone(),
|
||||
exec_approval_requirement,
|
||||
@@ -441,6 +444,7 @@ mod tests {
|
||||
assert_eq!(exec_params.command, expected_command);
|
||||
assert_eq!(exec_params.cwd, expected_cwd);
|
||||
assert_eq!(exec_params.env, expected_env);
|
||||
assert_eq!(exec_params.network, turn_context.config.network);
|
||||
assert_eq!(exec_params.expiration.timeout_ms(), timeout_ms);
|
||||
assert_eq!(exec_params.sandbox_permissions, sandbox_permissions);
|
||||
assert_eq!(exec_params.justification, justification);
|
||||
|
||||
@@ -23,6 +23,7 @@ use crate::tools::sandboxing::ToolCtx;
|
||||
use crate::tools::sandboxing::ToolError;
|
||||
use crate::tools::sandboxing::ToolRuntime;
|
||||
use crate::tools::sandboxing::with_cached_approval;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use futures::future::BoxFuture;
|
||||
use std::path::PathBuf;
|
||||
@@ -33,6 +34,7 @@ pub struct ShellRequest {
|
||||
pub cwd: PathBuf,
|
||||
pub timeout_ms: Option<u64>,
|
||||
pub env: std::collections::HashMap<String, String>,
|
||||
pub network: Option<NetworkProxy>,
|
||||
pub sandbox_permissions: SandboxPermissions,
|
||||
pub justification: Option<String>,
|
||||
pub exec_approval_requirement: ExecApprovalRequirement,
|
||||
@@ -155,10 +157,14 @@ impl ToolRuntime<ShellRequest, ExecToolCallOutput> for ShellRuntime {
|
||||
command
|
||||
};
|
||||
|
||||
let mut env = req.env.clone();
|
||||
if let Some(network) = req.network.as_ref() {
|
||||
network.apply_to_env(&mut env);
|
||||
}
|
||||
let spec = build_command_spec(
|
||||
&command,
|
||||
&req.cwd,
|
||||
&req.env,
|
||||
&env,
|
||||
req.timeout_ms.into(),
|
||||
req.sandbox_permissions,
|
||||
req.justification.clone(),
|
||||
|
||||
@@ -27,6 +27,7 @@ use crate::tools::sandboxing::with_cached_approval;
|
||||
use crate::unified_exec::UnifiedExecError;
|
||||
use crate::unified_exec::UnifiedExecProcess;
|
||||
use crate::unified_exec::UnifiedExecProcessManager;
|
||||
use codex_network_proxy::NetworkProxy;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use futures::future::BoxFuture;
|
||||
use std::collections::HashMap;
|
||||
@@ -37,6 +38,7 @@ pub struct UnifiedExecRequest {
|
||||
pub command: Vec<String>,
|
||||
pub cwd: PathBuf,
|
||||
pub env: HashMap<String, String>,
|
||||
pub network: Option<NetworkProxy>,
|
||||
pub tty: bool,
|
||||
pub sandbox_permissions: SandboxPermissions,
|
||||
pub justification: Option<String>,
|
||||
@@ -60,6 +62,7 @@ impl UnifiedExecRequest {
|
||||
command: Vec<String>,
|
||||
cwd: PathBuf,
|
||||
env: HashMap<String, String>,
|
||||
network: Option<NetworkProxy>,
|
||||
tty: bool,
|
||||
sandbox_permissions: SandboxPermissions,
|
||||
justification: Option<String>,
|
||||
@@ -69,6 +72,7 @@ impl UnifiedExecRequest {
|
||||
command,
|
||||
cwd,
|
||||
env,
|
||||
network,
|
||||
tty,
|
||||
sandbox_permissions,
|
||||
justification,
|
||||
@@ -181,10 +185,14 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecProcess> for UnifiedExecRunt
|
||||
command
|
||||
};
|
||||
|
||||
let mut env = req.env.clone();
|
||||
if let Some(network) = req.network.as_ref() {
|
||||
network.apply_to_env(&mut env);
|
||||
}
|
||||
let spec = build_command_spec(
|
||||
&command,
|
||||
&req.cwd,
|
||||
&req.env,
|
||||
&env,
|
||||
ExecExpiration::DefaultTimeout,
|
||||
req.sandbox_permissions,
|
||||
req.justification.clone(),
|
||||
|
||||
@@ -505,6 +505,7 @@ impl UnifiedExecProcessManager {
|
||||
request.command.clone(),
|
||||
cwd,
|
||||
env,
|
||||
context.turn.config.network.clone(),
|
||||
request.tty,
|
||||
request.sandbox_permissions,
|
||||
request.justification.clone(),
|
||||
|
||||
Reference in New Issue
Block a user