diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 5df79eff17..fadc843683 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -2921,6 +2921,54 @@ impl App { let _ = preset; } } + AppEvent::BeginWindowsSandboxLegacySetup { preset } => { + #[cfg(target_os = "windows")] + { + let policy = preset.sandbox.clone(); + let policy_cwd = self.config.cwd.clone(); + let command_cwd = policy_cwd.clone(); + let env_map: std::collections::HashMap = + std::env::vars().collect(); + let codex_home = self.config.codex_home.clone(); + + let result = tokio::task::spawn_blocking(move || { + codex_core::windows_sandbox::run_legacy_setup_preflight( + &policy, + policy_cwd.as_path(), + command_cwd.as_path(), + &env_map, + codex_home.as_path(), + ) + }) + .await + .map_err(|join_err| { + anyhow::anyhow!("legacy Windows sandbox setup task failed: {join_err}") + })?; + + match result { + Ok(()) => { + self.app_event_tx + .send(AppEvent::EnableWindowsSandboxForAgentMode { + preset, + mode: WindowsSandboxEnableMode::Legacy, + }); + } + Err(err) => { + tracing::error!( + error = %err, + "failed to run legacy Windows sandbox setup preflight" + ); + self.chat_widget.add_error_message(format!( + "Failed to enable the Windows sandbox feature: {err}" + )); + } + } + } + #[cfg(not(target_os = "windows"))] + { + let _ = preset; + } + } AppEvent::BeginWindowsSandboxGrantReadRoot { path } => { #[cfg(target_os = "windows")] { diff --git a/codex-rs/tui/src/app_event.rs b/codex-rs/tui/src/app_event.rs index 04968f68d9..a15e0b068e 100644 --- a/codex-rs/tui/src/app_event.rs +++ b/codex-rs/tui/src/app_event.rs @@ -294,6 +294,12 @@ pub(crate) enum AppEvent { preset: ApprovalPreset, }, + /// Begin the non-elevated Windows sandbox setup flow. + #[cfg_attr(not(target_os = "windows"), allow(dead_code))] + BeginWindowsSandboxLegacySetup { + preset: ApprovalPreset, + }, + /// Begin a non-elevated grant of read access for an additional directory. #[cfg_attr(not(target_os = "windows"), allow(dead_code))] BeginWindowsSandboxGrantReadRoot { diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index ef526b3821..72eb278da3 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -4910,9 +4910,8 @@ impl ChatWidget { .send(AppEvent::BeginWindowsSandboxElevatedSetup { preset }); } WindowsSandboxEnableMode::Legacy => { - self.app_event_tx.send( - AppEvent::EnableWindowsSandboxForAgentMode { preset, mode }, - ); + self.app_event_tx + .send(AppEvent::BeginWindowsSandboxLegacySetup { preset }); } } return QueueReplayControl::Stop; @@ -8771,9 +8770,8 @@ impl ChatWidget { name: "Enable experimental sandbox".to_string(), description: None, actions: vec![Box::new(move |tx| { - tx.send(AppEvent::EnableWindowsSandboxForAgentMode { + tx.send(AppEvent::BeginWindowsSandboxLegacySetup { preset: preset_clone.clone(), - mode: WindowsSandboxEnableMode::Legacy, }); })], dismiss_on_select: true, diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 15a1b97f86..9a01505291 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -9147,6 +9147,22 @@ async fn approvals_elevated_inline_args_start_windows_sandbox_setup() { ); } +#[cfg(target_os = "windows")] +#[tokio::test] +async fn approvals_legacy_inline_args_start_windows_sandbox_setup() { + let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await; + chat.set_windows_sandbox_mode(None); + chat.handle_serialized_slash_command(ChatWidget::approval_preset_draft( + "auto", + &["--enable-windows-sandbox=legacy"], + )); + + assert_matches!( + rx.try_recv(), + Ok(AppEvent::BeginWindowsSandboxLegacySetup { preset }) if preset.id == "auto" + ); +} + #[tokio::test] async fn permissions_selection_history_snapshot_after_mode_switch() { let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;