From a3ba42b0108db0bbff97e97f97b3fae8ea3e973e Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Wed, 9 Sep 2026 17:56:32 +0000 Subject: [PATCH] Remove the Windows `/sandbox-add-read-dir` slash command (#44259) ## What changed Remove the TUI command introduced in https://github.com/openai/codex/pull/11512 for granting sandbox read access to additional directories, along with its event handlers and non-elevated read-root grant helper. ## Testing Enable the existing voice command popup snapshot test on Windows as well as macOS. GitOrigin-RevId: 8a3a06b76749420101e34aa6587a8beab8eb5fdd --- codex-rs/tui/src/app/event_dispatch.rs | 57 ------------------- codex-rs/tui/src/app_event.rs | 13 ----- codex-rs/tui/src/bottom_pane/chat_composer.rs | 1 - codex-rs/tui/src/bottom_pane/command_popup.rs | 2 +- codex-rs/tui/src/chatwidget/slash_dispatch.rs | 10 ---- codex-rs/tui/src/slash_command.rs | 8 --- codex-rs/tui/src/windows_sandbox.rs | 39 +------------ 7 files changed, 3 insertions(+), 127 deletions(-) diff --git a/codex-rs/tui/src/app/event_dispatch.rs b/codex-rs/tui/src/app/event_dispatch.rs index 6b01c1bd1d..be2cf3e923 100644 --- a/codex-rs/tui/src/app/event_dispatch.rs +++ b/codex-rs/tui/src/app/event_dispatch.rs @@ -2167,63 +2167,6 @@ impl App { let _ = (preset, profile_selection); } } - AppEvent::BeginWindowsSandboxGrantReadRoot { path } => { - #[cfg(target_os = "windows")] - { - self.chat_widget - .add_to_history(history_cell::new_info_event( - format!("Granting sandbox read access to {path} ..."), - /*hint*/ None, - )); - - let permission_profile = self.config.permissions.effective_permission_profile(); - let workspace_roots = self.config.effective_workspace_roots(); - let command_cwd = self.config.cwd.clone(); - let env_map: std::collections::HashMap = - std::env::vars().collect(); - let codex_home = self.config.codex_home.clone(); - let tx = self.app_event_tx.clone(); - - tokio::task::spawn_blocking(move || { - let requested_path = PathBuf::from(path); - let event = match crate::windows_sandbox::grant_read_root_non_elevated( - &permission_profile, - workspace_roots.as_slice(), - command_cwd.as_path(), - &env_map, - codex_home.as_path(), - requested_path.as_path(), - ) { - Ok(canonical_path) => AppEvent::WindowsSandboxGrantReadRootCompleted { - path: canonical_path, - error: None, - }, - Err(err) => AppEvent::WindowsSandboxGrantReadRootCompleted { - path: requested_path, - error: Some(err.to_string()), - }, - }; - tx.send(event); - }); - } - #[cfg(not(target_os = "windows"))] - { - let _ = path; - } - } - AppEvent::WindowsSandboxGrantReadRootCompleted { path, error } => match error { - Some(err) => { - self.chat_widget - .add_to_history(history_cell::new_error_event(format!("Error: {err}"))); - } - None => { - self.chat_widget - .add_to_history(history_cell::new_info_event( - format!("Sandbox read access granted for {}", path.display()), - /*hint*/ None, - )); - } - }, AppEvent::EnableWindowsSandboxForAgentMode { preset, mode, diff --git a/codex-rs/tui/src/app_event.rs b/codex-rs/tui/src/app_event.rs index c397c98f64..3697ebb118 100644 --- a/codex-rs/tui/src/app_event.rs +++ b/codex-rs/tui/src/app_event.rs @@ -1231,19 +1231,6 @@ pub(crate) enum AppEvent { profile_selection: Option, }, - /// Begin a non-elevated grant of read access for an additional directory. - #[cfg_attr(not(target_os = "windows"), allow(dead_code))] - BeginWindowsSandboxGrantReadRoot { - path: String, - }, - - /// Result of attempting to grant read access for an additional directory. - #[cfg_attr(not(target_os = "windows"), allow(dead_code))] - WindowsSandboxGrantReadRootCompleted { - path: PathBuf, - error: Option, - }, - /// Enable the Windows sandbox feature and switch to Agent mode. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] EnableWindowsSandboxForAgentMode { diff --git a/codex-rs/tui/src/bottom_pane/chat_composer.rs b/codex-rs/tui/src/bottom_pane/chat_composer.rs index 85198a0ccd..05dbee3e91 100644 --- a/codex-rs/tui/src/bottom_pane/chat_composer.rs +++ b/codex-rs/tui/src/bottom_pane/chat_composer.rs @@ -423,7 +423,6 @@ fn parent_owned_command_is_allowed(command: SlashCommand, args: &str) -> bool { | SlashCommand::Vim | SlashCommand::Keymap | SlashCommand::ElevateSandbox - | SlashCommand::SandboxReadRoot | SlashCommand::Experimental | SlashCommand::Memories | SlashCommand::Quit diff --git a/codex-rs/tui/src/bottom_pane/command_popup.rs b/codex-rs/tui/src/bottom_pane/command_popup.rs index f577205eba..65d3976f12 100644 --- a/codex-rs/tui/src/bottom_pane/command_popup.rs +++ b/codex-rs/tui/src/bottom_pane/command_popup.rs @@ -414,7 +414,7 @@ mod tests { insta::assert_snapshot!("command_popup_app", format!("{buf:?}")); } - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "windows"))] #[test] fn voice_command_popup_snapshot() { let mut popup = CommandPopup::new( diff --git a/codex-rs/tui/src/chatwidget/slash_dispatch.rs b/codex-rs/tui/src/chatwidget/slash_dispatch.rs index 453aad4022..d9580abd57 100644 --- a/codex-rs/tui/src/chatwidget/slash_dispatch.rs +++ b/codex-rs/tui/src/chatwidget/slash_dispatch.rs @@ -411,11 +411,6 @@ impl ChatWidget { // Not supported; on non-Windows this command should never be reachable. } } - SlashCommand::SandboxReadRoot => { - self.add_error_message( - "Usage: /sandbox-add-read-dir ".to_string(), - ); - } SlashCommand::Experimental => { self.open_experimental_popup(); } @@ -1005,10 +1000,6 @@ impl ChatWidget { self.app_event_tx .send(AppEvent::ResumeSessionByIdOrName(args)); } - SlashCommand::SandboxReadRoot if !trimmed.is_empty() => { - self.app_event_tx - .send(AppEvent::BeginWindowsSandboxGrantReadRoot { path: args }); - } SlashCommand::Pets if matches!( args.trim().to_ascii_lowercase().as_str(), @@ -1228,7 +1219,6 @@ impl ChatWidget { | SlashCommand::MultiAgents | SlashCommand::Permissions | SlashCommand::ElevateSandbox - | SlashCommand::SandboxReadRoot | SlashCommand::Experimental | SlashCommand::AutoReview | SlashCommand::Memories diff --git a/codex-rs/tui/src/slash_command.rs b/codex-rs/tui/src/slash_command.rs index 93feadc318..d866c8feea 100644 --- a/codex-rs/tui/src/slash_command.rs +++ b/codex-rs/tui/src/slash_command.rs @@ -19,8 +19,6 @@ pub enum SlashCommand { Vim, #[strum(serialize = "setup-default-sandbox")] ElevateSandbox, - #[strum(serialize = "sandbox-add-read-dir")] - SandboxReadRoot, Experimental, #[strum(to_string = "approve")] AutoReview, @@ -142,9 +140,6 @@ impl SlashCommand { SlashCommand::Keymap => "remap TUI shortcuts", SlashCommand::Vim => "toggle Vim mode for the composer", SlashCommand::ElevateSandbox => "set up elevated agent sandbox", - SlashCommand::SandboxReadRoot => { - "let sandbox read a directory: /sandbox-add-read-dir " - } SlashCommand::Experimental => "toggle experimental features", SlashCommand::AutoReview => "approve one retry of a recent auto-review denial", SlashCommand::Memories => "configure memory use and generation", @@ -187,7 +182,6 @@ impl SlashCommand { | SlashCommand::Side | SlashCommand::Btw | SlashCommand::Resume - | SlashCommand::SandboxReadRoot ) } @@ -223,7 +217,6 @@ impl SlashCommand { | SlashCommand::Keymap | SlashCommand::Vim | SlashCommand::ElevateSandbox - | SlashCommand::SandboxReadRoot | SlashCommand::Experimental | SlashCommand::Memories | SlashCommand::Import @@ -275,7 +268,6 @@ impl SlashCommand { fn is_visible(self) -> bool { match self { - SlashCommand::SandboxReadRoot => cfg!(target_os = "windows"), SlashCommand::Copy => !cfg!(target_os = "android"), SlashCommand::App => cfg!(any(target_os = "macos", target_os = "windows")), SlashCommand::Voice => true, diff --git a/codex-rs/tui/src/windows_sandbox.rs b/codex-rs/tui/src/windows_sandbox.rs index 3786221a17..0a4d9e8199 100644 --- a/codex-rs/tui/src/windows_sandbox.rs +++ b/codex-rs/tui/src/windows_sandbox.rs @@ -2,9 +2,8 @@ //! //! TODO: These helpers inspect and modify the TUI host, so they do not support //! cross-platform remote app servers. Move readiness and setup to the existing -//! `windowsSandbox/*` RPCs while preserving the pending permission profile, -//! use the server platform reported during initialization, and add a remote -//! equivalent for read-root grants. +//! `windowsSandbox/*` RPCs while preserving the pending permission profile and +//! using the server platform reported during initialization. use crate::legacy_core::config::Config; use codex_config::types::WindowsSandboxModeToml; @@ -19,8 +18,6 @@ use codex_utils_absolute_path::AbsolutePathBuf; #[cfg(target_os = "windows")] use std::collections::HashMap; use std::path::Path; -#[cfg(target_os = "windows")] -use std::path::PathBuf; #[cfg(target_os = "windows")] pub(crate) fn record_world_writable_scan_result( @@ -113,35 +110,3 @@ pub(crate) fn elevated_setup_failure_metric_name(err: &anyhow::Error) -> &'stati "codex.windows_sandbox.elevated_setup_failure" } } - -#[cfg(target_os = "windows")] -pub(crate) fn grant_read_root_non_elevated( - permission_profile: &PermissionProfile, - workspace_roots: &[AbsolutePathBuf], - command_cwd: &Path, - env_map: &HashMap, - codex_home: &Path, - read_root: &Path, -) -> anyhow::Result { - if !read_root.is_absolute() { - anyhow::bail!("path must be absolute: {}", read_root.display()); - } - if !read_root.exists() { - anyhow::bail!("path does not exist: {}", read_root.display()); - } - if !read_root.is_dir() { - anyhow::bail!("path must be a directory: {}", read_root.display()); - } - - let canonical_root = dunce::canonicalize(read_root)?; - codex_windows_sandbox::run_setup_refresh_with_extra_read_roots( - permission_profile, - workspace_roots, - command_cwd, - env_map, - codex_home, - vec![canonical_root.clone()], - /*proxy_enforced*/ false, - )?; - Ok(canonical_root) -}