From 7e6316d4aa321287d4f7d0115b5e8954acd670bf Mon Sep 17 00:00:00 2001 From: ae Date: Tue, 18 Nov 2025 22:00:06 -0800 Subject: [PATCH] feat: tweak windows sandbox strings (#6875) New strings: 1. Approval mode picker just says "Select Approval Mode" 1. Updated "Auto" to "Agent" 1. When you select "Agent", you get "Agent mode on Windows uses an experimental sandbox to limit network and filesystem access. [Learn more]" 1. Updated world-writable warning to "The Windows sandbox cannot protect writes to folders that are writable by Everyone. Consider removing write access for Everyone from the following folders: {folders}" --------- Co-authored-by: iceweasel-oai --- codex-rs/tui/src/app.rs | 9 ++- codex-rs/tui/src/app_event.rs | 6 +- codex-rs/tui/src/chatwidget.rs | 92 +++++++++++++--------------- codex-rs/tui/src/chatwidget/tests.rs | 10 ++- 4 files changed, 55 insertions(+), 62 deletions(-) diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 32c466db57..cc17598284 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..78ea73c129 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(()), @@ -2367,11 +2355,15 @@ impl ChatWidget { None => (None, None), }; let mut header_children: Vec> = Vec::new(); - let mode_label = match self.config.sandbox_policy { - SandboxPolicy::WorkspaceWrite { .. } => "Auto mode", + let describe_policy = |policy: &SandboxPolicy| match policy { + SandboxPolicy::WorkspaceWrite { .. } => "Agent mode", SandboxPolicy::ReadOnly => "Read-Only mode", - _ => "Auto 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. " @@ -2381,11 +2373,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:".into(), ]) }; header_children.push(Box::new( @@ -2395,7 +2384,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}"))); @@ -2470,37 +2458,39 @@ impl ChatWidget { use ratatui_macros::line; 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." - ]); + 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![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::EnableWindowsSandboxForAgentMode { + 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 bad8f24c30..6494120bff 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -1494,14 +1494,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); @@ -1511,7 +1511,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}" );