From 9eeb78e54f6deacbaa31ec7d45e0b69beb400462 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 19 Apr 2025 07:21:19 -0700 Subject: [PATCH] feat: allow switching approval modes when prompted to approve an edit/command (#400) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements https://github.com/openai/codex/issues/392 When the user is in suggest or auto-edit mode and gets an approval request, they now have an option in the `Shell Command` dialog to: `Switch approval mode (v)` That option brings up the standard `Switch approval mode` dialog, allowing the user to switch into the desired mode, then drops them back to the `Shell Command` dialog's `Allow command?` prompt, allowing them to approve the current command and let the agent continue doing the rest of what it was doing without interruption. ``` ╭──────────────────────────────────────────────────────── │Shell Command │ │$ apply_patch << 'PATCH' │*** Begin Patch │*** Update File: foo.txt │@@ -1 +1 @@ │-foo │+bar │*** End Patch │PATCH │ │ │Allow command? │ │ Yes (y) │ Explain this command (x) │ Edit or give feedback (e) │ Switch approval mode (v) │ No, and keep going (n) │ No, and stop for now (esc) ╰────────────────────────────────────────────────────────╭──────────────────────────────────────────────────────── │ Switch approval mode │ Current mode: suggest │ │ │ │ ❯ suggest │ auto-edit │ full-auto │ type to search · enter to confirm · esc to cancel ╰──────────────────────────────────────────────────────── ``` --- .../chat/terminal-chat-command-review.tsx | 28 +++++++++++++++++-- .../components/chat/terminal-chat-input.tsx | 4 +++ .../chat/terminal-chat-new-input.tsx | 4 +++ .../src/components/chat/terminal-chat.tsx | 19 +++++++++++-- 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/codex-cli/src/components/chat/terminal-chat-command-review.tsx b/codex-cli/src/components/chat/terminal-chat-command-review.tsx index 124178b0..eadb9071 100644 --- a/codex-cli/src/components/chat/terminal-chat-command-review.tsx +++ b/codex-cli/src/components/chat/terminal-chat-command-review.tsx @@ -15,11 +15,18 @@ const DEFAULT_DENY_MESSAGE = export function TerminalChatCommandReview({ confirmationPrompt, onReviewCommand, + // callback to switch approval mode overlay + onSwitchApprovalMode, explanation: propExplanation, + // whether this review Select is active (listening for keys) + isActive = true, }: { confirmationPrompt: React.ReactNode; onReviewCommand: (decision: ReviewDecision, customMessage?: string) => void; + onSwitchApprovalMode: () => void; explanation?: string; + // when false, disable the underlying Select so it won't capture input + isActive?: boolean; }): React.ReactElement { const [mode, setMode] = React.useState<"select" | "input" | "explanation">( "select", @@ -70,6 +77,7 @@ export function TerminalChatCommandReview({ const opts: Array< | { label: string; value: ReviewDecision } | { label: string; value: "edit" } + | { label: string; value: "switch" } > = [ { label: "Yes (y)", @@ -93,6 +101,11 @@ export function TerminalChatCommandReview({ label: "Edit or give feedback (e)", value: "edit", }, + // allow switching approval mode + { + label: "Switch approval mode (s)", + value: "switch", + }, { label: "No, and keep going (n)", value: ReviewDecision.NO_CONTINUE, @@ -106,7 +119,8 @@ export function TerminalChatCommandReview({ return opts; }, [showAlwaysApprove]); - useInput((input, key) => { + useInput( + (input, key) => { if (mode === "select") { if (input === "y") { onReviewCommand(ReviewDecision.YES); @@ -121,6 +135,9 @@ export function TerminalChatCommandReview({ ); } else if (input === "a" && showAlwaysApprove) { onReviewCommand(ReviewDecision.ALWAYS); + } else if (input === "s") { + // switch approval mode + onSwitchApprovalMode(); } else if (key.escape) { onReviewCommand(ReviewDecision.NO_EXIT); } @@ -143,7 +160,8 @@ export function TerminalChatCommandReview({ ); } } - }); + }, { isActive } + ); return ( @@ -191,9 +209,13 @@ export function TerminalChatCommandReview({ Allow command?