From 0559d72d65ae278a82f03959d8f37b7628b10954 Mon Sep 17 00:00:00 2001 From: Arjan Date: Wed, 15 Jul 2026 22:36:18 +0530 Subject: [PATCH] refactor(cli): centralize dense payload detection in tool mapping Move dense payload detection logic from UI components to `mapToDisplay`. Add `hasDensePayload` property to `IndividualToolCallDisplay` interface. Cleanup redundant helper functions in `ToolGroupMessage`. --- .../components/messages/ToolGroupMessage.tsx | 26 +------------------ packages/cli/src/ui/hooks/toolMapping.ts | 12 +++++++++ packages/cli/src/ui/types.ts | 1 + 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx b/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx index 3ca1fad6584..aca1b813c97 100644 --- a/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolGroupMessage.tsx @@ -33,7 +33,6 @@ import { WEB_FETCH_DISPLAY_NAME, WRITE_FILE_DISPLAY_NAME, READ_MANY_FILES_DISPLAY_NAME, - isFileDiff, } from '@google/gemini-cli-core'; import { buildToolVisibilityContextFromDisplay } from '../../utils/historyUtils.js'; import { useUIState } from '../../contexts/UIStateContext.js'; @@ -70,29 +69,6 @@ export const isCompactTool = ( ); }; -// Helper to identify if a compact tool has a payload (diff, list, etc.) -export const hasDensePayload = (tool: IndividualToolCallDisplay): boolean => { - if (tool.outputFile) return true; - const res = tool.resultDisplay; - if (!res) return false; - - // TODO(24053): Usage of type guards makes this class too aware of internals - if (isFileDiff(res)) return true; - if (tool.confirmationDetails?.type === 'edit') return true; - - // Generic summary/payload pattern - if ( - typeof res === 'object' && - res !== null && - 'summary' in res && - 'payload' in res - ) { - return true; - } - - return false; -}; - interface ToolGroupMessageProps { item: HistoryItem | HistoryItemWithoutId; toolCalls: IndividualToolCallDisplay[]; @@ -279,7 +255,7 @@ export const ToolGroupMessage: React.FC = ({ for (const tool of visibleToolCalls) { if (tool.kind !== Kind.Agent) { if (isCompactTool(tool, isCompactModeEnabled)) { - if (hasDensePayload(tool)) { + if (tool.hasDensePayload) { countToolCallsWithResults++; } } else if ( diff --git a/packages/cli/src/ui/hooks/toolMapping.ts b/packages/cli/src/ui/hooks/toolMapping.ts index abf53e76e5b..81ab96a4c98 100644 --- a/packages/cli/src/ui/hooks/toolMapping.ts +++ b/packages/cli/src/ui/hooks/toolMapping.ts @@ -11,6 +11,7 @@ import { debugLogger, CoreToolCallStatus, type SubagentActivityItem, + isFileDiff, } from '@google/gemini-cli-core'; import { type HistoryItemToolGroup, @@ -107,6 +108,16 @@ export function mapToDisplay( } } + const hasDensePayload = !!( + outputFile || + (resultDisplay && isFileDiff(resultDisplay)) || + confirmationDetails?.type === 'edit' || + (typeof resultDisplay === 'object' && + resultDisplay !== null && + 'summary' in resultDisplay && + 'payload' in resultDisplay) + ); + return { ...baseDisplayProperties, status: call.status, @@ -125,6 +136,7 @@ export function mapToDisplay( subagentHistory: hasSubagentHistory(call) ? call.subagentHistory : undefined, + hasDensePayload, }; }); diff --git a/packages/cli/src/ui/types.ts b/packages/cli/src/ui/types.ts index 5ed6e05723c..3712c6bd678 100644 --- a/packages/cli/src/ui/types.ts +++ b/packages/cli/src/ui/types.ts @@ -139,6 +139,7 @@ export interface IndividualToolCallDisplay { progress?: number; progressTotal?: number; subagentHistory?: SubagentActivityItem[]; + hasDensePayload?: boolean; } export interface CompressionProps {