@@ -2816,7 +2816,7 @@ impl ChatWidget {
28162816 let is_current =
28172817 Self :: preset_matches_current ( current_approval, current_sandbox, & preset) ;
28182818 let name = if preset. id == "auto" && windows_degraded_sandbox_enabled {
2819- "Agent (degraded )" . to_string ( )
2819+ "Agent (non-elevated sandbox )" . to_string ( )
28202820 } else {
28212821 preset. label . to_string ( )
28222822 } ;
@@ -2897,8 +2897,8 @@ impl ChatWidget {
28972897
28982898 let footer_note = show_elevate_sandbox_hint. then ( || {
28992899 vec ! [
2900- "To upgrade to the elevated sandbox, run " . dim( ) ,
2901- "/elevate -sandbox" . cyan( ) ,
2900+ "The non-elevated sandbox protects your files and prevents network access under most circumstances. However, it carries greater risk if prompt injected. To upgrade to the elevated sandbox, run " . dim( ) ,
2901+ "/setup-elevated -sandbox" . cyan( ) ,
29022902 "." . dim( ) ,
29032903 ]
29042904 . into ( )
@@ -3230,40 +3230,59 @@ impl ChatWidget {
32303230 return ;
32313231 }
32323232
3233+ let current_approval = self . config . approval_policy . value ( ) ;
3234+ let current_sandbox = self . config . sandbox_policy . get ( ) ;
3235+ let presets = builtin_approval_presets ( ) ;
3236+ let stay_full_access = presets
3237+ . iter ( )
3238+ . find ( |preset| preset. id == "full-access" )
3239+ . is_some_and ( |preset| {
3240+ Self :: preset_matches_current ( current_approval, current_sandbox, preset)
3241+ } ) ;
3242+ let stay_actions = if stay_full_access {
3243+ Vec :: new ( )
3244+ } else {
3245+ presets
3246+ . iter ( )
3247+ . find ( |preset| preset. id == "read-only" )
3248+ . map ( |preset| {
3249+ Self :: approval_preset_actions ( preset. approval , preset. sandbox . clone ( ) )
3250+ } )
3251+ . unwrap_or_default ( )
3252+ } ;
3253+ let stay_label = if stay_full_access {
3254+ "Stay in Agent Full Access" . to_string ( )
3255+ } else {
3256+ "Stay in Read-Only" . to_string ( )
3257+ } ;
3258+
32333259 let mut header = ColumnRenderable :: new ( ) ;
32343260 header. push ( * Box :: new (
32353261 Paragraph :: new ( vec ! [
3236- line![ "Codex works best in Agent mode. " . bold( ) ] ,
3237- line![ "To use Agent mode on Windows, we need to configure the sandbox. " ] ,
3238- line![ "This setup requires elevation. Do you accept? " ] ,
3262+ line![ "Set Up Agent Sandbox " . bold( ) ] ,
3263+ line![ "" ] ,
3264+ line![ "Agent mode uses an experimental Windows sandbox that protects your files and prevents network access by default. " ] ,
32393265 line![ "Learn more: https://developers.openai.com/codex/windows" ] ,
32403266 ] )
32413267 . wrap ( Wrap { trim : false } ) ,
32423268 ) ) ;
32433269
3244- let preset_accept = preset. clone ( ) ;
3245- let preset_decline = preset;
32463270 let items = vec ! [
32473271 SelectionItem {
3248- name: "Yes, I accept " . to_string( ) ,
3272+ name: "Set up agent sandbox (requires elevation) " . to_string( ) ,
32493273 description: None ,
32503274 actions: vec![ Box :: new( move |tx| {
32513275 tx. send( AppEvent :: BeginWindowsSandboxElevatedSetup {
3252- preset: preset_accept . clone( ) ,
3276+ preset: preset . clone( ) ,
32533277 } ) ;
32543278 } ) ] ,
32553279 dismiss_on_select: true ,
32563280 ..Default :: default ( )
32573281 } ,
32583282 SelectionItem {
3259- name: "No, I do not accept" . to_string ( ) ,
3283+ name: stay_label ,
32603284 description: None ,
3261- actions: vec![ Box :: new( move |tx| {
3262- tx. send( AppEvent :: OpenWindowsSandboxFallbackPrompt {
3263- preset: preset_decline. clone( ) ,
3264- reason: WindowsSandboxFallbackReason :: DeclinedElevation ,
3265- } ) ;
3266- } ) ] ,
3285+ actions: stay_actions,
32673286 dismiss_on_select: true ,
32683287 ..Default :: default ( )
32693288 } ,
@@ -3289,53 +3308,75 @@ impl ChatWidget {
32893308 ) {
32903309 use ratatui_macros:: line;
32913310
3311+ let _ = reason;
3312+
3313+ let current_approval = self . config . approval_policy . value ( ) ;
3314+ let current_sandbox = self . config . sandbox_policy . get ( ) ;
3315+ let presets = builtin_approval_presets ( ) ;
3316+ let stay_full_access = presets
3317+ . iter ( )
3318+ . find ( |preset| preset. id == "full-access" )
3319+ . is_some_and ( |preset| {
3320+ Self :: preset_matches_current ( current_approval, current_sandbox, preset)
3321+ } ) ;
3322+ let stay_actions = if stay_full_access {
3323+ Vec :: new ( )
3324+ } else {
3325+ presets
3326+ . iter ( )
3327+ . find ( |preset| preset. id == "read-only" )
3328+ . map ( |preset| {
3329+ Self :: approval_preset_actions ( preset. approval , preset. sandbox . clone ( ) )
3330+ } )
3331+ . unwrap_or_default ( )
3332+ } ;
3333+ let stay_label = if stay_full_access {
3334+ "Stay in Agent Full Access" . to_string ( )
3335+ } else {
3336+ "Stay in Read-Only" . to_string ( )
3337+ } ;
3338+
32923339 let mut lines = Vec :: new ( ) ;
3293- if reason == WindowsSandboxFallbackReason :: ElevationFailed {
3294- lines. push ( line ! [ "The elevated setup did not complete." . bold( ) ] ) ;
3295- }
3296- lines. push ( line ! [
3297- "You can still use a degraded sandbox without elevation."
3298- ] ) ;
3299- lines. push ( line ! [ "It is less watertight, but still secure." ] ) ;
3340+ lines. push ( line ! [ "Use Non-Elevated Sandbox?" . bold( ) ] ) ;
3341+ lines. push ( line ! [ "" ] ) ;
33003342 lines. push ( line ! [
3301- "Learn more: https://developers.openai.com/codex/windows "
3343+ "Elevation failed. You can also use a non-elevated sandbox, which protects your files and prevents network access under most circumstances. However, it carries greater risk if prompt injected. "
33023344 ] ) ;
3345+ lines. push ( line ! [ "Learn more: https://developers.openai.com/codex/windows" ] ) ;
33033346
33043347 let mut header = ColumnRenderable :: new ( ) ;
33053348 header. push ( * Box :: new ( Paragraph :: new ( lines) . wrap ( Wrap { trim : false } ) ) ) ;
33063349
3307- let preset_retry = preset. clone ( ) ;
3308- let preset_degraded = preset;
3350+ let elevated_preset = preset. clone ( ) ;
3351+ let legacy_preset = preset. clone ( ) ;
33093352 let items = vec ! [
33103353 SelectionItem {
3311- name: "Try elevated setup again" . to_string( ) ,
3354+ name: "Try elevated agent sandbox setup again" . to_string( ) ,
33123355 description: None ,
33133356 actions: vec![ Box :: new( move |tx| {
33143357 tx. send( AppEvent :: BeginWindowsSandboxElevatedSetup {
3315- preset: preset_retry . clone( ) ,
3358+ preset: elevated_preset . clone( ) ,
33163359 } ) ;
33173360 } ) ] ,
33183361 dismiss_on_select: true ,
33193362 ..Default :: default ( )
33203363 } ,
33213364 SelectionItem {
3322- name: "Use degraded sandbox" . to_string( ) ,
3365+ name: "Use non-elevated agent sandbox" . to_string( ) ,
33233366 description: None ,
33243367 actions: vec![ Box :: new( move |tx| {
33253368 tx. send( AppEvent :: EnableWindowsSandboxForAgentMode {
3326- preset: preset_degraded . clone( ) ,
3369+ preset: legacy_preset . clone( ) ,
33273370 mode: WindowsSandboxEnableMode :: Legacy ,
33283371 } ) ;
33293372 } ) ] ,
33303373 dismiss_on_select: true ,
33313374 ..Default :: default ( )
33323375 } ,
33333376 SelectionItem {
3334- name: "Use no sandbox" . to_string ( ) ,
3377+ name: stay_label ,
33353378 description: None ,
3336- actions: vec![ Box :: new( |tx| {
3337- tx. send( AppEvent :: OpenApprovalsPopup ) ;
3338- } ) ] ,
3379+ actions: stay_actions,
33393380 dismiss_on_select: true ,
33403381 ..Default :: default ( )
33413382 } ,
@@ -3384,8 +3425,7 @@ impl ChatWidget {
33843425 self . bottom_pane . ensure_status_indicator ( ) ;
33853426 self . bottom_pane . set_interrupt_hint_visible ( false ) ;
33863427 self . set_status_header (
3387- "Setting up the elevated Windows sandbox (this may take a minute or more). You'll stay in your current mode until it's done."
3388- . to_string ( ) ,
3428+ "Setting up agent sandbox. This can take a minute." . to_string ( ) ,
33893429 ) ;
33903430 self . request_redraw ( ) ;
33913431 }
0 commit comments