Files
gemini-cli/packages/cli/src/ui/components/messages/ToolMessage.tsx
Jarrod Whelan 974fd7a528 refactor(cli): address code review feedback
- Abstracted hardcoded padding, margin, and width calculations in `DenseToolMessage` into explicit constants to improve readability.
- Made `terminalWidth` a required property on `DenseToolMessageProps` to ensure consistent layout calculations, simplifying internal ternary checks.
- Updated `DenseToolMessage` tests to provide the now-required `terminalWidth` prop.
- Removed expensive `node:crypto` usage in `DiffRenderer` key generation, opting for a simpler optional key.
- Simplified terminal refresh logic in `AppContainer` by removing `setTimeout` from the "show more lines" handler, as it was redundant.
- Streamlined `staticHeight` calculation loop in `ToolGroupMessage` to use layout constants.
- Removed redundant `height={0}` properties on Box borders in `ToolGroupMessage`.
- Simplified `effectiveMaxHeight` assignment in `ToolResultDisplay` by using the pre-calculated `availableHeight` directly.
- Restore tool message padding by moving `paddingTop={1}` from `ToolMessage` and `ShellToolMessage` content boxes back to `paddingBottom={1}` in `StickyHeader`.
- Restore `ToolConfirmationQueue` layout.
- Removed excluded file information from ReadManyFiles tool's compact output
2026-03-30 15:44:15 -07:00

157 lines
4.2 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import type React from 'react';
import { Box } from 'ink';
import type { IndividualToolCallDisplay } from '../../types.js';
import { StickyHeader } from '../StickyHeader.js';
import { ToolResultDisplay } from './ToolResultDisplay.js';
import {
ToolStatusIndicator,
ToolInfo,
TrailingIndicator,
McpProgressIndicator,
type TextEmphasis,
STATUS_INDICATOR_WIDTH,
isThisShellFocusable as checkIsShellFocusable,
isThisShellFocused as checkIsShellFocused,
useFocusHint,
FocusHint,
} from './ToolShared.js';
import { type Config, CoreToolCallStatus, Kind } 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 {
availableTerminalHeight?: number;
terminalWidth: number;
emphasis?: TextEmphasis;
renderOutputAsMarkdown?: boolean;
isFirst: boolean;
borderColor: string;
borderDimColor: boolean;
activeShellPtyId?: number | null;
embeddedShellFocused?: boolean;
ptyId?: number;
config?: Config;
}
export const ToolMessage: React.FC<ToolMessageProps> = ({
name,
description,
resultDisplay,
status,
kind,
availableTerminalHeight,
terminalWidth,
emphasis = 'medium',
renderOutputAsMarkdown = true,
isFirst,
borderColor,
borderDimColor,
activeShellPtyId,
embeddedShellFocused,
ptyId,
config,
progressMessage,
originalRequestName,
progress,
progressTotal,
}) => {
const isThisShellFocused = checkIsShellFocused(
name,
status,
ptyId,
activeShellPtyId,
embeddedShellFocused,
);
const isThisShellFocusable = checkIsShellFocusable(name, status, config);
const { shouldShowFocusHint } = useFocusHint(
isThisShellFocusable,
isThisShellFocused,
resultDisplay,
);
return (
// It is crucial we don't replace this <> with a Box because otherwise the
// sticky header inside it would be sticky to that box rather than to the
// parent component of this ToolMessage.
<>
<StickyHeader
width={terminalWidth}
isFirst={isFirst}
borderColor={borderColor}
borderDimColor={borderDimColor}
>
<ToolStatusIndicator
status={status}
name={name}
isFocused={isThisShellFocused}
/>
<ToolInfo
name={name}
status={status}
description={description}
emphasis={emphasis}
progressMessage={progressMessage}
originalRequestName={originalRequestName}
/>
<FocusHint
shouldShowFocusHint={shouldShowFocusHint}
isThisShellFocused={isThisShellFocused}
/>
{emphasis === 'high' && <TrailingIndicator />}
</StickyHeader>
<Box
width={terminalWidth}
borderStyle="round"
borderColor={borderColor}
borderDimColor={borderDimColor}
borderTop={false}
borderBottom={false}
borderLeft={true}
borderRight={true}
paddingX={1}
flexDirection="column"
>
{status === CoreToolCallStatus.Executing && progress !== undefined && (
<McpProgressIndicator
progress={progress}
total={progressTotal}
message={progressMessage}
barWidth={20}
/>
)}
<ToolResultDisplay
resultDisplay={resultDisplay}
availableTerminalHeight={availableTerminalHeight}
terminalWidth={terminalWidth}
renderOutputAsMarkdown={renderOutputAsMarkdown}
hasFocus={isThisShellFocused}
maxLines={
kind === Kind.Agent && availableTerminalHeight !== undefined
? SUBAGENT_MAX_LINES
: undefined
}
overflowDirection={kind === Kind.Agent ? 'bottom' : 'top'}
/>
{isThisShellFocused && config && (
<Box paddingLeft={STATUS_INDICATOR_WIDTH} marginTop={1}>
<ShellInputPrompt
activeShellPtyId={activeShellPtyId ?? null}
focus={embeddedShellFocused}
/>
</Box>
)}
</Box>
</>
);
};