diff --git a/packages/cli/src/ui/components/messages/DenseToolMessage.tsx b/packages/cli/src/ui/components/messages/DenseToolMessage.tsx index f5e4b31c66..72b61429b7 100644 --- a/packages/cli/src/ui/components/messages/DenseToolMessage.tsx +++ b/packages/cli/src/ui/components/messages/DenseToolMessage.tsx @@ -17,6 +17,7 @@ import { isGrepResult, isListResult, isReadManyFilesResult, + type ToolDisplay, } from '@google/gemini-cli-core'; import { type IndividualToolCallDisplay, @@ -46,6 +47,7 @@ const PAYLOAD_SCROLL_GUTTER = 4; const PAYLOAD_MAX_WIDTH = 120 + PAYLOAD_SCROLL_GUTTER; interface DenseToolMessageProps extends IndividualToolCallDisplay { + display?: ToolDisplay; terminalWidth: number; availableTerminalHeight?: number; } @@ -269,6 +271,7 @@ export const DenseToolMessage: React.FC = (props) => { terminalWidth, availableTerminalHeight, description: originalDescription, + display, } = props; const settings = useSettings(); @@ -322,6 +325,58 @@ export const DenseToolMessage: React.FC = (props) => { // State-to-View Coordination const viewParts = useMemo((): ViewParts => { + if (display) { + const descriptionText = ( + + {display.description || originalDescription} + + ); + + const summaryText = display.resultSummary ? ( + + → {display.resultSummary} + + ) : status === CoreToolCallStatus.Error ? ( + + → {typeof resultDisplay === 'string' ? resultDisplay : 'Failed'} + + ) : undefined; + + // For now, DenseToolMessage still handles complex resultDisplay types + // like FileDiff or ListResult manually if display.result is not provided + // or doesn't cover them. + if (!display.result) { + if (diff) { + return { + ...getFileOpData( + diff, + status, + resultDisplay, + terminalWidth, + availableTerminalHeight, + isAlternateBuffer, + ), + description: descriptionText, + summary: summaryText, + }; + } + if (isListResult(resultDisplay)) { + return { + ...getListResultData(resultDisplay, originalDescription), + description: descriptionText, + summary: summaryText, + }; + } + } + + // If we have a display.result or a simple success, use it + return { + description: descriptionText, + summary: summaryText, + payload: undefined, // Payload rendering will be updated in Step 5 + }; + } + if (diff) { return getFileOpData( diff, @@ -383,6 +438,7 @@ export const DenseToolMessage: React.FC = (props) => { availableTerminalHeight, originalDescription, isAlternateBuffer, + display, ]); const { description, summary } = viewParts; diff --git a/packages/cli/src/ui/components/messages/ShellToolMessage.tsx b/packages/cli/src/ui/components/messages/ShellToolMessage.tsx index f3694f3490..201a78f70e 100644 --- a/packages/cli/src/ui/components/messages/ShellToolMessage.tsx +++ b/packages/cli/src/ui/components/messages/ShellToolMessage.tsx @@ -43,6 +43,7 @@ export interface ShellToolMessageProps extends ToolMessageProps { export const ShellToolMessage: React.FC = ({ name, description, + display, resultDisplay, status, availableTerminalHeight, @@ -167,6 +168,7 @@ export const ShellToolMessage: React.FC = ({ name={name} status={status} description={description} + display={display} emphasis={emphasis} originalRequestName={originalRequestName} /> diff --git a/packages/cli/src/ui/components/messages/ToolMessage.tsx b/packages/cli/src/ui/components/messages/ToolMessage.tsx index 5747f7677f..103f4443b5 100644 --- a/packages/cli/src/ui/components/messages/ToolMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolMessage.tsx @@ -21,13 +21,20 @@ import { useFocusHint, FocusHint, } from './ToolShared.js'; -import { type Config, CoreToolCallStatus, Kind } from '@google/gemini-cli-core'; +import { + type Config, + CoreToolCallStatus, + Kind, + type ToolDisplay, +} from '@google/gemini-cli-core'; import { ShellInputPrompt } from '../ShellInputPrompt.js'; import { SUBAGENT_MAX_LINES } from '../../constants.js'; export type { TextEmphasis }; export interface ToolMessageProps extends IndividualToolCallDisplay { + description: string; + display?: ToolDisplay; availableTerminalHeight?: number; terminalWidth: number; emphasis?: TextEmphasis; @@ -44,6 +51,7 @@ export interface ToolMessageProps extends IndividualToolCallDisplay { export const ToolMessage: React.FC = ({ name, description, + display, resultDisplay, status, kind, @@ -99,6 +107,7 @@ export const ToolMessage: React.FC = ({ name={name} status={status} description={description} + display={display} emphasis={emphasis} progressMessage={progressMessage} originalRequestName={originalRequestName} diff --git a/packages/cli/src/ui/components/messages/ToolShared.tsx b/packages/cli/src/ui/components/messages/ToolShared.tsx index 2aa5ed992a..21157da2b3 100644 --- a/packages/cli/src/ui/components/messages/ToolShared.tsx +++ b/packages/cli/src/ui/components/messages/ToolShared.tsx @@ -21,6 +21,7 @@ import { isCompletedAskUserTool, type ToolResultDisplay, CoreToolCallStatus, + type ToolDisplay, } from '@google/gemini-cli-core'; import { useInactivityTimer } from '../../hooks/useInactivityTimer.js'; import { formatCommand } from '../../key/keybindingUtils.js'; @@ -192,6 +193,7 @@ type ToolInfoProps = { description: string; status: CoreToolCallStatus; emphasis: TextEmphasis; + display?: ToolDisplay; progressMessage?: string; originalRequestName?: string; }; @@ -201,6 +203,7 @@ export const ToolInfo: React.FC = ({ description, status: coreStatus, emphasis, + display, progressMessage: _progressMessage, originalRequestName, }) => { @@ -223,11 +226,15 @@ export const ToolInfo: React.FC = ({ // Hide description for completed Ask User tools (the result display speaks for itself) const isCompletedAskUser = isCompletedAskUserTool(name, status); + const displayName = display?.name || name; + const displayDescription = display?.description || description; + const displaySummary = display?.resultSummary; + return ( - {name} + {displayName} {originalRequestName && originalRequestName !== name && ( @@ -238,7 +245,13 @@ export const ToolInfo: React.FC = ({ {!isCompletedAskUser && ( <> {' '} - {description} + {displayDescription} + + )} + {displaySummary && ( + <> + + {displaySummary} )}