Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ describe('AlternateBufferQuittingDisplay', () => {
type: 'info',
title: 'Confirm Tool',
prompt: 'Confirm this action?',
onConfirm: async () => {},
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,6 @@ describe('<HistoryItemDisplay />', () => {
command: 'echo "\u001b[31mhello\u001b[0m"',
rootCommand: 'echo',
rootCommands: ['echo'],
onConfirm: async () => {},
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { describe, it, expect } from 'vitest';
import { Box } from 'ink';
import { ToolConfirmationQueue } from './ToolConfirmationQueue.js';
import { ToolCallStatus, StreamingState } from '../types.js';
Expand Down Expand Up @@ -70,7 +70,6 @@ describe('ToolConfirmationQueue', () => {
command: 'ls',
rootCommand: 'ls',
rootCommands: ['ls'],
onConfirm: vi.fn(),
},
},
index: 1,
Expand Down Expand Up @@ -144,7 +143,6 @@ describe('ToolConfirmationQueue', () => {
fileDiff: longDiff,
originalContent: 'old',
newContent: 'new',
onConfirm: vi.fn(),
},
},
index: 1,
Expand Down Expand Up @@ -192,7 +190,6 @@ describe('ToolConfirmationQueue', () => {
fileDiff: longDiff,
originalContent: 'old',
newContent: 'new',
onConfirm: vi.fn(),
},
},
index: 1,
Expand Down Expand Up @@ -242,7 +239,6 @@ describe('ToolConfirmationQueue', () => {
fileDiff: longDiff,
originalContent: 'old',
newContent: 'new',
onConfirm: vi.fn(),
},
},
index: 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { describe, it, expect, vi, beforeAll } from 'vitest';
import { describe, it, expect, beforeAll } from 'vitest';
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
import type {
ToolCallConfirmationDetails,
SerializableConfirmationDetails,
Config,
} from '@google/gemini-cli-core';
import { initializeShellParsers } from '@google/gemini-cli-core';
Expand All @@ -24,13 +24,12 @@ describe('ToolConfirmationMessage Redirection', () => {
} as unknown as Config;

it('should display redirection warning and tip for redirected commands', () => {
const confirmationDetails: ToolCallConfirmationDetails = {
const confirmationDetails: SerializableConfirmationDetails = {
type: 'exec',
title: 'Confirm Shell Command',
command: 'echo "hello" > test.txt',
rootCommand: 'echo, redirection (>)',
rootCommands: ['echo'],
onConfirm: vi.fn(),
};

const { lastFrame } = renderWithProviders(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { describe, it, expect, vi } from 'vitest';
import { ToolConfirmationMessage } from './ToolConfirmationMessage.js';
import type {
ToolCallConfirmationDetails,
SerializableConfirmationDetails,
Config,
} from '@google/gemini-cli-core';
import { renderWithProviders } from '../../../test-utils/render.js';
Expand Down Expand Up @@ -39,12 +39,11 @@ describe('ToolConfirmationMessage', () => {
} as unknown as Config;

it('should not display urls if prompt and url are the same', () => {
const confirmationDetails: ToolCallConfirmationDetails = {
const confirmationDetails: SerializableConfirmationDetails = {
type: 'info',
title: 'Confirm Web Fetch',
prompt: 'https://example.com',
urls: ['https://example.com'],
onConfirm: vi.fn(),
};

const { lastFrame } = renderWithProviders(
Expand All @@ -61,15 +60,14 @@ describe('ToolConfirmationMessage', () => {
});

it('should display urls if prompt and url are different', () => {
const confirmationDetails: ToolCallConfirmationDetails = {
const confirmationDetails: SerializableConfirmationDetails = {
type: 'info',
title: 'Confirm Web Fetch',
prompt:
'fetch https://github.com/google/gemini-react/blob/main/README.md',
urls: [
'https://raw.githubusercontent.com/google/gemini-react/main/README.md',
],
onConfirm: vi.fn(),
};

const { lastFrame } = renderWithProviders(
Expand All @@ -86,14 +84,13 @@ describe('ToolConfirmationMessage', () => {
});

it('should display multiple commands for exec type when provided', () => {
const confirmationDetails: ToolCallConfirmationDetails = {
const confirmationDetails: SerializableConfirmationDetails = {
type: 'exec',
title: 'Confirm Multiple Commands',
command: 'echo "hello"', // Primary command
rootCommand: 'echo',
rootCommands: ['echo'],
commands: ['echo "hello"', 'ls -la', 'whoami'], // Multi-command list
onConfirm: vi.fn(),
};

const { lastFrame } = renderWithProviders(
Expand All @@ -114,41 +111,37 @@ describe('ToolConfirmationMessage', () => {
});

describe('with folder trust', () => {
const editConfirmationDetails: ToolCallConfirmationDetails = {
const editConfirmationDetails: SerializableConfirmationDetails = {
type: 'edit',
title: 'Confirm Edit',
fileName: 'test.txt',
filePath: '/test.txt',
fileDiff: '...diff...',
originalContent: 'a',
newContent: 'b',
onConfirm: vi.fn(),
};

const execConfirmationDetails: ToolCallConfirmationDetails = {
const execConfirmationDetails: SerializableConfirmationDetails = {
type: 'exec',
title: 'Confirm Execution',
command: 'echo "hello"',
rootCommand: 'echo',
rootCommands: ['echo'],
onConfirm: vi.fn(),
};

const infoConfirmationDetails: ToolCallConfirmationDetails = {
const infoConfirmationDetails: SerializableConfirmationDetails = {
type: 'info',
title: 'Confirm Web Fetch',
prompt: 'https://example.com',
urls: ['https://example.com'],
onConfirm: vi.fn(),
};

const mcpConfirmationDetails: ToolCallConfirmationDetails = {
const mcpConfirmationDetails: SerializableConfirmationDetails = {
type: 'mcp',
title: 'Confirm MCP Tool',
serverName: 'test-server',
toolName: 'test-tool',
toolDisplayName: 'Test Tool',
onConfirm: vi.fn(),
};

describe.each([
Expand Down Expand Up @@ -214,15 +207,14 @@ describe('ToolConfirmationMessage', () => {
});

describe('enablePermanentToolApproval setting', () => {
const editConfirmationDetails: ToolCallConfirmationDetails = {
const editConfirmationDetails: SerializableConfirmationDetails = {
type: 'edit',
title: 'Confirm Edit',
fileName: 'test.txt',
filePath: '/test.txt',
fileDiff: '...diff...',
originalContent: 'a',
newContent: 'b',
onConfirm: vi.fn(),
};

it('should NOT show "Allow for all future sessions" when setting is false (default)', () => {
Expand Down Expand Up @@ -275,15 +267,14 @@ describe('ToolConfirmationMessage', () => {
});

describe('Modify with external editor option', () => {
const editConfirmationDetails: ToolCallConfirmationDetails = {
const editConfirmationDetails: SerializableConfirmationDetails = {
type: 'edit',
title: 'Confirm Edit',
fileName: 'test.txt',
filePath: '/test.txt',
fileDiff: '...diff...',
originalContent: 'a',
newContent: 'b',
onConfirm: vi.fn(),
};

it('should show "Modify with external editor" when NOT in IDE mode', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { DiffRenderer } from './DiffRenderer.js';
import { RenderInline } from '../../utils/InlineMarkdownRenderer.js';
import {
type SerializableConfirmationDetails,
type ToolCallConfirmationDetails,
type Config,
type ToolConfirmationPayload,
ToolConfirmationOutcome,
Expand All @@ -38,9 +37,7 @@ import { ExitPlanModeDialog } from '../ExitPlanModeDialog.js';

export interface ToolConfirmationMessageProps {
callId: string;
confirmationDetails:
| ToolCallConfirmationDetails
| SerializableConfirmationDetails;
confirmationDetails: SerializableConfirmationDetails;
config: Config;
isFocused?: boolean;
availableTerminalHeight?: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ describe('<ToolGroupMessage />', () => {
type: 'info',
title: 'Confirm tool',
prompt: 'Do you want to proceed?',
onConfirm: vi.fn(),
},
}),
];
Expand Down
53 changes: 8 additions & 45 deletions packages/cli/src/ui/contexts/ToolActionsContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
ToolConfirmationOutcome,
MessageBusType,
IdeClient,
type ToolCallConfirmationDetails,
} from '@google/gemini-cli-core';
import { ToolCallStatus, type IndividualToolCallDisplay } from '../types.js';

Expand Down Expand Up @@ -50,21 +49,9 @@ describe('ToolActionsContext', () => {
resultDisplay: undefined,
confirmationDetails: { type: 'info', title: 'title', prompt: 'prompt' },
},
{
callId: 'legacy-call',
name: 'legacy-tool',
description: 'desc',
status: ToolCallStatus.Confirming,
resultDisplay: undefined,
confirmationDetails: {
type: 'info',
title: 'legacy',
prompt: 'prompt',
onConfirm: vi.fn(),
} as ToolCallConfirmationDetails,
},
{
callId: 'edit-call',
correlationId: 'corr-edit',
name: 'edit-tool',
description: 'desc',
status: ToolCallStatus.Confirming,
Expand All @@ -77,8 +64,7 @@ describe('ToolActionsContext', () => {
fileDiff: 'diff',
originalContent: 'old',
newContent: 'new',
onConfirm: vi.fn(),
} as ToolCallConfirmationDetails,
},
},
];

Expand All @@ -92,7 +78,7 @@ describe('ToolActionsContext', () => {
</ToolActionsProvider>
);

it('publishes to MessageBus for tools with correlationId (Modern Path)', async () => {
it('publishes to MessageBus for tools with correlationId', async () => {
const { result } = renderHook(() => useToolActions(), { wrapper });

await result.current.confirm(
Expand All @@ -110,27 +96,6 @@ describe('ToolActionsContext', () => {
});
});

it('calls onConfirm for legacy tools (Legacy Path)', async () => {
const { result } = renderHook(() => useToolActions(), { wrapper });
const legacyDetails = mockToolCalls[1]
.confirmationDetails as ToolCallConfirmationDetails;

await result.current.confirm(
'legacy-call',
ToolConfirmationOutcome.ProceedOnce,
);

if (legacyDetails && 'onConfirm' in legacyDetails) {
expect(legacyDetails.onConfirm).toHaveBeenCalledWith(
ToolConfirmationOutcome.ProceedOnce,
undefined,
);
} else {
throw new Error('Expected onConfirm to be present');
}
expect(mockMessageBus.publish).not.toHaveBeenCalled();
});

it('handles cancel by calling confirm with Cancel outcome', async () => {
const { result } = renderHook(() => useToolActions(), { wrapper });

Expand Down Expand Up @@ -170,13 +135,11 @@ describe('ToolActionsContext', () => {
'/f.txt',
'accepted',
);
const editDetails = mockToolCalls[2]
.confirmationDetails as ToolCallConfirmationDetails;
if (editDetails && 'onConfirm' in editDetails) {
expect(editDetails.onConfirm).toHaveBeenCalled();
} else {
throw new Error('Expected onConfirm to be present');
}
expect(mockMessageBus.publish).toHaveBeenCalledWith(
expect.objectContaining({
correlationId: 'corr-edit',
}),
);
});

it('updates isDiffingEnabled when IdeClient status changes', async () => {
Expand Down
19 changes: 2 additions & 17 deletions packages/cli/src/ui/contexts/ToolActionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
MessageBusType,
type Config,
type ToolConfirmationPayload,
type ToolCallConfirmationDetails,
debugLogger,
} from '@google/gemini-cli-core';
import type { IndividualToolCallDisplay } from '../types.js';
Expand Down Expand Up @@ -113,8 +112,7 @@ export const ToolActionsProvider: React.FC<ToolActionsProviderProps> = (
await ideClient?.resolveDiffFromCli(details.filePath, cliOutcome);
}

// 2. Dispatch
// PATH A: Event Bus (Modern)
// 2. Dispatch via Event Bus
if (tool.correlationId) {
await config.getMessageBus().publish({
type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
Expand All @@ -127,20 +125,7 @@ export const ToolActionsProvider: React.FC<ToolActionsProviderProps> = (
return;
}

// PATH B: Legacy Callback (Adapter or Old Scheduler)
if (
details &&
'onConfirm' in details &&
typeof details.onConfirm === 'function'
) {
await (details as ToolCallConfirmationDetails).onConfirm(
outcome,
payload,
);
return;
}

debugLogger.warn(`ToolActions: No confirmation mechanism for ${callId}`);
debugLogger.warn(`ToolActions: No correlationId for ${callId}`);
},
[config, ideClient, toolCalls, isDiffingEnabled],
);
Expand Down
Loading
Loading