feat(plan): hide plan write and edit operations on plans in Plan Mode (#19012)

This commit is contained in:
Jerop Kipruto
2026-02-13 18:15:21 -05:00
committed by GitHub
parent 4e1b3b5f57
commit 9df604b01b
20 changed files with 373 additions and 108 deletions

View File

@@ -10,9 +10,14 @@ import { ToolGroupMessage } from './ToolGroupMessage.js';
import type { IndividualToolCallDisplay } from '../../types.js';
import { Scrollable } from '../shared/Scrollable.js';
import {
ASK_USER_DISPLAY_NAME,
makeFakeConfig,
CoreToolCallStatus,
ApprovalMode,
ASK_USER_DISPLAY_NAME,
WRITE_FILE_DISPLAY_NAME,
EDIT_DISPLAY_NAME,
READ_FILE_DISPLAY_NAME,
GLOB_DISPLAY_NAME,
} from '@google/gemini-cli-core';
import os from 'node:os';
@@ -511,4 +516,42 @@ describe('<ToolGroupMessage />', () => {
unmount();
});
});
describe('Plan Mode Filtering', () => {
it.each([
{
name: WRITE_FILE_DISPLAY_NAME,
mode: ApprovalMode.PLAN,
visible: false,
},
{ name: EDIT_DISPLAY_NAME, mode: ApprovalMode.PLAN, visible: false },
{
name: WRITE_FILE_DISPLAY_NAME,
mode: ApprovalMode.DEFAULT,
visible: true,
},
{ name: READ_FILE_DISPLAY_NAME, mode: ApprovalMode.PLAN, visible: true },
{ name: GLOB_DISPLAY_NAME, mode: ApprovalMode.PLAN, visible: true },
])('filtering logic for $name in $mode mode', ({ name, mode, visible }) => {
const toolCalls = [
createToolCall({
callId: 'test-call',
name,
approvalMode: mode,
}),
];
const { lastFrame, unmount } = renderWithProviders(
<ToolGroupMessage {...baseProps} toolCalls={toolCalls} />,
{ config: baseMockConfig },
);
if (visible) {
expect(lastFrame()).toContain(name);
} else {
expect(lastFrame()).toBe('');
}
unmount();
});
});
});

View File

@@ -15,8 +15,8 @@ import { theme } from '../../semantic-colors.js';
import { useConfig } from '../../contexts/ConfigContext.js';
import { isShellTool, isThisShellFocused } from './ToolShared.js';
import {
shouldHideAskUserTool,
CoreToolCallStatus,
shouldHideToolCall,
} from '@google/gemini-cli-core';
import { ShowMoreLines } from '../ShowMoreLines.js';
import { useUIState } from '../../contexts/UIStateContext.js';
@@ -45,13 +45,18 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
borderTop: borderTopOverride,
borderBottom: borderBottomOverride,
}) => {
// Filter out Ask User tools that should be hidden (e.g. in-progress or errors without result)
// Filter out tool calls that should be hidden (e.g. in-progress Ask User, or Plan Mode operations).
const toolCalls = useMemo(
() =>
allToolCalls.filter((t) => {
const displayStatus = mapCoreStatusToDisplayStatus(t.status);
return !shouldHideAskUserTool(t.name, displayStatus, !!t.resultDisplay);
}),
allToolCalls.filter(
(t) =>
!shouldHideToolCall({
displayName: t.name,
status: t.status,
approvalMode: t.approvalMode,
hasResultDisplay: !!t.resultDisplay,
}),
),
[allToolCalls],
);

View File

@@ -95,6 +95,7 @@ export function mapToDisplay(
outputFile,
ptyId,
correlationId,
approvalMode: call.approvalMode,
};
});

View File

@@ -14,6 +14,7 @@ import {
type RetrieveUserQuotaResponse,
type SkillDefinition,
type AgentDefinition,
type ApprovalMode,
CoreToolCallStatus,
checkExhaustive,
} from '@google/gemini-cli-core';
@@ -106,6 +107,7 @@ export interface IndividualToolCallDisplay {
ptyId?: number;
outputFile?: string;
correlationId?: string;
approvalMode?: ApprovalMode;
}
export interface CompressionProps {