mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-10 18:10:43 -07:00
fix(ui): resolve rebase conflicts and type errors for ToolDisplay
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
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';
|
||||
@@ -286,6 +287,7 @@ 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 => {
|
||||
@@ -369,11 +371,36 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a display.result or a simple success, use it
|
||||
// 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: undefined, // Payload rendering will be updated in Step 5
|
||||
payload,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -439,6 +466,8 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
originalDescription,
|
||||
isAlternateBuffer,
|
||||
display,
|
||||
isActuallyCompact,
|
||||
isExpanded,
|
||||
]);
|
||||
|
||||
const { description, summary } = viewParts;
|
||||
@@ -476,6 +505,10 @@ 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;
|
||||
|
||||
@@ -495,6 +528,8 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
diffLines.length,
|
||||
viewParts.payload,
|
||||
outputFile,
|
||||
isActuallyCompact,
|
||||
display,
|
||||
]);
|
||||
|
||||
const keyExtractor = (_item: React.ReactNode, index: number) =>
|
||||
@@ -505,7 +540,16 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Box marginLeft={2} flexDirection="row" flexWrap="wrap">
|
||||
<Box
|
||||
marginLeft={2}
|
||||
flexDirection="row"
|
||||
flexWrap="wrap"
|
||||
ref={
|
||||
isActuallyCompact || (isAlternateBuffer && diff)
|
||||
? toggleRef
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Box flexDirection="row" flexShrink={1}>
|
||||
<ToolStatusIndicator status={status} name={name} />
|
||||
<Box maxWidth={25} flexShrink={0} flexGrow={0}>
|
||||
@@ -519,12 +563,7 @@ export const DenseToolMessage: React.FC<DenseToolMessageProps> = (props) => {
|
||||
</Box>
|
||||
|
||||
{summary && (
|
||||
<Box
|
||||
key="tool-summary"
|
||||
ref={isAlternateBuffer && diff ? toggleRef : undefined}
|
||||
marginLeft={1}
|
||||
flexGrow={0}
|
||||
>
|
||||
<Box key="tool-summary" marginLeft={1} flexGrow={0}>
|
||||
{summary}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -87,6 +87,11 @@ 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
|
||||
@@ -139,7 +144,7 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
||||
/>
|
||||
)}
|
||||
<ToolResultDisplay
|
||||
resultDisplay={resultDisplay}
|
||||
resultDisplay={effectiveResultDisplay}
|
||||
availableTerminalHeight={availableTerminalHeight}
|
||||
terminalWidth={terminalWidth}
|
||||
renderOutputAsMarkdown={renderOutputAsMarkdown}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
type ToolCall,
|
||||
type SerializableConfirmationDetails,
|
||||
type ToolResultDisplay,
|
||||
type ToolDisplay,
|
||||
debugLogger,
|
||||
CoreToolCallStatus,
|
||||
type SubagentActivityItem,
|
||||
@@ -35,10 +36,17 @@ export function mapToDisplay(
|
||||
borderBottom?: boolean;
|
||||
borderColor?: string;
|
||||
borderDimColor?: boolean;
|
||||
isAgentSessionInteractive?: boolean;
|
||||
} = {},
|
||||
): HistoryItemToolGroup {
|
||||
const toolCalls = Array.isArray(toolOrTools) ? toolOrTools : [toolOrTools];
|
||||
const { borderTop, borderBottom, borderColor, borderDimColor } = options;
|
||||
const {
|
||||
borderTop,
|
||||
borderBottom,
|
||||
borderColor,
|
||||
borderDimColor,
|
||||
isAgentSessionInteractive,
|
||||
} = options;
|
||||
|
||||
const toolDisplays = toolCalls.map((call): IndividualToolCallDisplay => {
|
||||
let description: string;
|
||||
@@ -63,6 +71,7 @@ export function mapToDisplay(
|
||||
};
|
||||
|
||||
let resultDisplay: ToolResultDisplay | undefined = undefined;
|
||||
let display: ToolDisplay | undefined = undefined;
|
||||
let confirmationDetails: SerializableConfirmationDetails | undefined =
|
||||
undefined;
|
||||
let outputFile: string | undefined = undefined;
|
||||
@@ -75,11 +84,17 @@ 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;
|
||||
@@ -112,6 +127,7 @@ 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(display) ?? tc.resultDisplay;
|
||||
displayContentToString(event.display?.result) ??
|
||||
tc.resultDisplay;
|
||||
const progressMessage =
|
||||
legacyState?.progressMessage ?? tc.progressMessage;
|
||||
const progress = legacyState?.progress ?? tc.progress;
|
||||
@@ -237,6 +237,7 @@ export const useAgentStream = ({
|
||||
|
||||
return {
|
||||
...tc,
|
||||
name: event.display?.name ?? tc.name,
|
||||
status,
|
||||
display: event.display
|
||||
? { ...tc.display, ...event.display }
|
||||
@@ -259,12 +260,13 @@ export const useAgentStream = ({
|
||||
|
||||
const legacyState = event._meta?.legacyState;
|
||||
const outputFile = legacyState?.outputFile;
|
||||
const display = event.display?.result;
|
||||
const display = event.display;
|
||||
const resultDisplay =
|
||||
displayContentToString(display) ?? tc.resultDisplay;
|
||||
displayContentToString(display?.result) ?? tc.resultDisplay;
|
||||
|
||||
return {
|
||||
...tc,
|
||||
name: display?.name ?? tc.name,
|
||||
status: event.isError
|
||||
? CoreToolCallStatus.Error
|
||||
: CoreToolCallStatus.Success,
|
||||
|
||||
Reference in New Issue
Block a user