feat: auto-approve pending tool calls when auto_edit/yolo is activated (#6665)

Co-authored-by: Jacob Richman <jacob314@gmail.com>
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
This commit is contained in:
Arya Gummadi
2025-09-14 20:20:21 -07:00
committed by GitHub
parent 00ecfdeb06
commit 1145f25ee3
5 changed files with 649 additions and 24 deletions
+51 -9
View File
@@ -31,6 +31,7 @@ import {
ConversationFinishedEvent,
ApprovalMode,
parseAndFormatApiError,
ToolConfirmationOutcome,
getCodeAssistServer,
UserTierId,
promptIdContext,
@@ -50,17 +51,16 @@ import { findLastSafeSplitPoint } from '../utils/markdownUtilities.js';
import { useStateAndRef } from './useStateAndRef.js';
import type { UseHistoryManagerReturn } from './useHistoryManager.js';
import { useLogger } from './useLogger.js';
import type {
TrackedToolCall,
TrackedCompletedToolCall,
TrackedCancelledToolCall,
} from './useReactToolScheduler.js';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import {
useReactToolScheduler,
mapToDisplay as mapTrackedToolCallsToDisplay,
type TrackedToolCall,
type TrackedCompletedToolCall,
type TrackedCancelledToolCall,
type TrackedWaitingToolCall,
} from './useReactToolScheduler.js';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import { useSessionStats } from '../contexts/SessionContext.js';
import { useKeypress } from './useKeypress.js';
import type { LoadedSettings } from '../../config/settings.js';
@@ -71,6 +71,8 @@ enum StreamProcessingStatus {
Error,
}
const EDIT_TOOL_NAMES = new Set(['replace', 'write_file']);
function showCitations(settings: LoadedSettings, config: Config): boolean {
const enabled = settings?.merged?.ui?.showCitations;
if (enabled !== undefined) {
@@ -847,6 +849,45 @@ export const useGeminiStream = (
],
);
const handleApprovalModeChange = useCallback(
async (newApprovalMode: ApprovalMode) => {
// Auto-approve pending tool calls when switching to auto-approval modes
if (
newApprovalMode === ApprovalMode.YOLO ||
newApprovalMode === ApprovalMode.AUTO_EDIT
) {
let awaitingApprovalCalls = toolCalls.filter(
(call): call is TrackedWaitingToolCall =>
call.status === 'awaiting_approval',
);
// For AUTO_EDIT mode, only approve edit tools (replace, write_file)
if (newApprovalMode === ApprovalMode.AUTO_EDIT) {
awaitingApprovalCalls = awaitingApprovalCalls.filter((call) =>
EDIT_TOOL_NAMES.has(call.request.name),
);
}
// Process pending tool calls sequentially to reduce UI chaos
for (const call of awaitingApprovalCalls) {
if (call.confirmationDetails?.onConfirm) {
try {
await call.confirmationDetails.onConfirm(
ToolConfirmationOutcome.ProceedOnce,
);
} catch (error) {
console.error(
`Failed to auto-approve tool call ${call.request.callId}:`,
error,
);
}
}
}
}
},
[toolCalls],
);
const handleCompletedTools = useCallback(
async (completedToolCallsFromScheduler: TrackedToolCall[]) => {
if (isResponding) {
@@ -981,8 +1022,7 @@ export const useGeminiStream = (
}
const restorableToolCalls = toolCalls.filter(
(toolCall) =>
(toolCall.request.name === 'replace' ||
toolCall.request.name === 'write_file') &&
EDIT_TOOL_NAMES.has(toolCall.request.name) &&
toolCall.status === 'awaiting_approval',
);
@@ -1101,6 +1141,8 @@ export const useGeminiStream = (
pendingHistoryItems,
thought,
cancelOngoingRequest,
pendingToolCalls: toolCalls,
handleApprovalModeChange,
activePtyId,
loopDetectionConfirmationRequest,
};