diff --git a/docs/tos-privacy.md b/docs/tos-privacy.md index 0c7073e0fb..0b16b49197 100644 --- a/docs/tos-privacy.md +++ b/docs/tos-privacy.md @@ -93,4 +93,4 @@ backend, these Terms of Service and Privacy Notice documents apply: You may opt-out from sending Gemini CLI Usage Statistics to Google by following the instructions available here: -[Usage Statistics Configuration](https://github.com/google-gemini/gemini-cli/blob/main/docs/get-started/configuration.md#usage-statistics). +[Usage Statistics Configuration](https://github.com/google-gemini/gemini-cli/blob/main/docs/reference/configuration.md#usage-statistics). diff --git a/packages/cli/src/ui/contexts/ToolActionsContext.test.tsx b/packages/cli/src/ui/contexts/ToolActionsContext.test.tsx index 69e9e284ed..8a75bf7d57 100644 --- a/packages/cli/src/ui/contexts/ToolActionsContext.test.tsx +++ b/packages/cli/src/ui/contexts/ToolActionsContext.test.tsx @@ -15,6 +15,7 @@ import { MessageBusType, IdeClient, CoreToolCallStatus, + type SerializableConfirmationDetails, } from '@google/gemini-cli-core'; import { type IndividualToolCallDisplay } from '../types.js'; @@ -182,4 +183,44 @@ describe('ToolActionsContext', () => { expect(result.current.isDiffingEnabled).toBe(false); }); + + it('calls local onConfirm for tools without correlationId', async () => { + const mockOnConfirm = vi.fn().mockResolvedValue(undefined); + const legacyTool: IndividualToolCallDisplay = { + callId: 'legacy-call', + name: 'legacy-tool', + description: 'desc', + status: CoreToolCallStatus.AwaitingApproval, + resultDisplay: undefined, + confirmationDetails: { + type: 'exec', + title: 'exec', + command: 'ls', + rootCommand: 'ls', + rootCommands: ['ls'], + onConfirm: mockOnConfirm, + } as unknown as SerializableConfirmationDetails, + }; + + const { result } = renderHook(() => useToolActions(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + await act(async () => { + await result.current.confirm( + 'legacy-call', + ToolConfirmationOutcome.ProceedOnce, + ); + }); + + expect(mockOnConfirm).toHaveBeenCalledWith( + ToolConfirmationOutcome.ProceedOnce, + undefined, + ); + expect(mockMessageBus.publish).not.toHaveBeenCalled(); + }); }); diff --git a/packages/cli/src/ui/contexts/ToolActionsContext.tsx b/packages/cli/src/ui/contexts/ToolActionsContext.tsx index d2d4f4322a..10e063e098 100644 --- a/packages/cli/src/ui/contexts/ToolActionsContext.tsx +++ b/packages/cli/src/ui/contexts/ToolActionsContext.tsx @@ -18,10 +18,28 @@ import { MessageBusType, type Config, type ToolConfirmationPayload, + type SerializableConfirmationDetails, debugLogger, } from '@google/gemini-cli-core'; import type { IndividualToolCallDisplay } from '../types.js'; +type LegacyConfirmationDetails = SerializableConfirmationDetails & { + onConfirm: ( + outcome: ToolConfirmationOutcome, + payload?: ToolConfirmationPayload, + ) => Promise; +}; + +function hasLegacyCallback( + details: SerializableConfirmationDetails | undefined, +): details is LegacyConfirmationDetails { + return ( + !!details && + 'onConfirm' in details && + typeof details.onConfirm === 'function' + ); +} + interface ToolActionsContextValue { confirm: ( callId: string, @@ -125,7 +143,15 @@ export const ToolActionsProvider: React.FC = ( return; } - debugLogger.warn(`ToolActions: No correlationId for ${callId}`); + // 3. Fallback: Legacy Callback + if (hasLegacyCallback(details)) { + await details.onConfirm(outcome, payload); + return; + } + + debugLogger.warn( + `ToolActions: No correlationId or callback for ${callId}`, + ); }, [config, ideClient, toolCalls, isDiffingEnabled], );