From 558f1c96c7163a0f4d29cce5a76026f7cd7703eb Mon Sep 17 00:00:00 2001 From: Dev Randalpura Date: Thu, 12 Mar 2026 14:27:32 -0500 Subject: [PATCH] Addressed case with 0 terminal height --- packages/cli/src/ui/components/AnsiOutput.tsx | 6 ++- .../components/messages/ToolResultDisplay.tsx | 8 ++- .../cli/src/ui/utils/toolLayoutUtils.test.ts | 53 +++++++------------ packages/cli/src/ui/utils/toolLayoutUtils.ts | 10 ++-- 4 files changed, 36 insertions(+), 41 deletions(-) diff --git a/packages/cli/src/ui/components/AnsiOutput.tsx b/packages/cli/src/ui/components/AnsiOutput.tsx index cc17b6b6b0..a1b30b0856 100644 --- a/packages/cli/src/ui/components/AnsiOutput.tsx +++ b/packages/cli/src/ui/components/AnsiOutput.tsx @@ -35,7 +35,11 @@ export const AnsiOutputText: React.FC = ({ ? Math.min(availableHeightLimit, maxLines) : (availableHeightLimit ?? maxLines ?? DEFAULT_HEIGHT); - const lastLines = disableTruncation ? data : data.slice(-numLinesRetained); + const lastLines = disableTruncation + ? data + : numLinesRetained === 0 + ? [] + : data.slice(-numLinesRetained); return ( {lastLines.map((line: AnsiLine, lineIndex: number) => ( diff --git a/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx b/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx index 1c29407e91..bc382471ba 100644 --- a/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx +++ b/packages/cli/src/ui/components/messages/ToolResultDisplay.tsx @@ -87,7 +87,7 @@ export const ToolResultDisplay: React.FC = ({ if (text.length > MAXIMUM_RESULT_DISPLAY_CHARACTERS) { text = '...' + text.slice(-MAXIMUM_RESULT_DISPLAY_CHARACTERS); } - if (maxLines) { + if (maxLines !== undefined) { const hasTrailingNewline = text.endsWith('\n'); const contentText = hasTrailingNewline ? text.slice(0, -1) : text; const lines = contentText.split('\n'); @@ -103,7 +103,11 @@ export const ToolResultDisplay: React.FC = ({ return { truncatedResultDisplay: text, hiddenLinesCount: hiddenLines }; } - if (Array.isArray(resultDisplay) && !isAlternateBuffer && maxLines) { + if ( + Array.isArray(resultDisplay) && + !isAlternateBuffer && + maxLines !== undefined + ) { if (resultDisplay.length > maxLines) { // We will have a label from MaxSizedBox. Reserve space for it. const targetLines = Math.max(1, maxLines - 1); diff --git a/packages/cli/src/ui/utils/toolLayoutUtils.test.ts b/packages/cli/src/ui/utils/toolLayoutUtils.test.ts index d8c74dd31a..b0c0a54916 100644 --- a/packages/cli/src/ui/utils/toolLayoutUtils.test.ts +++ b/packages/cli/src/ui/utils/toolLayoutUtils.test.ts @@ -8,8 +8,6 @@ import { describe, it, expect } from 'vitest'; import { calculateToolContentMaxLines, calculateShellMaxLines, - TOOL_RESULT_STATIC_HEIGHT, - TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT, } from './toolLayoutUtils.js'; import { CoreToolCallStatus } from '@google/gemini-cli-core'; import { @@ -36,26 +34,26 @@ describe('toolLayoutUtils', () => { expect(result).toBe(10); }); - it('caps height to prevent overflow in constrained terminal (Standard mode)', () => { + it('returns available space directly in constrained terminal (Standard mode)', () => { const availableTerminalHeight = 2; // Very small const result = calculateToolContentMaxLines({ availableTerminalHeight, isAlternateBuffer: false, }); - // Math.max(0, 2 - 1 - 2) = 0 - expect(result).toBe(0); + // Math.max(0, 2) = 2 + expect(result).toBe(2); }); - it('caps height to prevent overflow in constrained terminal (ASB mode)', () => { + it('returns available space directly in constrained terminal (ASB mode)', () => { const availableTerminalHeight = 4; // Very small const result = calculateToolContentMaxLines({ availableTerminalHeight, isAlternateBuffer: true, }); - // Math.max(0, 4 - 1 - 6) = 0 - expect(result).toBe(0); + // Math.max(0, 4) = 4 + expect(result).toBe(4); }); it('returns remaining space if sufficient space exists (Standard mode)', () => { @@ -65,8 +63,8 @@ describe('toolLayoutUtils', () => { isAlternateBuffer: false, }); - // Space remaining is 20 - 1 - 2 = 17 - expect(result).toBe(17); + // Math.max(0, 20) = 20 + expect(result).toBe(20); }); it('returns remaining space if sufficient space exists (ASB mode)', () => { @@ -76,19 +74,8 @@ describe('toolLayoutUtils', () => { isAlternateBuffer: true, }); - // Space remaining is 20 - 1 - 6 = 13 - expect(result).toBe(13); - }); - - it('returns 0 if availableTerminalHeight is <= TOOL_RESULT_STATIC_HEIGHT + reservedLines', () => { - const result = calculateToolContentMaxLines({ - availableTerminalHeight: - TOOL_RESULT_STATIC_HEIGHT + TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT, - isAlternateBuffer: false, - }); - - // Cap at 3 - 1 - 2 = 0 - expect(result).toBe(0); + // Math.max(0, 20) = 20 + expect(result).toBe(20); }); }); @@ -129,32 +116,32 @@ describe('toolLayoutUtils', () => { expect(result).toBeUndefined(); }); - it('handles small availableTerminalHeight gracefully to prevent overflow in Standard mode', () => { + it('handles small availableTerminalHeight gracefully without overflow in Standard mode', () => { const result = calculateShellMaxLines({ status: CoreToolCallStatus.Executing, isAlternateBuffer: false, isThisShellFocused: false, - availableTerminalHeight: 2, // Too small to subtract 1 + 2 + availableTerminalHeight: 2, constrainHeight: true, isExpandable: false, }); - // Math.max(0, 2 - 1 - 2) = 0 - expect(result).toBe(0); + // Math.max(0, 2) = 2 + expect(result).toBe(2); }); - it('handles small availableTerminalHeight gracefully to prevent overflow in ASB mode', () => { + it('handles small availableTerminalHeight gracefully without overflow in ASB mode', () => { const result = calculateShellMaxLines({ status: CoreToolCallStatus.Executing, isAlternateBuffer: true, isThisShellFocused: false, - availableTerminalHeight: 6, // Too small to subtract 1 + 6 + availableTerminalHeight: 6, constrainHeight: true, isExpandable: false, }); - // Math.max(0, 6 - 1 - 6) = 0 - expect(result).toBe(0); + // Math.max(0, 6) = 6 + expect(result).toBe(6); }); it('handles negative availableTerminalHeight gracefully', () => { @@ -180,8 +167,8 @@ describe('toolLayoutUtils', () => { isExpandable: false, }); - // 30 - 1 (static) - 6 (ASB reserved) = 23 - expect(result).toBe(23); + // 30 + expect(result).toBe(30); }); it('falls back to COMPLETED_SHELL_MAX_LINES for completed shells if space allows', () => { diff --git a/packages/cli/src/ui/utils/toolLayoutUtils.ts b/packages/cli/src/ui/utils/toolLayoutUtils.ts index a99bd8a7b0..c6498ba7f8 100644 --- a/packages/cli/src/ui/utils/toolLayoutUtils.ts +++ b/packages/cli/src/ui/utils/toolLayoutUtils.ts @@ -15,7 +15,6 @@ import { CoreToolCallStatus } from '@google/gemini-cli-core'; * These MUST be kept in sync between ToolGroupMessage (for overflow detection) * and ToolResultDisplay (for actual truncation). */ -export const TOOL_RESULT_STATIC_HEIGHT = 1; export const TOOL_RESULT_ASB_RESERVED_LINE_COUNT = 6; export const TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT = 2; export const TOOL_RESULT_MIN_LINES_SHOWN = 2; @@ -35,9 +34,10 @@ export function calculateToolContentMaxLines(options: { }): number | undefined { const { availableTerminalHeight, maxLinesLimit } = options; - let contentHeight = availableTerminalHeight - ? Math.max(TOOL_RESULT_STATIC_HEIGHT, availableTerminalHeight) - : undefined; + let contentHeight = + availableTerminalHeight !== undefined + ? Math.max(0, availableTerminalHeight) + : undefined; if (maxLinesLimit) { contentHeight = @@ -84,7 +84,7 @@ export function calculateShellMaxLines(options: { return isAlternateBuffer ? ACTIVE_SHELL_MAX_LINES : undefined; } - const maxLinesBasedOnHeight = Math.max(1, availableTerminalHeight); + const maxLinesBasedOnHeight = Math.max(0, availableTerminalHeight); // 3. Handle ASB mode focus expansion. // We allow a focused shell in ASB mode to take up the full available height,