From 3e786aad1c0baeb71099ca825200eb445dcf6ed3 Mon Sep 17 00:00:00 2001 From: Dev Randalpura Date: Fri, 6 Mar 2026 11:59:31 -0500 Subject: [PATCH] Changed max height --- .../cli/src/ui/components/MainContent.tsx | 19 +- .../__snapshots__/MainContent.test.tsx.snap | 35 ++- .../cli/src/ui/utils/toolLayoutUtils.test.ts | 213 ++++++++++++++++++ packages/cli/src/ui/utils/toolLayoutUtils.ts | 13 +- 4 files changed, 260 insertions(+), 20 deletions(-) create mode 100644 packages/cli/src/ui/utils/toolLayoutUtils.test.ts diff --git a/packages/cli/src/ui/components/MainContent.tsx b/packages/cli/src/ui/components/MainContent.tsx index 7386a246e7..7d26f9f88e 100644 --- a/packages/cli/src/ui/components/MainContent.tsx +++ b/packages/cli/src/ui/components/MainContent.tsx @@ -48,6 +48,7 @@ export const MainContent = () => { pendingHistoryItems, mainAreaWidth, staticAreaMaxItemHeight, + availableTerminalHeight, cleanUiDetailsVisible, } = uiState; const showHeaderDetails = cleanUiDetailsVisible; @@ -70,9 +71,11 @@ export const MainContent = () => { { uiState.history, mainAreaWidth, staticAreaMaxItemHeight, + availableTerminalHeight, uiState.slashCommands, uiState.constrainHeight, lastUserPromptIndex, @@ -110,7 +114,7 @@ export const MainContent = () => { { [ pendingHistoryItems, uiState.constrainHeight, - staticAreaMaxItemHeight, + availableTerminalHeight, mainAreaWidth, showConfirmationQueue, confirmingTool, @@ -161,9 +165,11 @@ export const MainContent = () => { { pendingItems, uiState.constrainHeight, staticAreaMaxItemHeight, + availableTerminalHeight, ], ); diff --git a/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap index d01043eee9..35ed23e664 100644 --- a/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/MainContent.test.tsx.snap @@ -6,11 +6,15 @@ AppHeader(full) ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │ ⊶ Shell Command Running a long command... │ │ │ -│ Line 10 │ -│ Line 11 │ -│ Line 12 │ -│ Line 13 │ -│ Line 14 │ +│ Line 6 │ +│ Line 7 │ +│ Line 8 │ +│ Line 9 ▄ │ +│ Line 10 █ │ +│ Line 11 █ │ +│ Line 12 █ │ +│ Line 13 █ │ +│ Line 14 █ │ │ Line 15 █ │ │ Line 16 █ │ │ Line 17 █ │ @@ -28,11 +32,15 @@ AppHeader(full) ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │ ⊶ Shell Command Running a long command... │ │ │ -│ Line 10 │ -│ Line 11 │ -│ Line 12 │ -│ Line 13 │ -│ Line 14 │ +│ Line 6 │ +│ Line 7 │ +│ Line 8 │ +│ Line 9 ▄ │ +│ Line 10 █ │ +│ Line 11 █ │ +│ Line 12 █ │ +│ Line 13 █ │ +│ Line 14 █ │ │ Line 15 █ │ │ Line 16 █ │ │ Line 17 █ │ @@ -49,7 +57,12 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Con ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │ ⊶ Shell Command Running a long command... │ │ │ -│ ... first 11 lines hidden (Ctrl+O to show) ... │ +│ ... first 6 lines hidden (Ctrl+O to show) ... │ +│ Line 7 │ +│ Line 8 │ +│ Line 9 │ +│ Line 10 │ +│ Line 11 │ │ Line 12 │ │ Line 13 │ │ Line 14 │ diff --git a/packages/cli/src/ui/utils/toolLayoutUtils.test.ts b/packages/cli/src/ui/utils/toolLayoutUtils.test.ts new file mode 100644 index 0000000000..d8c74dd31a --- /dev/null +++ b/packages/cli/src/ui/utils/toolLayoutUtils.test.ts @@ -0,0 +1,213 @@ +/** + * @license + * Copyright 2026 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +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 { + ACTIVE_SHELL_MAX_LINES, + COMPLETED_SHELL_MAX_LINES, +} from '../constants.js'; + +describe('toolLayoutUtils', () => { + describe('calculateToolContentMaxLines', () => { + it('returns undefined if availableTerminalHeight is undefined', () => { + const result = calculateToolContentMaxLines({ + availableTerminalHeight: undefined, + isAlternateBuffer: false, + }); + expect(result).toBeUndefined(); + }); + + it('returns maxLinesLimit if maxLinesLimit applies but availableTerminalHeight is undefined', () => { + const result = calculateToolContentMaxLines({ + availableTerminalHeight: undefined, + isAlternateBuffer: false, + maxLinesLimit: 10, + }); + expect(result).toBe(10); + }); + + it('caps height to prevent overflow 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); + }); + + it('caps height to prevent overflow 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); + }); + + it('returns remaining space if sufficient space exists (Standard mode)', () => { + const availableTerminalHeight = 20; + const result = calculateToolContentMaxLines({ + availableTerminalHeight, + isAlternateBuffer: false, + }); + + // Space remaining is 20 - 1 - 2 = 17 + expect(result).toBe(17); + }); + + it('returns remaining space if sufficient space exists (ASB mode)', () => { + const availableTerminalHeight = 20; + const result = calculateToolContentMaxLines({ + availableTerminalHeight, + 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); + }); + }); + + describe('calculateShellMaxLines', () => { + it('returns undefined when not constrained and is expandable', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: false, + isThisShellFocused: false, + availableTerminalHeight: 20, + constrainHeight: false, + isExpandable: true, + }); + expect(result).toBeUndefined(); + }); + + it('returns ACTIVE_SHELL_MAX_LINES for ASB mode when availableTerminalHeight is undefined', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: true, + isThisShellFocused: false, + availableTerminalHeight: undefined, + constrainHeight: true, + isExpandable: false, + }); + expect(result).toBe(ACTIVE_SHELL_MAX_LINES); + }); + + it('returns undefined for Standard mode when availableTerminalHeight is undefined', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: false, + isThisShellFocused: false, + availableTerminalHeight: undefined, + constrainHeight: true, + isExpandable: false, + }); + expect(result).toBeUndefined(); + }); + + it('handles small availableTerminalHeight gracefully to prevent overflow in Standard mode', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: false, + isThisShellFocused: false, + availableTerminalHeight: 2, // Too small to subtract 1 + 2 + constrainHeight: true, + isExpandable: false, + }); + + // Math.max(0, 2 - 1 - 2) = 0 + expect(result).toBe(0); + }); + + it('handles small availableTerminalHeight gracefully to prevent overflow in ASB mode', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: true, + isThisShellFocused: false, + availableTerminalHeight: 6, // Too small to subtract 1 + 6 + constrainHeight: true, + isExpandable: false, + }); + + // Math.max(0, 6 - 1 - 6) = 0 + expect(result).toBe(0); + }); + + it('handles negative availableTerminalHeight gracefully', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: false, + isThisShellFocused: false, + availableTerminalHeight: -5, + constrainHeight: true, + isExpandable: false, + }); + + expect(result).toBe(0); + }); + + it('returns maxLinesBasedOnHeight for focused ASB shells', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: true, + isThisShellFocused: true, + availableTerminalHeight: 30, + constrainHeight: false, + isExpandable: false, + }); + + // 30 - 1 (static) - 6 (ASB reserved) = 23 + expect(result).toBe(23); + }); + + it('falls back to COMPLETED_SHELL_MAX_LINES for completed shells if space allows', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Success, + isAlternateBuffer: false, + isThisShellFocused: false, + availableTerminalHeight: 100, + constrainHeight: true, + isExpandable: false, + }); + + expect(result).toBe(COMPLETED_SHELL_MAX_LINES); + }); + + it('falls back to ACTIVE_SHELL_MAX_LINES for executing shells if space allows', () => { + const result = calculateShellMaxLines({ + status: CoreToolCallStatus.Executing, + isAlternateBuffer: false, + isThisShellFocused: false, + availableTerminalHeight: 100, + constrainHeight: true, + isExpandable: false, + }); + + expect(result).toBe(ACTIVE_SHELL_MAX_LINES); + }); + }); +}); diff --git a/packages/cli/src/ui/utils/toolLayoutUtils.ts b/packages/cli/src/ui/utils/toolLayoutUtils.ts index 8f619901f6..7b35f1ccd5 100644 --- a/packages/cli/src/ui/utils/toolLayoutUtils.ts +++ b/packages/cli/src/ui/utils/toolLayoutUtils.ts @@ -26,7 +26,7 @@ export const TOOL_RESULT_MIN_LINES_SHOWN = 2; * This accounts for: * 1. The static height of the tool message (name, status line). * 2. Reserved space for hints and padding (different in ASB vs Standard mode). - * 3. Enforcing a minimum number of lines shown. + * 3. Enforcing a physical minimum size based on terminal limits. */ export function calculateToolContentMaxLines(options: { availableTerminalHeight: number | undefined; @@ -41,8 +41,8 @@ export function calculateToolContentMaxLines(options: { let contentHeight = availableTerminalHeight ? Math.max( + 0, availableTerminalHeight - TOOL_RESULT_STATIC_HEIGHT - reservedLines, - TOOL_RESULT_MIN_LINES_SHOWN + 1, ) : undefined; @@ -91,7 +91,14 @@ export function calculateShellMaxLines(options: { return isAlternateBuffer ? ACTIVE_SHELL_MAX_LINES : undefined; } - const maxLinesBasedOnHeight = Math.max(1, availableTerminalHeight - 2); + const reservedLines = isAlternateBuffer + ? TOOL_RESULT_ASB_RESERVED_LINE_COUNT + : TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT; + + const maxLinesBasedOnHeight = Math.max( + 0, + availableTerminalHeight - TOOL_RESULT_STATIC_HEIGHT - reservedLines, + ); // 3. Handle ASB mode focus expansion. // We allow a focused shell in ASB mode to take up the full available height,