From 882a97aff998b2f19731e9966d135f1db5a59914 Mon Sep 17 00:00:00 2001 From: agarwalravikant Date: Wed, 6 Aug 2025 23:16:42 +0530 Subject: [PATCH] =?UTF-8?q?Fix=20to=20send=20user=20tool=20confirmation=20?= =?UTF-8?q?decision=20for=20yolo=20or=20non=20interacti=E2=80=A6=20(#5677)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ravikant Agarwal --- packages/core/src/core/coreToolScheduler.ts | 26 ++++++++++++++----- .../src/core/nonInteractiveToolExecutor.ts | 2 ++ packages/core/src/telemetry/metrics.ts | 2 +- packages/core/src/telemetry/types.ts | 4 ++- .../core/src/telemetry/uiTelemetry.test.ts | 6 +++++ packages/core/src/telemetry/uiTelemetry.ts | 4 +++ 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/core/src/core/coreToolScheduler.ts b/packages/core/src/core/coreToolScheduler.ts index f54aa532..9b999b6b 100644 --- a/packages/core/src/core/coreToolScheduler.ts +++ b/packages/core/src/core/coreToolScheduler.ts @@ -468,6 +468,10 @@ export class CoreToolScheduler { const { request: reqInfo, tool: toolInstance } = toolCall; try { if (this.config.getApprovalMode() === ApprovalMode.YOLO) { + this.setToolCallOutcome( + reqInfo.callId, + ToolConfirmationOutcome.ProceedAlways, + ); this.setStatusInternal(reqInfo.callId, 'scheduled'); } else { const confirmationDetails = await toolInstance.shouldConfirmExecute( @@ -521,6 +525,10 @@ export class CoreToolScheduler { wrappedConfirmationDetails, ); } else { + this.setToolCallOutcome( + reqInfo.callId, + ToolConfirmationOutcome.ProceedAlways, + ); this.setStatusInternal(reqInfo.callId, 'scheduled'); } } @@ -555,13 +563,7 @@ export class CoreToolScheduler { await originalOnConfirm(outcome); } - this.toolCalls = this.toolCalls.map((call) => { - if (call.request.callId !== callId) return call; - return { - ...call, - outcome, - }; - }); + this.setToolCallOutcome(callId, outcome); if (outcome === ToolConfirmationOutcome.Cancel || signal.aborted) { this.setStatusInternal( @@ -774,4 +776,14 @@ export class CoreToolScheduler { this.onToolCallsUpdate([...this.toolCalls]); } } + + private setToolCallOutcome(callId: string, outcome: ToolConfirmationOutcome) { + this.toolCalls = this.toolCalls.map((call) => { + if (call.request.callId !== callId) return call; + return { + ...call, + outcome, + }; + }); + } } diff --git a/packages/core/src/core/nonInteractiveToolExecutor.ts b/packages/core/src/core/nonInteractiveToolExecutor.ts index 52704bf1..ed235cd3 100644 --- a/packages/core/src/core/nonInteractiveToolExecutor.ts +++ b/packages/core/src/core/nonInteractiveToolExecutor.ts @@ -14,6 +14,7 @@ import { } from '../index.js'; import { Config } from '../config/config.js'; import { convertToFunctionResponse } from './coreToolScheduler.js'; +import { ToolCallDecision } from '../telemetry/types.js'; /** * Executes a single tool call non-interactively. @@ -87,6 +88,7 @@ export async function executeToolCall( error_type: toolResult.error === undefined ? undefined : toolResult.error.type, prompt_id: toolCallRequest.prompt_id, + decision: ToolCallDecision.AUTO_ACCEPT, }); const response = convertToFunctionResponse( diff --git a/packages/core/src/telemetry/metrics.ts b/packages/core/src/telemetry/metrics.ts index 124bc602..103f7f71 100644 --- a/packages/core/src/telemetry/metrics.ts +++ b/packages/core/src/telemetry/metrics.ts @@ -100,7 +100,7 @@ export function recordToolCallMetrics( functionName: string, durationMs: number, success: boolean, - decision?: 'accept' | 'reject' | 'modify', + decision?: 'accept' | 'reject' | 'modify' | 'auto_accept', ): void { if (!toolCallCounter || !toolCallLatencyHistogram || !isMetricsInitialized) return; diff --git a/packages/core/src/telemetry/types.ts b/packages/core/src/telemetry/types.ts index 668421f0..db84e2da 100644 --- a/packages/core/src/telemetry/types.ts +++ b/packages/core/src/telemetry/types.ts @@ -14,6 +14,7 @@ export enum ToolCallDecision { ACCEPT = 'accept', REJECT = 'reject', MODIFY = 'modify', + AUTO_ACCEPT = 'auto_accept', } export function getDecisionFromOutcome( @@ -21,10 +22,11 @@ export function getDecisionFromOutcome( ): ToolCallDecision { switch (outcome) { case ToolConfirmationOutcome.ProceedOnce: + return ToolCallDecision.ACCEPT; case ToolConfirmationOutcome.ProceedAlways: case ToolConfirmationOutcome.ProceedAlwaysServer: case ToolConfirmationOutcome.ProceedAlwaysTool: - return ToolCallDecision.ACCEPT; + return ToolCallDecision.AUTO_ACCEPT; case ToolConfirmationOutcome.ModifyWithEditor: return ToolCallDecision.MODIFY; case ToolConfirmationOutcome.Cancel: diff --git a/packages/core/src/telemetry/uiTelemetry.test.ts b/packages/core/src/telemetry/uiTelemetry.test.ts index bce54ad8..221804d2 100644 --- a/packages/core/src/telemetry/uiTelemetry.test.ts +++ b/packages/core/src/telemetry/uiTelemetry.test.ts @@ -104,6 +104,7 @@ describe('UiTelemetryService', () => { [ToolCallDecision.ACCEPT]: 0, [ToolCallDecision.REJECT]: 0, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }, byName: {}, }, @@ -362,6 +363,7 @@ describe('UiTelemetryService', () => { [ToolCallDecision.ACCEPT]: 1, [ToolCallDecision.REJECT]: 0, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }, }); }); @@ -395,6 +397,7 @@ describe('UiTelemetryService', () => { [ToolCallDecision.ACCEPT]: 0, [ToolCallDecision.REJECT]: 1, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }, }); }); @@ -434,11 +437,13 @@ describe('UiTelemetryService', () => { [ToolCallDecision.ACCEPT]: 0, [ToolCallDecision.REJECT]: 0, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }); expect(tools.byName['test_tool'].decisions).toEqual({ [ToolCallDecision.ACCEPT]: 0, [ToolCallDecision.REJECT]: 0, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }); }); @@ -483,6 +488,7 @@ describe('UiTelemetryService', () => { [ToolCallDecision.ACCEPT]: 1, [ToolCallDecision.REJECT]: 1, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }, }); }); diff --git a/packages/core/src/telemetry/uiTelemetry.ts b/packages/core/src/telemetry/uiTelemetry.ts index 2713ac65..fbf5b8dc 100644 --- a/packages/core/src/telemetry/uiTelemetry.ts +++ b/packages/core/src/telemetry/uiTelemetry.ts @@ -32,6 +32,7 @@ export interface ToolCallStats { [ToolCallDecision.ACCEPT]: number; [ToolCallDecision.REJECT]: number; [ToolCallDecision.MODIFY]: number; + [ToolCallDecision.AUTO_ACCEPT]: number; }; } @@ -62,6 +63,7 @@ export interface SessionMetrics { [ToolCallDecision.ACCEPT]: number; [ToolCallDecision.REJECT]: number; [ToolCallDecision.MODIFY]: number; + [ToolCallDecision.AUTO_ACCEPT]: number; }; byName: Record; }; @@ -94,6 +96,7 @@ const createInitialMetrics = (): SessionMetrics => ({ [ToolCallDecision.ACCEPT]: 0, [ToolCallDecision.REJECT]: 0, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }, byName: {}, }, @@ -192,6 +195,7 @@ export class UiTelemetryService extends EventEmitter { [ToolCallDecision.ACCEPT]: 0, [ToolCallDecision.REJECT]: 0, [ToolCallDecision.MODIFY]: 0, + [ToolCallDecision.AUTO_ACCEPT]: 0, }, }; }