diff --git a/codex-rs/tui/src/app_server_session.rs b/codex-rs/tui/src/app_server_session.rs index 263838e7b1..87ff2b0190 100644 --- a/codex-rs/tui/src/app_server_session.rs +++ b/codex-rs/tui/src/app_server_session.rs @@ -1103,31 +1103,6 @@ fn config_request_overrides_from_config( }) } -fn sandbox_mode_from_permission_profile( - permission_profile: &PermissionProfile, - cwd: &std::path::Path, -) -> Option { - match permission_profile { - PermissionProfile::Disabled => { - Some(codex_app_server_protocol::SandboxMode::DangerFullAccess) - } - PermissionProfile::External { .. } => None, - PermissionProfile::Managed { .. } => { - let file_system_policy = permission_profile.file_system_sandbox_policy(); - if file_system_policy.has_full_disk_write_access() { - permission_profile - .network_sandbox_policy() - .is_enabled() - .then_some(codex_app_server_protocol::SandboxMode::DangerFullAccess) - } else if file_system_policy.can_write_path_with_cwd(cwd, cwd) { - Some(codex_app_server_protocol::SandboxMode::WorkspaceWrite) - } else { - Some(codex_app_server_protocol::SandboxMode::ReadOnly) - } - } - } -} - fn permissions_selection_from_active_profile( active: ActivePermissionProfile, ) -> PermissionProfileSelectionParams { @@ -1195,22 +1170,13 @@ fn thread_start_params_from_config( session_start_source: Option, ) -> ThreadStartParams { let permissions = permissions_selection_from_config(config, thread_params_mode); - let sandbox = permissions - .is_none() - .then(|| { - sandbox_mode_from_permission_profile( - &config.permissions.permission_profile(), - config.cwd.as_path(), - ) - }) - .flatten(); ThreadStartParams { model: config.model.clone(), model_provider: thread_params_mode.model_provider_from_config(config), cwd: thread_cwd_from_config(config, thread_params_mode, remote_cwd_override), approval_policy: Some(config.permissions.approval_policy.value().into()), approvals_reviewer: approvals_reviewer_override_from_config(config), - sandbox, + sandbox: None, permissions, config: config_request_overrides_from_config(config), ephemeral: Some(config.ephemeral), @@ -1227,15 +1193,6 @@ fn thread_resume_params_from_config( remote_cwd_override: Option<&std::path::Path>, ) -> ThreadResumeParams { let permissions = permissions_selection_from_config(&config, thread_params_mode); - let sandbox = permissions - .is_none() - .then(|| { - sandbox_mode_from_permission_profile( - &config.permissions.permission_profile(), - config.cwd.as_path(), - ) - }) - .flatten(); ThreadResumeParams { thread_id: thread_id.to_string(), model: config.model.clone(), @@ -1243,7 +1200,7 @@ fn thread_resume_params_from_config( cwd: thread_cwd_from_config(&config, thread_params_mode, remote_cwd_override), approval_policy: Some(config.permissions.approval_policy.value().into()), approvals_reviewer: approvals_reviewer_override_from_config(&config), - sandbox, + sandbox: None, permissions, config: config_request_overrides_from_config(&config), persist_extended_history: true, @@ -1258,15 +1215,6 @@ fn thread_fork_params_from_config( remote_cwd_override: Option<&std::path::Path>, ) -> ThreadForkParams { let permissions = permissions_selection_from_config(&config, thread_params_mode); - let sandbox = permissions - .is_none() - .then(|| { - sandbox_mode_from_permission_profile( - &config.permissions.permission_profile(), - config.cwd.as_path(), - ) - }) - .flatten(); ThreadForkParams { thread_id: thread_id.to_string(), model: config.model.clone(), @@ -1274,7 +1222,7 @@ fn thread_fork_params_from_config( cwd: thread_cwd_from_config(&config, thread_params_mode, remote_cwd_override), approval_policy: Some(config.permissions.approval_policy.value().into()), approvals_reviewer: approvals_reviewer_override_from_config(&config), - sandbox, + sandbox: None, permissions, config: config_request_overrides_from_config(&config), base_instructions: config.base_instructions.clone(), @@ -1714,10 +1662,6 @@ mod tests { let temp_dir = tempfile::tempdir().expect("tempdir"); let config = build_config(&temp_dir).await; let thread_id = ThreadId::new(); - let expected_sandbox = sandbox_mode_from_permission_profile( - &config.permissions.permission_profile(), - config.cwd.as_path(), - ); let start = thread_start_params_from_config( &config, @@ -1744,83 +1688,20 @@ mod tests { assert_eq!(start.model_provider, None); assert_eq!(resume.model_provider, None); assert_eq!(fork.model_provider, None); - assert_eq!(start.sandbox, expected_sandbox); - assert_eq!(resume.sandbox, expected_sandbox); - assert_eq!(fork.sandbox, expected_sandbox); + assert_eq!(start.sandbox, None); + assert_eq!(resume.sandbox, None); + assert_eq!(fork.sandbox, None); assert_eq!(start.permissions, None); assert_eq!(resume.permissions, None); assert_eq!(fork.permissions, None); } - #[test] - fn sandbox_mode_does_not_project_non_cwd_write_roots_for_remote_sessions() { - let cwd = test_path_buf("/workspace/project").abs(); - let extra_root = test_path_buf("/workspace/cache").abs(); - let permission_profile = PermissionProfile::Managed { - file_system: ManagedFileSystemPermissions::Restricted { - entries: vec![ - FileSystemSandboxEntry { - path: FileSystemPath::Special { - value: FileSystemSpecialPath::Root, - }, - access: FileSystemAccessMode::Read, - }, - FileSystemSandboxEntry { - path: FileSystemPath::Path { path: extra_root }, - access: FileSystemAccessMode::Write, - }, - ], - glob_scan_max_depth: None, - }, - network: NetworkSandboxPolicy::Restricted, - }; - - assert_eq!( - sandbox_mode_from_permission_profile(&permission_profile, cwd.as_path()), - Some(codex_app_server_protocol::SandboxMode::ReadOnly) - ); - } - - #[test] - fn sandbox_mode_projects_cwd_write_for_remote_sessions() { - let cwd = test_path_buf("/workspace/project").abs(); - let permission_profile = PermissionProfile::Managed { - file_system: ManagedFileSystemPermissions::Restricted { - entries: vec![ - FileSystemSandboxEntry { - path: FileSystemPath::Special { - value: FileSystemSpecialPath::Root, - }, - access: FileSystemAccessMode::Read, - }, - FileSystemSandboxEntry { - path: FileSystemPath::Special { - value: FileSystemSpecialPath::ProjectRoots { subpath: None }, - }, - access: FileSystemAccessMode::Write, - }, - ], - glob_scan_max_depth: None, - }, - network: NetworkSandboxPolicy::Restricted, - }; - - assert_eq!( - sandbox_mode_from_permission_profile(&permission_profile, cwd.as_path()), - Some(codex_app_server_protocol::SandboxMode::WorkspaceWrite) - ); - } - #[tokio::test] async fn thread_lifecycle_params_forward_explicit_remote_cwd_override_for_remote_sessions() { let temp_dir = tempfile::tempdir().expect("tempdir"); let config = build_config(&temp_dir).await; let thread_id = ThreadId::new(); let remote_cwd = PathBuf::from("repo/on/server"); - let expected_sandbox = sandbox_mode_from_permission_profile( - &config.permissions.permission_profile(), - config.cwd.as_path(), - ); let start = thread_start_params_from_config( &config, @@ -1847,9 +1728,9 @@ mod tests { assert_eq!(start.model_provider, None); assert_eq!(resume.model_provider, None); assert_eq!(fork.model_provider, None); - assert_eq!(start.sandbox, expected_sandbox); - assert_eq!(resume.sandbox, expected_sandbox); - assert_eq!(fork.sandbox, expected_sandbox); + assert_eq!(start.sandbox, None); + assert_eq!(resume.sandbox, None); + assert_eq!(fork.sandbox, None); assert_eq!(start.permissions, None); assert_eq!(resume.permissions, None); assert_eq!(fork.permissions, None); diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index 39b4294b4a..505f97aec5 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -44,8 +44,8 @@ use codex_login::default_client::set_default_client_residency_requirement; use codex_login::enforce_login_restrictions; use codex_protocol::ThreadId; use codex_protocol::config_types::AltScreenMode; -use codex_protocol::config_types::SandboxMode; use codex_protocol::config_types::WindowsSandboxLevel; +use codex_protocol::models::PermissionProfile; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::RolloutLine; @@ -697,16 +697,15 @@ pub async fn run_main( .cwd .clone() .filter(|_| matches!(app_server_target, AppServerTarget::Remote { .. })); - let (sandbox_mode, approval_policy) = if cli.dangerously_bypass_approvals_and_sandbox { - ( - Some(SandboxMode::DangerFullAccess), - Some(AskForApproval::Never), - ) + let approval_policy = if cli.dangerously_bypass_approvals_and_sandbox { + Some(AskForApproval::Never) } else { - ( - cli.sandbox_mode.map(Into::::into), - cli.approval_policy.map(Into::into), - ) + cli.approval_policy.map(Into::into) + }; + let sandbox_mode = if cli.dangerously_bypass_approvals_and_sandbox { + None + } else { + cli.sandbox_mode.map(Into::into) }; // Map the legacy --search flag to the canonical web_search mode. @@ -789,6 +788,12 @@ pub async fn run_main( tracing::warn!(error = %err, "failed to run personality migration"); } + let permission_profile = if cli.dangerously_bypass_approvals_and_sandbox { + Some(PermissionProfile::Disabled) + } else { + None + }; + let chatgpt_base_url = config_toml .chatgpt_base_url .clone() @@ -843,6 +848,7 @@ pub async fn run_main( model, approval_policy, sandbox_mode, + permission_profile, cwd: if matches!(app_server_target, AppServerTarget::Remote { .. }) { None } else {