Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
31 changes: 31 additions & 0 deletions packages/cli/src/ui/hooks/useGeminiStream.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
debugLogger,
coreEvents,
CoreEvent,
SHELL_TOOL_NAME,
MCPDiscoveryState,
GeminiCliOperation,
getPlanModeExitMessage,
Expand Down Expand Up @@ -2449,6 +2450,36 @@ describe('useGeminiStream', () => {
);
});

it('should auto-approve shell commands with redirection when switching to AUTO_EDIT mode', async () => {
const shellCall = createMockToolCall(SHELL_TOOL_NAME, 'call-shell', 'info');
shellCall.request.args = { command: 'ls > files.txt' };

const { result } = await renderTestHook([shellCall]);

await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.AUTO_EDIT);
});

// Shell command with redirection should be auto-approved
expect(mockMessageBus.publish).toHaveBeenCalledWith(
expect.objectContaining({ correlationId: 'corr-call-shell' }),
);
});

it('should NOT auto-approve shell commands without redirection when switching to AUTO_EDIT mode', async () => {
const shellCall = createMockToolCall(SHELL_TOOL_NAME, 'call-shell', 'info');
shellCall.request.args = { command: 'ls -la' };

const { result } = await renderTestHook([shellCall]);

await act(async () => {
await result.current.handleApprovalModeChange(ApprovalMode.AUTO_EDIT);
});

// Regular shell command should NOT be auto-approved
expect(mockMessageBus.publish).not.toHaveBeenCalled();
});

it('should not auto-approve any tools when switching to REQUIRE_CONFIRMATION mode', async () => {
const awaitingApprovalToolCalls: TrackedToolCall[] = [
createMockToolCall('replace', 'call1', 'edit'),
Expand Down
19 changes: 16 additions & 3 deletions packages/cli/src/ui/hooks/useGeminiStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
debugLogger,
runInDevTraceSpan,
EDIT_TOOL_NAMES,
SHELL_TOOL_NAME,
hasRedirection,
processRestorableToolCalls,
recordToolCallInteractions,
ToolErrorType,
Expand Down Expand Up @@ -1820,10 +1822,21 @@ export const useGeminiStream = (
);

// For AUTO_EDIT mode, only approve edit tools (replace, write_file)
// or shell commands with redirection (which act as edits).
if (newApprovalMode === ApprovalMode.AUTO_EDIT) {
awaitingApprovalCalls = awaitingApprovalCalls.filter((call) =>
EDIT_TOOL_NAMES.has(call.request.name),
);
awaitingApprovalCalls = awaitingApprovalCalls.filter((call) => {
if (EDIT_TOOL_NAMES.has(call.request.name)) {
return true;
}

if (call.request.name === SHELL_TOOL_NAME) {
const command = (call.request.args as { command?: string })
.command;
return command && hasRedirection(command);
}

return false;
});
}

// Process pending tool calls sequentially to reduce UI chaos
Expand Down
Loading