mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-06-01 19:03:42 +00:00
revert: remove invasive ToolDisplay logic from legacy UI components
This commit is contained in:
@@ -17,14 +17,12 @@ import {
|
||||
isGrepResult,
|
||||
isListResult,
|
||||
isReadManyFilesResult,
|
||||
type ToolDisplay,
|
||||
} from '@google/gemini-cli-core';
|
||||
import {
|
||||
type IndividualToolCallDisplay,
|
||||
type ToolResultDisplay,
|
||||
isTodoList,
|
||||
} from '../../types.js';
|
||||
import { isCompactTool } from './ToolGroupMessage.js';
|
||||
import { useAlternateBuffer } from '../../hooks/useAlternateBuffer.js';
|
||||
import { ToolStatusIndicator } from './ToolShared.js';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
@@ -48,7 +46,6 @@ const PAYLOAD_SCROLL_GUTTER = 4;
|
||||
const PAYLOAD_MAX_WIDTH = 120 + PAYLOAD_SCROLL_GUTTER;
|
||||
|
||||
interface DenseToolMessageProps extends IndividualToolCallDisplay {
|
||||
display?: ToolDisplay;
|
||||
terminalWidth: number;
|
||||
availableTerminalHeight?: number;
|
||||
}
|
||||
@@ -272,7 +269,6 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
terminalWidth,
|
||||
availableTerminalHeight,
|
||||
description: originalDescription,
|
||||
display,
|
||||
} = props;
|
||||
|
||||
const settings = useSettings();
|
||||
@@ -287,7 +283,6 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const toggleRef = useRef<DOMElement>(null);
|
||||
const isActuallyCompact = useMemo(() => isCompactTool(props, true), [props]);
|
||||
|
||||
// Unified File Data Extraction (Safely bridge resultDisplay and confirmationDetails)
|
||||
const diff = useMemo((): FileDiff | undefined => {
|
||||
@@ -327,83 +322,6 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
|
||||
// State-to-View Coordination
|
||||
const viewParts = useMemo((): ViewParts => {
|
||||
if (display) {
|
||||
const descriptionText = (
|
||||
<Text color={theme.text.secondary} wrap="truncate-end">
|
||||
{display.description || originalDescription}
|
||||
</Text>
|
||||
);
|
||||
|
||||
const summaryText = display.resultSummary ? (
|
||||
<Text color={theme.text.accent} wrap="truncate-end">
|
||||
→ {display.resultSummary}
|
||||
</Text>
|
||||
) : status === CoreToolCallStatus.Error ? (
|
||||
<Text color={theme.status.error} wrap="truncate-end">
|
||||
→ {typeof resultDisplay === 'string' ? resultDisplay : 'Failed'}
|
||||
</Text>
|
||||
) : 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, use it as the payload
|
||||
let payload: React.ReactNode;
|
||||
if (display.result) {
|
||||
if (display.result.type === 'text') {
|
||||
const text = display.result.text;
|
||||
if (text) {
|
||||
payload = (
|
||||
<Text color={theme.text.secondary} wrap="truncate-end">
|
||||
{text}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
}
|
||||
// Step 5 will expand this to handle 'diff' type
|
||||
}
|
||||
|
||||
// Compact tools should elide text payloads by default unless expanded.
|
||||
if (
|
||||
isActuallyCompact &&
|
||||
!isExpanded &&
|
||||
display.result?.type === 'text' &&
|
||||
!isAlternateBuffer
|
||||
) {
|
||||
payload = undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
description: descriptionText,
|
||||
summary: summaryText,
|
||||
payload,
|
||||
};
|
||||
}
|
||||
|
||||
if (diff) {
|
||||
return getFileOpData(
|
||||
diff,
|
||||
@@ -465,9 +383,6 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
availableTerminalHeight,
|
||||
originalDescription,
|
||||
isAlternateBuffer,
|
||||
display,
|
||||
isActuallyCompact,
|
||||
isExpanded,
|
||||
]);
|
||||
|
||||
const { description, summary } = viewParts;
|
||||
@@ -505,10 +420,6 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
}, [diff, isExpanded, isAlternateBuffer, terminalWidth, settings, status]);
|
||||
|
||||
const showPayload = useMemo(() => {
|
||||
// If we are using the new display protocol and it's a compact tool,
|
||||
// hide the payload by default unless expanded.
|
||||
if (display && isActuallyCompact && !isExpanded) return false;
|
||||
|
||||
const policy = !isAlternateBuffer || !diff || isExpanded;
|
||||
if (!policy) return false;
|
||||
|
||||
@@ -528,8 +439,6 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
diffLines.length,
|
||||
viewParts.payload,
|
||||
outputFile,
|
||||
isActuallyCompact,
|
||||
display,
|
||||
]);
|
||||
|
||||
const keyExtractor = (_item: React.ReactNode, index: number) =>
|
||||
@@ -540,16 +449,7 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Box
|
||||
marginLeft={2}
|
||||
flexDirection="row"
|
||||
flexWrap="wrap"
|
||||
ref={
|
||||
isActuallyCompact || (isAlternateBuffer && diff)
|
||||
? toggleRef
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Box marginLeft={2} flexDirection="row" flexWrap="wrap">
|
||||
<Box flexDirection="row" flexShrink={1}>
|
||||
<ToolStatusIndicator status={status} name={name} />
|
||||
<Box maxWidth={25} flexShrink={0} flexGrow={0}>
|
||||
@@ -563,7 +463,12 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
</Box>
|
||||
|
||||
{summary && (
|
||||
<Box key="tool-summary" marginLeft={1} flexGrow={0}>
|
||||
<Box
|
||||
key="tool-summary"
|
||||
ref={isAlternateBuffer && diff ? toggleRef : undefined}
|
||||
marginLeft={1}
|
||||
flexGrow={0}
|
||||
>
|
||||
{summary}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -43,7 +43,6 @@ export interface ShellToolMessageProps extends ToolMessageProps {
|
||||
export const ShellToolMessage: React.FC<ShellToolMessageProps> = ({
|
||||
name,
|
||||
description,
|
||||
display,
|
||||
resultDisplay,
|
||||
status,
|
||||
availableTerminalHeight,
|
||||
@@ -168,7 +167,6 @@ export const ShellToolMessage: React.FC<ShellToolMessageProps> = ({
|
||||
name={name}
|
||||
status={status}
|
||||
description={description}
|
||||
display={display}
|
||||
emphasis={emphasis}
|
||||
originalRequestName={originalRequestName}
|
||||
/>
|
||||
|
||||
@@ -61,9 +61,7 @@ export const isCompactTool = (
|
||||
tool: IndividualToolCallDisplay,
|
||||
isCompactModeEnabled: boolean,
|
||||
): boolean => {
|
||||
const hasCompactOutputSupport = COMPACT_OUTPUT_ALLOWLIST.has(
|
||||
tool.originalRequestName || tool.name,
|
||||
);
|
||||
const hasCompactOutputSupport = COMPACT_OUTPUT_ALLOWLIST.has(tool.name);
|
||||
const displayStatus = mapCoreStatusToDisplayStatus(tool.status);
|
||||
return (
|
||||
isCompactModeEnabled &&
|
||||
@@ -121,7 +119,6 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
|
||||
isToolGroupBoundary,
|
||||
}) => {
|
||||
const settings = useSettings();
|
||||
|
||||
const isLowErrorVerbosity = settings.merged.ui?.errorVerbosity !== 'full';
|
||||
const isCompactModeEnabled = settings.merged.ui?.compactToolOutput === true;
|
||||
|
||||
|
||||
@@ -21,20 +21,13 @@ import {
|
||||
useFocusHint,
|
||||
FocusHint,
|
||||
} from './ToolShared.js';
|
||||
import {
|
||||
type Config,
|
||||
CoreToolCallStatus,
|
||||
Kind,
|
||||
type ToolDisplay,
|
||||
} from '@google/gemini-cli-core';
|
||||
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 {
|
||||
description: string;
|
||||
display?: ToolDisplay;
|
||||
availableTerminalHeight?: number;
|
||||
terminalWidth: number;
|
||||
emphasis?: TextEmphasis;
|
||||
@@ -51,7 +44,6 @@ export interface ToolMessageProps extends IndividualToolCallDisplay {
|
||||
export const ToolMessage: React.FC<ToolMessageProps> = ({
|
||||
name,
|
||||
description,
|
||||
display,
|
||||
resultDisplay,
|
||||
status,
|
||||
kind,
|
||||
@@ -87,11 +79,6 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
||||
resultDisplay,
|
||||
);
|
||||
|
||||
const effectiveResultDisplay =
|
||||
display?.resultSummary && !display.result
|
||||
? display.resultSummary
|
||||
: 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
|
||||
@@ -112,11 +99,9 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
||||
name={name}
|
||||
status={status}
|
||||
description={description}
|
||||
display={display}
|
||||
emphasis={emphasis}
|
||||
progressMessage={progressMessage}
|
||||
originalRequestName={originalRequestName}
|
||||
hideSummary={!display?.result && !!display?.resultSummary}
|
||||
/>
|
||||
<FocusHint
|
||||
shouldShowFocusHint={shouldShowFocusHint}
|
||||
@@ -145,7 +130,7 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
||||
/>
|
||||
)}
|
||||
<ToolResultDisplay
|
||||
resultDisplay={effectiveResultDisplay}
|
||||
resultDisplay={resultDisplay}
|
||||
availableTerminalHeight={availableTerminalHeight}
|
||||
terminalWidth={terminalWidth}
|
||||
renderOutputAsMarkdown={renderOutputAsMarkdown}
|
||||
|
||||
@@ -21,7 +21,6 @@ import {
|
||||
isCompletedAskUserTool,
|
||||
type ToolResultDisplay,
|
||||
CoreToolCallStatus,
|
||||
type ToolDisplay,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { useInactivityTimer } from '../../hooks/useInactivityTimer.js';
|
||||
import { formatCommand } from '../../key/keybindingUtils.js';
|
||||
@@ -193,10 +192,8 @@ type ToolInfoProps = {
|
||||
description: string;
|
||||
status: CoreToolCallStatus;
|
||||
emphasis: TextEmphasis;
|
||||
display?: ToolDisplay;
|
||||
progressMessage?: string;
|
||||
originalRequestName?: string;
|
||||
hideSummary?: boolean;
|
||||
};
|
||||
|
||||
export const ToolInfo: React.FC<ToolInfoProps> = ({
|
||||
@@ -204,10 +201,8 @@ export const ToolInfo: React.FC<ToolInfoProps> = ({
|
||||
description,
|
||||
status: coreStatus,
|
||||
emphasis,
|
||||
display,
|
||||
progressMessage: _progressMessage,
|
||||
originalRequestName,
|
||||
hideSummary,
|
||||
}) => {
|
||||
const status = mapCoreStatusToDisplayStatus(coreStatus);
|
||||
const nameColor = React.useMemo<string>(() => {
|
||||
@@ -228,15 +223,11 @@ export const ToolInfo: React.FC<ToolInfoProps> = ({
|
||||
// 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 = hideSummary ? undefined : display?.resultSummary;
|
||||
|
||||
return (
|
||||
<Box overflow="hidden" height={1} flexGrow={1} flexShrink={1}>
|
||||
<Text strikethrough={status === ToolCallStatus.Canceled} wrap="truncate">
|
||||
<Text color={nameColor} bold>
|
||||
{displayName}
|
||||
{name}
|
||||
</Text>
|
||||
{originalRequestName && originalRequestName !== name && (
|
||||
<Text color={theme.text.secondary} italic>
|
||||
@@ -247,13 +238,7 @@ export const ToolInfo: React.FC<ToolInfoProps> = ({
|
||||
{!isCompletedAskUser && (
|
||||
<>
|
||||
{' '}
|
||||
<Text color={theme.text.secondary}>{displayDescription}</Text>
|
||||
</>
|
||||
)}
|
||||
{displaySummary && (
|
||||
<>
|
||||
<Text color={theme.text.accent}> → </Text>
|
||||
<Text color={theme.text.accent}>{displaySummary}</Text>
|
||||
<Text color={theme.text.secondary}>{description}</Text>
|
||||
</>
|
||||
)}
|
||||
</Text>
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
type ToolCall,
|
||||
type SerializableConfirmationDetails,
|
||||
type ToolResultDisplay,
|
||||
type ToolDisplay,
|
||||
debugLogger,
|
||||
CoreToolCallStatus,
|
||||
type SubagentActivityItem,
|
||||
@@ -36,17 +35,10 @@ export function mapToDisplay(
|
||||
borderBottom?: boolean;
|
||||
borderColor?: string;
|
||||
borderDimColor?: boolean;
|
||||
isAgentSessionInteractive?: boolean;
|
||||
} = {},
|
||||
): HistoryItemToolGroup {
|
||||
const toolCalls = Array.isArray(toolOrTools) ? toolOrTools : [toolOrTools];
|
||||
const {
|
||||
borderTop,
|
||||
borderBottom,
|
||||
borderColor,
|
||||
borderDimColor,
|
||||
isAgentSessionInteractive,
|
||||
} = options;
|
||||
const { borderTop, borderBottom, borderColor, borderDimColor } = options;
|
||||
|
||||
const toolDisplays = toolCalls.map((call): IndividualToolCallDisplay => {
|
||||
let description: string;
|
||||
@@ -71,7 +63,6 @@ export function mapToDisplay(
|
||||
};
|
||||
|
||||
let resultDisplay: ToolResultDisplay | undefined = undefined;
|
||||
let display: ToolDisplay | undefined = undefined;
|
||||
let confirmationDetails: SerializableConfirmationDetails | undefined =
|
||||
undefined;
|
||||
let outputFile: string | undefined = undefined;
|
||||
@@ -84,17 +75,11 @@ export function mapToDisplay(
|
||||
switch (call.status) {
|
||||
case CoreToolCallStatus.Success:
|
||||
resultDisplay = call.response.resultDisplay;
|
||||
if (isAgentSessionInteractive) {
|
||||
display = call.response.display;
|
||||
}
|
||||
outputFile = call.response.outputFile;
|
||||
break;
|
||||
case CoreToolCallStatus.Error:
|
||||
case CoreToolCallStatus.Cancelled:
|
||||
resultDisplay = call.response.resultDisplay;
|
||||
if (isAgentSessionInteractive) {
|
||||
display = call.response.display;
|
||||
}
|
||||
break;
|
||||
case CoreToolCallStatus.AwaitingApproval:
|
||||
correlationId = call.correlationId;
|
||||
@@ -127,7 +112,6 @@ export function mapToDisplay(
|
||||
status: call.status,
|
||||
isClientInitiated: !!call.request.isClientInitiated,
|
||||
kind: call.tool?.kind,
|
||||
display,
|
||||
resultDisplay,
|
||||
confirmationDetails,
|
||||
outputFile,
|
||||
|
||||
@@ -224,9 +224,9 @@ export const useAgentStream = ({
|
||||
else if (evtStatus === 'success')
|
||||
status = CoreToolCallStatus.Success;
|
||||
|
||||
const display = event.display?.result;
|
||||
const liveOutput =
|
||||
displayContentToString(event.display?.result) ??
|
||||
tc.resultDisplay;
|
||||
displayContentToString(display) ?? tc.resultDisplay;
|
||||
const progressMessage =
|
||||
legacyState?.progressMessage ?? tc.progressMessage;
|
||||
const progress = legacyState?.progress ?? tc.progress;
|
||||
@@ -237,7 +237,6 @@ export const useAgentStream = ({
|
||||
|
||||
return {
|
||||
...tc,
|
||||
name: event.display?.name ?? tc.name,
|
||||
status,
|
||||
display: event.display
|
||||
? { ...tc.display, ...event.display }
|
||||
@@ -260,13 +259,12 @@ export const useAgentStream = ({
|
||||
|
||||
const legacyState = event._meta?.legacyState;
|
||||
const outputFile = legacyState?.outputFile;
|
||||
const display = event.display;
|
||||
const display = event.display?.result;
|
||||
const resultDisplay =
|
||||
displayContentToString(display?.result) ?? tc.resultDisplay;
|
||||
displayContentToString(display) ?? tc.resultDisplay;
|
||||
|
||||
return {
|
||||
...tc,
|
||||
name: display?.name ?? tc.name,
|
||||
status: event.isError
|
||||
? CoreToolCallStatus.Error
|
||||
: CoreToolCallStatus.Success,
|
||||
|
||||
Reference in New Issue
Block a user