Skip to content

Commit c4629f2

Browse files
authored
fix(cli): support legacy onConfirm callback in ToolActionsContext (#19369)
1 parent 00384b9 commit c4629f2

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

packages/cli/src/ui/contexts/ToolActionsContext.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
MessageBusType,
1616
IdeClient,
1717
CoreToolCallStatus,
18+
type SerializableConfirmationDetails,
1819
} from '@google/gemini-cli-core';
1920
import { type IndividualToolCallDisplay } from '../types.js';
2021

@@ -182,4 +183,44 @@ describe('ToolActionsContext', () => {
182183

183184
expect(result.current.isDiffingEnabled).toBe(false);
184185
});
186+
187+
it('calls local onConfirm for tools without correlationId', async () => {
188+
const mockOnConfirm = vi.fn().mockResolvedValue(undefined);
189+
const legacyTool: IndividualToolCallDisplay = {
190+
callId: 'legacy-call',
191+
name: 'legacy-tool',
192+
description: 'desc',
193+
status: CoreToolCallStatus.AwaitingApproval,
194+
resultDisplay: undefined,
195+
confirmationDetails: {
196+
type: 'exec',
197+
title: 'exec',
198+
command: 'ls',
199+
rootCommand: 'ls',
200+
rootCommands: ['ls'],
201+
onConfirm: mockOnConfirm,
202+
} as unknown as SerializableConfirmationDetails,
203+
};
204+
205+
const { result } = renderHook(() => useToolActions(), {
206+
wrapper: ({ children }) => (
207+
<ToolActionsProvider config={mockConfig} toolCalls={[legacyTool]}>
208+
{children}
209+
</ToolActionsProvider>
210+
),
211+
});
212+
213+
await act(async () => {
214+
await result.current.confirm(
215+
'legacy-call',
216+
ToolConfirmationOutcome.ProceedOnce,
217+
);
218+
});
219+
220+
expect(mockOnConfirm).toHaveBeenCalledWith(
221+
ToolConfirmationOutcome.ProceedOnce,
222+
undefined,
223+
);
224+
expect(mockMessageBus.publish).not.toHaveBeenCalled();
225+
});
185226
});

packages/cli/src/ui/contexts/ToolActionsContext.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,28 @@ import {
1818
MessageBusType,
1919
type Config,
2020
type ToolConfirmationPayload,
21+
type SerializableConfirmationDetails,
2122
debugLogger,
2223
} from '@google/gemini-cli-core';
2324
import type { IndividualToolCallDisplay } from '../types.js';
2425

26+
type LegacyConfirmationDetails = SerializableConfirmationDetails & {
27+
onConfirm: (
28+
outcome: ToolConfirmationOutcome,
29+
payload?: ToolConfirmationPayload,
30+
) => Promise<void>;
31+
};
32+
33+
function hasLegacyCallback(
34+
details: SerializableConfirmationDetails | undefined,
35+
): details is LegacyConfirmationDetails {
36+
return (
37+
!!details &&
38+
'onConfirm' in details &&
39+
typeof details.onConfirm === 'function'
40+
);
41+
}
42+
2543
interface ToolActionsContextValue {
2644
confirm: (
2745
callId: string,
@@ -125,7 +143,15 @@ export const ToolActionsProvider: React.FC<ToolActionsProviderProps> = (
125143
return;
126144
}
127145

128-
debugLogger.warn(`ToolActions: No correlationId for ${callId}`);
146+
// 3. Fallback: Legacy Callback
147+
if (hasLegacyCallback(details)) {
148+
await details.onConfirm(outcome, payload);
149+
return;
150+
}
151+
152+
debugLogger.warn(
153+
`ToolActions: No correlationId or callback for ${callId}`,
154+
);
129155
},
130156
[config, ideClient, toolCalls, isDiffingEnabled],
131157
);

0 commit comments

Comments
 (0)