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],
);