fix: yolo mode not respected (#4972)
This commit is contained in:
parent
0b5cc96362
commit
9ca48c00a6
|
@ -138,7 +138,6 @@ export function useReactToolScheduler(
|
||||||
outputUpdateHandler,
|
outputUpdateHandler,
|
||||||
onAllToolCallsComplete: allToolCallsCompleteHandler,
|
onAllToolCallsComplete: allToolCallsCompleteHandler,
|
||||||
onToolCallsUpdate: toolCallsUpdateHandler,
|
onToolCallsUpdate: toolCallsUpdateHandler,
|
||||||
approvalMode: config.getApprovalMode(),
|
|
||||||
getPreferredEditor,
|
getPreferredEditor,
|
||||||
config,
|
config,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
ToolResult,
|
ToolResult,
|
||||||
Config,
|
Config,
|
||||||
Icon,
|
Icon,
|
||||||
|
ApprovalMode,
|
||||||
} from '../index.js';
|
} from '../index.js';
|
||||||
import { Part, PartListUnion } from '@google/genai';
|
import { Part, PartListUnion } from '@google/genai';
|
||||||
|
|
||||||
|
@ -126,6 +127,7 @@ describe('CoreToolScheduler', () => {
|
||||||
getSessionId: () => 'test-session-id',
|
getSessionId: () => 'test-session-id',
|
||||||
getUsageStatisticsEnabled: () => true,
|
getUsageStatisticsEnabled: () => true,
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getApprovalMode: () => ApprovalMode.DEFAULT,
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
|
|
||||||
const scheduler = new CoreToolScheduler({
|
const scheduler = new CoreToolScheduler({
|
||||||
|
@ -194,6 +196,7 @@ describe('CoreToolScheduler with payload', () => {
|
||||||
getSessionId: () => 'test-session-id',
|
getSessionId: () => 'test-session-id',
|
||||||
getUsageStatisticsEnabled: () => true,
|
getUsageStatisticsEnabled: () => true,
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getApprovalMode: () => ApprovalMode.DEFAULT,
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
|
|
||||||
const scheduler = new CoreToolScheduler({
|
const scheduler = new CoreToolScheduler({
|
||||||
|
@ -470,6 +473,7 @@ describe('CoreToolScheduler edit cancellation', () => {
|
||||||
getSessionId: () => 'test-session-id',
|
getSessionId: () => 'test-session-id',
|
||||||
getUsageStatisticsEnabled: () => true,
|
getUsageStatisticsEnabled: () => true,
|
||||||
getDebugMode: () => false,
|
getDebugMode: () => false,
|
||||||
|
getApprovalMode: () => ApprovalMode.DEFAULT,
|
||||||
} as unknown as Config;
|
} as unknown as Config;
|
||||||
|
|
||||||
const scheduler = new CoreToolScheduler({
|
const scheduler = new CoreToolScheduler({
|
||||||
|
@ -527,3 +531,85 @@ describe('CoreToolScheduler edit cancellation', () => {
|
||||||
expect(cancelledCall.response.resultDisplay.fileName).toBe('test.txt');
|
expect(cancelledCall.response.resultDisplay.fileName).toBe('test.txt');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('CoreToolScheduler YOLO mode', () => {
|
||||||
|
it('should execute tool requiring confirmation directly without waiting', async () => {
|
||||||
|
// Arrange
|
||||||
|
const mockTool = new MockTool();
|
||||||
|
// This tool would normally require confirmation.
|
||||||
|
mockTool.shouldConfirm = true;
|
||||||
|
|
||||||
|
const toolRegistry = {
|
||||||
|
getTool: () => mockTool,
|
||||||
|
getToolByName: () => mockTool,
|
||||||
|
// Other properties are not needed for this test but are included for type consistency.
|
||||||
|
getFunctionDeclarations: () => [],
|
||||||
|
tools: new Map(),
|
||||||
|
discovery: {} as any,
|
||||||
|
registerTool: () => {},
|
||||||
|
getToolByDisplayName: () => mockTool,
|
||||||
|
getTools: () => [],
|
||||||
|
discoverTools: async () => {},
|
||||||
|
getAllTools: () => [],
|
||||||
|
getToolsByServer: () => [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAllToolCallsComplete = vi.fn();
|
||||||
|
const onToolCallsUpdate = vi.fn();
|
||||||
|
|
||||||
|
// Configure the scheduler for YOLO mode.
|
||||||
|
const mockConfig = {
|
||||||
|
getSessionId: () => 'test-session-id',
|
||||||
|
getUsageStatisticsEnabled: () => true,
|
||||||
|
getDebugMode: () => false,
|
||||||
|
getApprovalMode: () => ApprovalMode.YOLO,
|
||||||
|
} as unknown as Config;
|
||||||
|
|
||||||
|
const scheduler = new CoreToolScheduler({
|
||||||
|
config: mockConfig,
|
||||||
|
toolRegistry: Promise.resolve(toolRegistry as any),
|
||||||
|
onAllToolCallsComplete,
|
||||||
|
onToolCallsUpdate,
|
||||||
|
getPreferredEditor: () => 'vscode',
|
||||||
|
});
|
||||||
|
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const request = {
|
||||||
|
callId: '1',
|
||||||
|
name: 'mockTool',
|
||||||
|
args: { param: 'value' },
|
||||||
|
isClientInitiated: false,
|
||||||
|
prompt_id: 'prompt-id-yolo',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await scheduler.schedule([request], abortController.signal);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
// 1. The tool's execute method was called directly.
|
||||||
|
expect(mockTool.executeFn).toHaveBeenCalledWith({ param: 'value' });
|
||||||
|
|
||||||
|
// 2. The tool call status never entered 'awaiting_approval'.
|
||||||
|
const statusUpdates = onToolCallsUpdate.mock.calls
|
||||||
|
.map((call) => (call[0][0] as ToolCall)?.status)
|
||||||
|
.filter(Boolean);
|
||||||
|
expect(statusUpdates).not.toContain('awaiting_approval');
|
||||||
|
expect(statusUpdates).toEqual([
|
||||||
|
'validating',
|
||||||
|
'scheduled',
|
||||||
|
'executing',
|
||||||
|
'success',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 3. The final callback indicates the tool call was successful.
|
||||||
|
expect(onAllToolCallsComplete).toHaveBeenCalled();
|
||||||
|
const completedCalls = onAllToolCallsComplete.mock
|
||||||
|
.calls[0][0] as ToolCall[];
|
||||||
|
expect(completedCalls).toHaveLength(1);
|
||||||
|
const completedCall = completedCalls[0];
|
||||||
|
expect(completedCall.status).toBe('success');
|
||||||
|
if (completedCall.status === 'success') {
|
||||||
|
expect(completedCall.response.resultDisplay).toBe('Tool executed');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -219,7 +219,6 @@ interface CoreToolSchedulerOptions {
|
||||||
outputUpdateHandler?: OutputUpdateHandler;
|
outputUpdateHandler?: OutputUpdateHandler;
|
||||||
onAllToolCallsComplete?: AllToolCallsCompleteHandler;
|
onAllToolCallsComplete?: AllToolCallsCompleteHandler;
|
||||||
onToolCallsUpdate?: ToolCallsUpdateHandler;
|
onToolCallsUpdate?: ToolCallsUpdateHandler;
|
||||||
approvalMode?: ApprovalMode;
|
|
||||||
getPreferredEditor: () => EditorType | undefined;
|
getPreferredEditor: () => EditorType | undefined;
|
||||||
config: Config;
|
config: Config;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +229,6 @@ export class CoreToolScheduler {
|
||||||
private outputUpdateHandler?: OutputUpdateHandler;
|
private outputUpdateHandler?: OutputUpdateHandler;
|
||||||
private onAllToolCallsComplete?: AllToolCallsCompleteHandler;
|
private onAllToolCallsComplete?: AllToolCallsCompleteHandler;
|
||||||
private onToolCallsUpdate?: ToolCallsUpdateHandler;
|
private onToolCallsUpdate?: ToolCallsUpdateHandler;
|
||||||
private approvalMode: ApprovalMode;
|
|
||||||
private getPreferredEditor: () => EditorType | undefined;
|
private getPreferredEditor: () => EditorType | undefined;
|
||||||
private config: Config;
|
private config: Config;
|
||||||
|
|
||||||
|
@ -240,7 +238,6 @@ export class CoreToolScheduler {
|
||||||
this.outputUpdateHandler = options.outputUpdateHandler;
|
this.outputUpdateHandler = options.outputUpdateHandler;
|
||||||
this.onAllToolCallsComplete = options.onAllToolCallsComplete;
|
this.onAllToolCallsComplete = options.onAllToolCallsComplete;
|
||||||
this.onToolCallsUpdate = options.onToolCallsUpdate;
|
this.onToolCallsUpdate = options.onToolCallsUpdate;
|
||||||
this.approvalMode = options.approvalMode ?? ApprovalMode.DEFAULT;
|
|
||||||
this.getPreferredEditor = options.getPreferredEditor;
|
this.getPreferredEditor = options.getPreferredEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +459,7 @@ export class CoreToolScheduler {
|
||||||
|
|
||||||
const { request: reqInfo, tool: toolInstance } = toolCall;
|
const { request: reqInfo, tool: toolInstance } = toolCall;
|
||||||
try {
|
try {
|
||||||
if (this.approvalMode === ApprovalMode.YOLO) {
|
if (this.config.getApprovalMode() === ApprovalMode.YOLO) {
|
||||||
this.setStatusInternal(reqInfo.callId, 'scheduled');
|
this.setStatusInternal(reqInfo.callId, 'scheduled');
|
||||||
} else {
|
} else {
|
||||||
const confirmationDetails = await toolInstance.shouldConfirmExecute(
|
const confirmationDetails = await toolInstance.shouldConfirmExecute(
|
||||||
|
|
Loading…
Reference in New Issue