From 30934abec56d9d5a7e273ca030d71709e730612d Mon Sep 17 00:00:00 2001 From: Alexander Embiricos Date: Tue, 18 Nov 2025 21:05:50 -0800 Subject: [PATCH 1/4] feat: tweak windows sandbox strings --- codex-rs/tui/src/app.rs | 9 ++-- codex-rs/tui/src/app_event.rs | 6 +-- codex-rs/tui/src/chatwidget.rs | 72 ++++++++++++---------------- codex-rs/tui/src/chatwidget/tests.rs | 10 ++-- 4 files changed, 44 insertions(+), 53 deletions(-) diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 718c33af3c..2921ff3a75 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -293,7 +293,7 @@ impl App { skip_world_writable_scan_once: false, }; - // On startup, if Auto mode (workspace-write) or ReadOnly is active, warn about world-writable dirs on Windows. + // On startup, if Agent mode (workspace-write) or ReadOnly is active, warn about world-writable dirs on Windows. #[cfg(target_os = "windows")] { let should_check = codex_core::get_platform_sandbox().is_some() @@ -546,7 +546,7 @@ impl App { AppEvent::OpenWindowsSandboxEnablePrompt { preset } => { self.chat_widget.open_windows_sandbox_enable_prompt(preset); } - AppEvent::EnableWindowsSandboxForAuto { preset } => { + AppEvent::EnableWindowsSandboxForAgentMode { preset } => { #[cfg(target_os = "windows")] { let profile = self.active_profile.as_deref(); @@ -587,8 +587,7 @@ impl App { self.app_event_tx .send(AppEvent::UpdateSandboxPolicy(preset.sandbox.clone())); self.chat_widget.add_info_message( - "Enabled the Windows sandbox feature and switched to Auto mode." - .to_string(), + "Enabled experimental Windows sandbox.".to_string(), None, ); } @@ -732,7 +731,7 @@ impl App { "failed to persist world-writable warning acknowledgement" ); self.chat_widget.add_error_message(format!( - "Failed to save Auto mode warning preference: {err}" + "Failed to save Agent mode warning preference: {err}" )); } } diff --git a/codex-rs/tui/src/app_event.rs b/codex-rs/tui/src/app_event.rs index e786372524..cf494f57d6 100644 --- a/codex-rs/tui/src/app_event.rs +++ b/codex-rs/tui/src/app_event.rs @@ -91,15 +91,15 @@ pub(crate) enum AppEvent { failed_scan: bool, }, - /// Prompt to enable the Windows sandbox feature before using Auto mode. + /// Prompt to enable the Windows sandbox feature before using Agent mode. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] OpenWindowsSandboxEnablePrompt { preset: ApprovalPreset, }, - /// Enable the Windows sandbox feature and switch to Auto mode. + /// Enable the Windows sandbox feature and switch to Agent mode. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] - EnableWindowsSandboxForAuto { + EnableWindowsSandboxForAgentMode { preset: ApprovalPreset, }, diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index c17eea92dc..41068d635d 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -2169,11 +2169,6 @@ impl ChatWidget { let current_sandbox = self.config.sandbox_policy.clone(); let mut items: Vec = Vec::new(); let presets: Vec = builtin_approval_presets(); - #[cfg(target_os = "windows")] - let forced_windows_read_only = self.config.forced_auto_mode_downgraded_on_windows - && codex_core::get_platform_sandbox().is_none(); - #[cfg(not(target_os = "windows"))] - let forced_windows_read_only = false; for preset in presets.into_iter() { let is_current = current_approval == preset.approval && current_sandbox == preset.sandbox; @@ -2237,14 +2232,7 @@ impl ChatWidget { } self.bottom_pane.show_selection_view(SelectionViewParams { - title: Some( - if forced_windows_read_only { - "Select approval mode (Codex changed your permissions to Read Only because the Windows sandbox is off)" - .to_string() - } else { - "Select Approval Mode".to_string() - }, - ), + title: Some("Select Approval Mode".to_string()), footer_hint: Some(standard_popup_hint_line()), items, header: Box::new(()), @@ -2368,9 +2356,9 @@ impl ChatWidget { }; let mut header_children: Vec> = Vec::new(); let mode_label = match self.config.sandbox_policy { - SandboxPolicy::WorkspaceWrite { .. } => "Auto mode", + SandboxPolicy::WorkspaceWrite { .. } => "Agent mode", SandboxPolicy::ReadOnly => "Read-Only mode", - _ => "Auto mode", + _ => "Agent mode", }; let info_line = if failed_scan { Line::from(vec![ @@ -2471,36 +2459,36 @@ impl ChatWidget { let mut header = ColumnRenderable::new(); header.push(line![ - "Auto mode requires the experimental Windows sandbox.".bold(), - " Turn it on to enable sandboxed commands on Windows." + "Agent mode on Windows uses an experimental sandbox".bold() + ]); + header.push(line!["to limit network and filesystem access.".bold()]); + header.push(line![ + "Learn more: https://github.com/openai/codex/blob/main/docs/sandbox.md#windows" ]); let preset_clone = preset; - let items = vec![SelectionItem { - name: "Turn on Windows sandbox and use Auto mode".to_string(), - description: Some( - "Adds enable_experimental_windows_sandbox = true to config.toml and switches to Auto mode." - .to_string(), - ), - actions: vec![Box::new(move |tx| { - tx.send(AppEvent::EnableWindowsSandboxForAuto { - preset: preset_clone.clone(), - }); - })], - dismiss_on_select: true, - ..Default::default() - }, SelectionItem { - name: "Go Back".to_string(), - description: Some( - "Stay on read-only or full access without enabling the sandbox feature." - .to_string(), - ), - actions: vec![Box::new(|tx| { - tx.send(AppEvent::OpenApprovalsPopup); - })], - dismiss_on_select: true, - ..Default::default() - }]; + let items = vec![ + SelectionItem { + name: "Enable experimental sandbox".to_string(), + description: None, + actions: vec![Box::new(move |tx| { + tx.send(AppEvent::EnableWindowsSandboxForAuto { + preset: preset_clone.clone(), + }); + })], + dismiss_on_select: true, + ..Default::default() + }, + SelectionItem { + name: "Go back".to_string(), + description: None, + actions: vec![Box::new(|tx| { + tx.send(AppEvent::OpenApprovalsPopup); + })], + dismiss_on_select: true, + ..Default::default() + }, + ]; self.bottom_pane.show_selection_view(SelectionViewParams { title: None, diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index d6d8f0248d..253ad4d7cc 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -1490,14 +1490,14 @@ fn windows_auto_mode_prompt_requests_enabling_sandbox_feature() { let popup = render_bottom_popup(&chat, 120); assert!( - popup.contains("experimental Windows sandbox"), + popup.contains("Agent mode on Windows uses an experimental sandbox"), "expected auto mode prompt to mention enabling the sandbox feature, popup: {popup}" ); } #[cfg(target_os = "windows")] #[test] -fn startup_prompts_for_windows_sandbox_when_auto_requested() { +fn startup_prompts_for_windows_sandbox_when_agent_requested() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(); set_windows_sandbox_enabled(false); @@ -1507,7 +1507,11 @@ fn startup_prompts_for_windows_sandbox_when_auto_requested() { let popup = render_bottom_popup(&chat, 120); assert!( - popup.contains("Turn on Windows sandbox and use Auto mode"), + popup.contains("Agent mode on Windows uses an experimental sandbox"), + "expected startup prompt to explain sandbox: {popup}" + ); + assert!( + popup.contains("Enable experimental sandbox"), "expected startup prompt to offer enabling the sandbox: {popup}" ); From 8acbb48d38eedeea32d47509fcebc6f14179c47f Mon Sep 17 00:00:00 2001 From: Alexander Embiricos Date: Tue, 18 Nov 2025 21:13:30 -0800 Subject: [PATCH 2/4] tweak world writable warning --- codex-rs/tui/src/chatwidget.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 41068d635d..3872c4b475 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -2369,11 +2369,8 @@ impl ChatWidget { ]) } else { Line::from(vec![ - "Some important directories on this system are world-writable. ".into(), - format!( - "The Windows sandbox cannot protect writes to these locations in {mode_label}." - ) - .fg(Color::Red), + "The Windows sandbox cannot protect writes to folders that are writable by Everyone.".into(), + "Consider removing write access for Everyone from the following folders:" ]) }; header_children.push(Box::new( @@ -2383,7 +2380,6 @@ impl ChatWidget { if !sample_paths.is_empty() { // Show up to three examples and optionally an "and X more" line. let mut lines: Vec = Vec::new(); - lines.push(Line::from("Examples:").bold()); lines.push(Line::from("")); for p in &sample_paths { lines.push(Line::from(format!(" - {p}"))); From 3fe8b00196b51e57933e32658a0ea0da500ed73f Mon Sep 17 00:00:00 2001 From: Alexander Embiricos Date: Tue, 18 Nov 2025 21:26:57 -0800 Subject: [PATCH 3/4] Add a space --- codex-rs/tui/src/chatwidget.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 3872c4b475..0d5e7b43e6 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -2370,7 +2370,7 @@ impl ChatWidget { } else { Line::from(vec![ "The Windows sandbox cannot protect writes to folders that are writable by Everyone.".into(), - "Consider removing write access for Everyone from the following folders:" + " Consider removing write access for Everyone from the following folders:" ]) }; header_children.push(Box::new( From 196b6790cee783a209b922b746e2818d80e52038 Mon Sep 17 00:00:00 2001 From: iceweasel-oai Date: Tue, 18 Nov 2025 21:45:10 -0800 Subject: [PATCH 4/4] wrap sandbox enable prompt, fix labels on world-writable warning choices --- codex-rs/tui/src/chatwidget.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 0d5e7b43e6..78ea73c129 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -2355,11 +2355,15 @@ impl ChatWidget { None => (None, None), }; let mut header_children: Vec> = Vec::new(); - let mode_label = match self.config.sandbox_policy { + let describe_policy = |policy: &SandboxPolicy| match policy { SandboxPolicy::WorkspaceWrite { .. } => "Agent mode", SandboxPolicy::ReadOnly => "Read-Only mode", _ => "Agent mode", }; + let mode_label = preset + .as_ref() + .map(|p| describe_policy(&p.sandbox)) + .unwrap_or_else(|| describe_policy(&self.config.sandbox_policy)); let info_line = if failed_scan { Line::from(vec![ "We couldn't complete the world-writable scan, so protections cannot be verified. " @@ -2370,7 +2374,7 @@ impl ChatWidget { } else { Line::from(vec![ "The Windows sandbox cannot protect writes to folders that are writable by Everyone.".into(), - " Consider removing write access for Everyone from the following folders:" + " Consider removing write access for Everyone from the following folders:".into(), ]) }; header_children.push(Box::new( @@ -2454,13 +2458,15 @@ impl ChatWidget { use ratatui_macros::line; let mut header = ColumnRenderable::new(); - header.push(line![ - "Agent mode on Windows uses an experimental sandbox".bold() - ]); - header.push(line!["to limit network and filesystem access.".bold()]); - header.push(line![ - "Learn more: https://github.com/openai/codex/blob/main/docs/sandbox.md#windows" - ]); + header.push(*Box::new( + Paragraph::new(vec![ + line!["Agent mode on Windows uses an experimental sandbox to limit network and filesystem access.".bold()], + line![ + "Learn more: https://github.com/openai/codex/blob/main/docs/sandbox.md#windows" + ], + ]) + .wrap(Wrap { trim: false }), + )); let preset_clone = preset; let items = vec![ @@ -2468,7 +2474,7 @@ impl ChatWidget { name: "Enable experimental sandbox".to_string(), description: None, actions: vec![Box::new(move |tx| { - tx.send(AppEvent::EnableWindowsSandboxForAuto { + tx.send(AppEvent::EnableWindowsSandboxForAgentMode { preset: preset_clone.clone(), }); })],