From 33743d347b6721f8eec537d01ad9f6a95b4c6683 Mon Sep 17 00:00:00 2001 From: Taylor Mullen Date: Thu, 15 May 2025 00:19:41 -0700 Subject: Fix: Prevent UI tearing and improve display of long content This commit introduces several changes to better manage terminal height and prevent UI tearing, especially when displaying long tool outputs or when the pending history item exceeds the available terminal height. - Calculate and utilize available terminal height in `App.tsx`, `HistoryItemDisplay.tsx`, `ToolGroupMessage.tsx`, and `ToolMessage.tsx`. - Refresh the static display area in `App.tsx` when a pending history item is too large, working around an Ink bug (see https://github.com/vadimdemedes/ink/pull/717). - Truncate long tool output in `ToolMessage.tsx` and indicate the number of hidden lines. - Refactor `App.tsx` to correctly measure and account for footer height. Fixes https://b.corp.google.com/issues/414196943 --- .../cli/src/ui/components/messages/ToolMessage.tsx | 45 ++++++++++++++++++---- 1 file changed, 38 insertions(+), 7 deletions(-) (limited to 'packages/cli/src/ui/components/messages/ToolMessage.tsx') diff --git a/packages/cli/src/ui/components/messages/ToolMessage.tsx b/packages/cli/src/ui/components/messages/ToolMessage.tsx index 3b58c052..220578de 100644 --- a/packages/cli/src/ui/components/messages/ToolMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolMessage.tsx @@ -12,14 +12,38 @@ import { DiffRenderer } from './DiffRenderer.js'; import { Colors } from '../../colors.js'; import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js'; -export const ToolMessage: React.FC = ({ +export interface ToolMessageProps extends IndividualToolCallDisplay { + availableTerminalHeight: number; +} + +export const ToolMessage: React.FC = ({ name, description, resultDisplay, status, + availableTerminalHeight, }) => { const statusIndicatorWidth = 3; const hasResult = resultDisplay && resultDisplay.toString().trim().length > 0; + const staticHeight = /* Header */ 1; + availableTerminalHeight -= staticHeight; + + let displayableResult = resultDisplay; + let hiddenLines = 0; + + // Truncate the overall string content if it's too long. + // MarkdownRenderer will handle specific truncation for code blocks within this content. + if (typeof resultDisplay === 'string' && resultDisplay.length > 0) { + const lines = resultDisplay.split('\n'); + // Estimate available height for this specific tool message content area + // This is a rough estimate; ideally, we'd have a more precise measurement. + const contentHeightEstimate = availableTerminalHeight - 5; // Subtracting lines for tool name, status, padding etc. + if (lines.length > contentHeightEstimate && contentHeightEstimate > 0) { + displayableResult = lines.slice(0, contentHeightEstimate).join('\n'); + hiddenLines = lines.length - contentHeightEstimate; + } + } + return ( @@ -56,15 +80,22 @@ export const ToolMessage: React.FC = ({ {hasResult && ( - - {/* Use default text color (white) or gray instead of dimColor */} - {typeof resultDisplay === 'string' && ( + + {typeof displayableResult === 'string' && ( - + )} - {typeof resultDisplay === 'object' && ( - + {typeof displayableResult === 'object' && ( + + )} + {hiddenLines > 0 && ( + + + ... {hiddenLines} more line{hiddenLines === 1 ? '' : 's'}{' '} + hidden ... + + )} -- cgit v1.2.3