diff --git a/packages/cli/src/ui/components/ToolConfirmationQueue.test.tsx b/packages/cli/src/ui/components/ToolConfirmationQueue.test.tsx
index 6e0bb87136..d1e855b5c3 100644
--- a/packages/cli/src/ui/components/ToolConfirmationQueue.test.tsx
+++ b/packages/cli/src/ui/components/ToolConfirmationQueue.test.tsx
@@ -7,7 +7,7 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Box } from 'ink';
import { ToolConfirmationQueue } from './ToolConfirmationQueue.js';
-import { StreamingState } from '../types.js';
+import { StreamingState, ToolCallStatus } from '../types.js';
import { renderWithProviders } from '../../test-utils/render.js';
import { waitFor } from '../../test-utils/async.js';
import { type Config, CoreToolCallStatus } from '@google/gemini-cli-core';
@@ -223,6 +223,58 @@ describe('ToolConfirmationQueue', () => {
expect(lastFrame()).toMatchSnapshot();
});
+ it('provides more height for ask_user by subtracting less overhead', async () => {
+ const confirmingTool = {
+ tool: {
+ callId: 'call-1',
+ name: 'ask_user',
+ description: 'ask user',
+ status: ToolCallStatus.Confirming,
+ confirmationDetails: {
+ type: 'ask_user' as const,
+ questions: [
+ {
+ type: 'choice',
+ header: 'Height Test',
+ question: 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6',
+ options: [{ label: 'Option 1', description: 'Desc' }],
+ },
+ ],
+ },
+ },
+ index: 1,
+ total: 1,
+ };
+
+ const { lastFrame } = renderWithProviders(
+ ,
+ {
+ config: mockConfig,
+ uiState: {
+ terminalWidth: 80,
+ terminalHeight: 40,
+ availableTerminalHeight: 20,
+ constrainHeight: true,
+ streamingState: StreamingState.WaitingForConfirmation,
+ },
+ },
+ );
+
+ // Calculation:
+ // availableTerminalHeight: 20 -> maxHeight: 19 (20-1)
+ // hideToolIdentity is true for ask_user -> subtracts 4 instead of 6
+ // availableContentHeight = 19 - 4 = 15
+ // ToolConfirmationMessage handlesOwnUI=true -> returns full 15
+ // AskUserDialog uses 15 lines to render its multi-line question and options.
+ await waitFor(() => {
+ expect(lastFrame()).toContain('Line 6');
+ expect(lastFrame()).not.toContain('lines hidden');
+ });
+ expect(lastFrame()).toMatchSnapshot();
+ });
+
it('does not render expansion hint when constrainHeight is false', () => {
const longDiff = 'line\n'.repeat(50);
const confirmingTool = {
diff --git a/packages/cli/src/ui/components/ToolConfirmationQueue.tsx b/packages/cli/src/ui/components/ToolConfirmationQueue.tsx
index 52cba7e0d7..e3c18e0231 100644
--- a/packages/cli/src/ui/components/ToolConfirmationQueue.tsx
+++ b/packages/cli/src/ui/components/ToolConfirmationQueue.tsx
@@ -60,6 +60,12 @@ export const ToolConfirmationQueue: React.FC = ({
? Math.max(uiAvailableHeight - 1, 4)
: Math.floor(terminalHeight * 0.5);
+ const isRoutine =
+ tool.confirmationDetails?.type === 'ask_user' ||
+ tool.confirmationDetails?.type === 'exit_plan_mode';
+ const borderColor = isRoutine ? theme.status.success : theme.status.warning;
+ const hideToolIdentity = isRoutine;
+
// ToolConfirmationMessage needs to know the height available for its OWN content.
// We subtract the lines used by the Queue wrapper:
// - 2 lines for the rounded border
@@ -67,15 +73,9 @@ export const ToolConfirmationQueue: React.FC = ({
// - 2 lines for Tool Identity (text + margin)
const availableContentHeight =
constrainHeight && !isAlternateBuffer
- ? Math.max(maxHeight - 6, 4)
+ ? Math.max(maxHeight - (hideToolIdentity ? 4 : 6), 4)
: undefined;
- const isRoutine =
- tool.confirmationDetails?.type === 'ask_user' ||
- tool.confirmationDetails?.type === 'exit_plan_mode';
- const borderColor = isRoutine ? theme.status.success : theme.status.warning;
- const hideToolIdentity = isRoutine;
-
return (
diff --git a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap
index aad58b92a7..f8ba499abd 100644
--- a/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap
+++ b/packages/cli/src/ui/components/__snapshots__/ToolConfirmationQueue.test.tsx.snap
@@ -40,6 +40,25 @@ exports[`ToolConfirmationQueue > does not render expansion hint when constrainHe
╰──────────────────────────────────────────────────────────────────────────────╯"
`;
+exports[`ToolConfirmationQueue > provides more height for ask_user by subtracting less overhead 1`] = `
+"╭──────────────────────────────────────────────────────────────────────────────╮
+│ Answer Questions │
+│ │
+│ Line 1 │
+│ Line 2 │
+│ Line 3 │
+│ Line 4 │
+│ Line 5 │
+│ Line 6 │
+│ │
+│ ● 1. Option 1 │
+│ Desc │
+│ 2. Enter a custom value │
+│ │
+│ Enter to select · ↑/↓ to navigate · Esc to cancel │
+╰──────────────────────────────────────────────────────────────────────────────╯"
+`;
+
exports[`ToolConfirmationQueue > renders AskUser tool confirmation with Success color 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────╮
│ Answer Questions │
diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
index 13feb1682f..42642d66f9 100644
--- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
+++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx
@@ -235,6 +235,10 @@ export const ToolConfirmationMessage: React.FC<
return undefined;
}
+ if (handlesOwnUI) {
+ return availableTerminalHeight;
+ }
+
// Calculate the vertical space (in lines) consumed by UI elements
// surrounding the main body content.
const PADDING_OUTER_Y = 2; // Main container has `padding={1}` (top & bottom).
@@ -253,7 +257,7 @@ export const ToolConfirmationMessage: React.FC<
1; // Reserve one line for 'ShowMoreLines' hint
return Math.max(availableTerminalHeight - surroundingElementsHeight, 1);
- }, [availableTerminalHeight, getOptions]);
+ }, [availableTerminalHeight, getOptions, handlesOwnUI]);
const { question, bodyContent, options } = useMemo(() => {
let bodyContent: React.ReactNode | null = null;