feat: allow switching approval modes when prompted to approve an edit/command (#400)

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 
╰────────────────────────────────────────────────────────
```
This commit is contained in:
Scott Leibrand
2025-04-19 07:21:19 -07:00
committed by GitHub
parent 6c7fbc7b94
commit 9eeb78e54f
4 changed files with 49 additions and 6 deletions

View File

@@ -206,6 +206,13 @@ export default function TerminalChat({
}
useEffect(() => {
// Skip recreating the agent if awaiting a decision on a pending confirmation
if (confirmationPrompt != null) {
if (isLoggingEnabled()) {
log("skip AgentLoop recreation due to pending confirmationPrompt");
}
return;
}
if (isLoggingEnabled()) {
log("creating NEW AgentLoop");
log(
@@ -293,10 +300,12 @@ export default function TerminalChat({
agentRef.current = undefined;
forceUpdate(); // rerender after teardown too
};
// We intentionally omit 'approvalPolicy' and 'confirmationPrompt' from the deps
// so switching modes or showing confirmation dialogs doesnt tear down the loop.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
model,
config,
approvalPolicy,
requestConfirmation,
additionalWritableRoots,
]);
@@ -580,12 +589,16 @@ export default function TerminalChat({
<ApprovalModeOverlay
currentMode={approvalPolicy}
onSelect={(newMode) => {
agent?.cancel();
setLoading(false);
// update approval policy without cancelling an in-progress session
if (newMode === approvalPolicy) {
return;
}
// update state
setApprovalPolicy(newMode as ApprovalPolicy);
// update existing AgentLoop instance
if (agentRef.current) {
(agentRef.current as unknown as { approvalPolicy: ApprovalPolicy }).approvalPolicy = newMode as ApprovalPolicy;
}
setItems((prev) => [
...prev,
{