This commit is contained in:
Dylan Hurd
2026-01-20 14:40:56 -08:00
parent df6a95ce9c
commit 24ab98ed85
6 changed files with 43 additions and 12 deletions

View File

@@ -38,7 +38,7 @@ pub fn builtin_approval_presets() -> Vec<ApprovalPreset> {
ApprovalPreset {
id: "full-access",
label: "Agent (full access)",
description: "Codex can edit files outside this workspace and run commands with network access. Exercise caution when using.",
description: "Codex can edit files outside this workspace and access the internet. Exercise caution when using.",
approval: AskForApproval::Never,
sandbox: SandboxPolicy::DangerFullAccess,
},

View File

@@ -997,8 +997,12 @@ impl App {
AppEvent::OpenAllModelsPopup { models } => {
self.chat_widget.open_all_models_popup(models);
}
AppEvent::OpenFullAccessConfirmation { preset } => {
self.chat_widget.open_full_access_confirmation(preset);
AppEvent::OpenFullAccessConfirmation {
preset,
return_to_permissions,
} => {
self.chat_widget
.open_full_access_confirmation(preset, return_to_permissions);
}
AppEvent::OpenWorldWritableWarningConfirmation {
preset,
@@ -1383,6 +1387,9 @@ impl App {
AppEvent::OpenApprovalsPopup => {
self.chat_widget.open_approvals_popup();
}
AppEvent::OpenPermissionsPopup => {
self.chat_widget.open_permissions_popup();
}
AppEvent::OpenReviewBranchPicker(cwd) => {
self.chat_widget.show_review_branch_picker(&cwd).await;
}

View File

@@ -125,6 +125,7 @@ pub(crate) enum AppEvent {
/// Open the confirmation prompt before enabling full access mode.
OpenFullAccessConfirmation {
preset: ApprovalPreset,
return_to_permissions: bool,
},
/// Open the Windows world-writable directories warning.
@@ -212,6 +213,9 @@ pub(crate) enum AppEvent {
/// Re-open the approval presets popup.
OpenApprovalsPopup,
/// Re-open the permissions presets popup.
OpenPermissionsPopup,
/// Open the branch picker option from the review popup.
OpenReviewBranchPicker(PathBuf),

View File

@@ -3525,6 +3525,7 @@ impl ChatWidget {
self.open_approval_mode_popup(
"Update Model Permissions",
true,
false,
|preset, is_windows_degraded| {
if preset.id == "auto" && is_windows_degraded {
"Agent (non-elevated sandbox)".to_string()
@@ -3532,6 +3533,7 @@ impl ChatWidget {
preset.label.to_string()
}
},
|preset| preset.description.to_string(),
);
}
@@ -3541,22 +3543,32 @@ impl ChatWidget {
self.open_approval_mode_popup(
"Update Model Permissions",
include_read_only,
true,
|preset, _| match preset.id {
"read-only" => "Read Only".to_string(),
"auto" => "Default".to_string(),
"full-access" => "Full Access".to_string(),
_ => preset.label.to_string(),
},
|preset| match preset.id {
"auto" => {
format!("{} Identical to Agent approvals.", preset.description)
}
_ => preset.description.to_string(),
},
);
}
fn open_approval_mode_popup<F>(
fn open_approval_mode_popup<F, D>(
&mut self,
title: &str,
include_read_only: bool,
return_to_permissions: bool,
label_for_preset: F,
description_for_preset: D,
) where
F: Fn(&ApprovalPreset, bool) -> String,
D: Fn(&ApprovalPreset) -> String,
{
let current_approval = self.config.approval_policy.value();
let current_sandbox = self.config.sandbox_policy.get();
@@ -3580,7 +3592,7 @@ impl ChatWidget {
let is_current =
Self::preset_matches_current(current_approval, current_sandbox, &preset);
let name = label_for_preset(&preset, windows_degraded_sandbox_enabled);
let description = Some(preset.description.to_string());
let description = Some(description_for_preset(&preset));
let disabled_reason = match self.config.approval_policy.can_set(&preset.approval) {
Ok(()) => None,
Err(err) => Some(err.to_string()),
@@ -3596,6 +3608,7 @@ impl ChatWidget {
vec![Box::new(move |tx| {
tx.send(AppEvent::OpenFullAccessConfirmation {
preset: preset_clone.clone(),
return_to_permissions,
});
})]
} else if preset.id == "auto" {
@@ -3765,7 +3778,11 @@ impl ChatWidget {
None
}
pub(crate) fn open_full_access_confirmation(&mut self, preset: ApprovalPreset) {
pub(crate) fn open_full_access_confirmation(
&mut self,
preset: ApprovalPreset,
return_to_permissions: bool,
) {
let approval = preset.approval;
let sandbox = preset.sandbox;
let mut header_children: Vec<Box<dyn Renderable>> = Vec::new();
@@ -3793,8 +3810,12 @@ impl ChatWidget {
tx.send(AppEvent::PersistFullAccessWarningAcknowledged);
}));
let deny_actions: Vec<SelectionAction> = vec![Box::new(|tx| {
tx.send(AppEvent::OpenApprovalsPopup);
let deny_actions: Vec<SelectionAction> = vec![Box::new(move |tx| {
if return_to_permissions {
tx.send(AppEvent::OpenPermissionsPopup);
} else {
tx.send(AppEvent::OpenApprovalsPopup);
}
})];
let items = vec![

View File

@@ -6,8 +6,7 @@ expression: popup
1. Read Only (current) Requires approval to edit files and run commands.
2. Agent Read and edit files, and run commands.
3. Agent (full access) Codex can edit files outside this workspace and run
commands with network access. Exercise caution when
using.
3. Agent (full access) Codex can edit files outside this workspace and
access the internet. Exercise caution when using.
Press enter to confirm or esc to go back

View File

@@ -2689,7 +2689,7 @@ async fn full_access_confirmation_popup_snapshot() {
.into_iter()
.find(|preset| preset.id == "full-access")
.expect("full access preset");
chat.open_full_access_confirmation(preset);
chat.open_full_access_confirmation(preset, false);
let popup = render_bottom_popup(&chat, 80);
assert_snapshot!("full_access_confirmation_popup", popup);