feat: add double Ctrl+C to exit from approval screen (#200)
Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -2561,6 +2561,32 @@ ${recentCommits}
|
||||
],
|
||||
);
|
||||
|
||||
// Cancel all pending approvals - queue denials to send with next message
|
||||
// Similar to interrupt flow during tool execution
|
||||
const handleCancelApprovals = useCallback(() => {
|
||||
if (pendingApprovals.length === 0) return;
|
||||
|
||||
// Create denial results for all pending approvals and queue for next message
|
||||
const denialResults = pendingApprovals.map((approval) => ({
|
||||
type: "approval" as const,
|
||||
tool_call_id: approval.toolCallId,
|
||||
approve: false,
|
||||
reason: "User cancelled the approval",
|
||||
}));
|
||||
setQueuedApprovalResults(denialResults);
|
||||
|
||||
// Mark the pending approval tool calls as cancelled in the buffers
|
||||
markIncompleteToolsAsCancelled(buffersRef.current);
|
||||
refreshDerived();
|
||||
|
||||
// Clear all approval state
|
||||
setPendingApprovals([]);
|
||||
setApprovalContexts([]);
|
||||
setApprovalResults([]);
|
||||
setAutoHandledResults([]);
|
||||
setAutoDeniedApprovals([]);
|
||||
}, [pendingApprovals, refreshDerived]);
|
||||
|
||||
const handleModelSelect = useCallback(
|
||||
async (modelId: string) => {
|
||||
setModelSelectorOpen(false);
|
||||
@@ -3447,6 +3473,7 @@ Plan file path: ${planFilePath}`;
|
||||
onApproveAll={handleApproveCurrent}
|
||||
onApproveAlways={handleApproveAlways}
|
||||
onDenyAll={handleDenyCurrent}
|
||||
onCancel={handleCancelApprovals}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -19,6 +19,7 @@ type Props = {
|
||||
onApproveAll: () => void;
|
||||
onApproveAlways: (scope?: "project" | "session") => void;
|
||||
onDenyAll: (reason: string) => void;
|
||||
onCancel?: () => void; // Cancel all approvals without sending to server
|
||||
};
|
||||
|
||||
type DynamicPreviewProps = {
|
||||
@@ -397,6 +398,7 @@ export const ApprovalDialog = memo(function ApprovalDialog({
|
||||
onApproveAll,
|
||||
onApproveAlways,
|
||||
onDenyAll,
|
||||
onCancel,
|
||||
}: Props) {
|
||||
const [selectedOption, setSelectedOption] = useState(0);
|
||||
const [isEnteringReason, setIsEnteringReason] = useState(false);
|
||||
@@ -453,6 +455,14 @@ export const ApprovalDialog = memo(function ApprovalDialog({
|
||||
useInput((_input, key) => {
|
||||
if (isExecuting) return;
|
||||
|
||||
// Handle CTRL-C to cancel all approvals
|
||||
if (key.ctrl && _input === "c") {
|
||||
if (onCancel) {
|
||||
onCancel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEnteringReason) {
|
||||
// When entering reason, only handle enter/escape
|
||||
if (key.return) {
|
||||
|
||||
Reference in New Issue
Block a user