mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-20 18:14:29 -07:00
fix(cli): switch default back to terminalBuffer=false and fix regressions introduced for that mode (#24873)
This commit is contained in:
@@ -757,7 +757,7 @@ const SETTINGS_SCHEMA = {
|
||||
label: 'Terminal Buffer',
|
||||
category: 'UI',
|
||||
requiresRestart: true,
|
||||
default: true,
|
||||
default: false,
|
||||
description: 'Use the new terminal buffer architecture for rendering.',
|
||||
showInDialog: true,
|
||||
},
|
||||
|
||||
@@ -156,8 +156,9 @@ export async function startInteractiveUI(
|
||||
useAlternateBuffer || config.getUseTerminalBuffer(),
|
||||
patchConsole: false,
|
||||
alternateBuffer: useAlternateBuffer,
|
||||
renderProcess: config.getUseRenderProcess(),
|
||||
terminalBuffer: config.getUseTerminalBuffer(),
|
||||
renderProcess:
|
||||
config.getUseRenderProcess() && config.getUseTerminalBuffer(),
|
||||
incrementalRendering:
|
||||
settings.merged.ui.incrementalRendering !== false &&
|
||||
useAlternateBuffer &&
|
||||
|
||||
@@ -55,6 +55,12 @@ Footer
|
||||
Gemini CLI v1.2.3
|
||||
|
||||
|
||||
|
||||
Tips for getting started:
|
||||
1. Create GEMINI.md files to customize your interactions
|
||||
2. /help for more information
|
||||
3. Ask coding questions, edit code or run commands
|
||||
4. Be specific for the best results
|
||||
Composer
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -69,6 +69,7 @@ import {
|
||||
AppEvent,
|
||||
TransientMessageType,
|
||||
} from '../../utils/events.js';
|
||||
import '../../test-utils/customMatchers.js';
|
||||
|
||||
vi.mock('../hooks/useShellHistory.js');
|
||||
vi.mock('../hooks/useCommandCompletion.js');
|
||||
@@ -254,7 +255,7 @@ describe('InputPrompt', () => {
|
||||
setText: vi.fn(
|
||||
(newText: string, cursorPosition?: 'start' | 'end' | number) => {
|
||||
mockBuffer.text = newText;
|
||||
mockBuffer.lines = [newText];
|
||||
mockBuffer.lines = newText.split('\n');
|
||||
let col = 0;
|
||||
if (typeof cursorPosition === 'number') {
|
||||
col = cursorPosition;
|
||||
@@ -264,11 +265,18 @@ describe('InputPrompt', () => {
|
||||
col = newText.length;
|
||||
}
|
||||
mockBuffer.cursor = [0, col];
|
||||
mockBuffer.allVisualLines = [newText];
|
||||
mockBuffer.viewportVisualLines = [newText];
|
||||
mockBuffer.allVisualLines = [newText];
|
||||
mockBuffer.visualToLogicalMap = [[0, 0]];
|
||||
mockBuffer.allVisualLines = newText.split('\n');
|
||||
mockBuffer.viewportVisualLines = newText.split('\n');
|
||||
mockBuffer.visualToLogicalMap = newText
|
||||
.split('\n')
|
||||
.map((_, i) => [i, 0] as [number, number]);
|
||||
mockBuffer.visualCursor = [0, col];
|
||||
mockBuffer.visualScrollRow = 0;
|
||||
mockBuffer.viewportHeight = 10;
|
||||
mockBuffer.visualToTransformedMap = newText
|
||||
.split('\n')
|
||||
.map((_, i) => i);
|
||||
mockBuffer.transformationsByLine = newText.split('\n').map(() => []);
|
||||
},
|
||||
),
|
||||
replaceRangeByOffset: vi.fn(),
|
||||
@@ -276,6 +284,7 @@ describe('InputPrompt', () => {
|
||||
allVisualLines: [''],
|
||||
visualCursor: [0, 0],
|
||||
visualScrollRow: 0,
|
||||
viewportHeight: 10,
|
||||
handleInput: vi.fn((key: Key) => {
|
||||
if (defaultKeyMatchers[Command.CLEAR_INPUT](key)) {
|
||||
if (mockBuffer.text.length > 0) {
|
||||
@@ -409,6 +418,7 @@ describe('InputPrompt', () => {
|
||||
getTargetDir: () => path.join('test', 'project', 'src'),
|
||||
getVimMode: () => false,
|
||||
getUseBackgroundColor: () => true,
|
||||
getUseTerminalBuffer: () => false,
|
||||
getTerminalBackground: () => undefined,
|
||||
getWorkspaceContext: () => ({
|
||||
getDirectories: () => ['/test/project/src'],
|
||||
@@ -3779,11 +3789,7 @@ describe('InputPrompt', () => {
|
||||
);
|
||||
|
||||
it('should unfocus embedded shell on click', async () => {
|
||||
props.buffer.text = 'hello';
|
||||
props.buffer.lines = ['hello'];
|
||||
props.buffer.allVisualLines = ['hello'];
|
||||
props.buffer.viewportVisualLines = ['hello'];
|
||||
props.buffer.visualToLogicalMap = [[0, 0]];
|
||||
props.buffer.setText('hello');
|
||||
props.isEmbeddedShellFocused = true;
|
||||
|
||||
const { stdin, stdout, unmount } = await renderWithProviders(
|
||||
@@ -4291,11 +4297,7 @@ describe('InputPrompt', () => {
|
||||
describe('IME Cursor Support', () => {
|
||||
it('should report correct cursor position for simple ASCII text', async () => {
|
||||
const text = 'hello';
|
||||
mockBuffer.text = text;
|
||||
mockBuffer.lines = [text];
|
||||
mockBuffer.allVisualLines = [text];
|
||||
mockBuffer.viewportVisualLines = [text];
|
||||
mockBuffer.visualToLogicalMap = [[0, 0]];
|
||||
mockBuffer.setText(text);
|
||||
mockBuffer.visualCursor = [0, 3]; // Cursor after 'hel'
|
||||
mockBuffer.visualScrollRow = 0;
|
||||
|
||||
@@ -4322,11 +4324,7 @@ describe('InputPrompt', () => {
|
||||
|
||||
it('should report correct cursor position for text with double-width characters', async () => {
|
||||
const text = '👍hello';
|
||||
mockBuffer.text = text;
|
||||
mockBuffer.lines = [text];
|
||||
mockBuffer.allVisualLines = [text];
|
||||
mockBuffer.viewportVisualLines = [text];
|
||||
mockBuffer.visualToLogicalMap = [[0, 0]];
|
||||
mockBuffer.setText(text);
|
||||
mockBuffer.visualCursor = [0, 2]; // Cursor after '👍h' (Note: '👍' is one code point but width 2)
|
||||
mockBuffer.visualScrollRow = 0;
|
||||
|
||||
@@ -4352,11 +4350,7 @@ describe('InputPrompt', () => {
|
||||
|
||||
it('should report correct cursor position for a line full of "😀" emojis', async () => {
|
||||
const text = '😀😀😀';
|
||||
mockBuffer.text = text;
|
||||
mockBuffer.lines = [text];
|
||||
mockBuffer.allVisualLines = [text];
|
||||
mockBuffer.viewportVisualLines = [text];
|
||||
mockBuffer.visualToLogicalMap = [[0, 0]];
|
||||
mockBuffer.setText(text);
|
||||
mockBuffer.visualCursor = [0, 2]; // Cursor after 2 emojis (each 1 code point, width 2)
|
||||
mockBuffer.visualScrollRow = 0;
|
||||
|
||||
@@ -4501,12 +4495,12 @@ describe('InputPrompt', () => {
|
||||
mockBuffer.lines = [logicalLine];
|
||||
mockBuffer.allVisualLines = [visualLine];
|
||||
mockBuffer.viewportVisualLines = [visualLine];
|
||||
mockBuffer.allVisualLines = [visualLine];
|
||||
mockBuffer.visualToLogicalMap = [[0, 0]];
|
||||
mockBuffer.visualToTransformedMap = [0];
|
||||
mockBuffer.transformationsByLine = [transformations];
|
||||
mockBuffer.cursor = [0, cursorCol];
|
||||
mockBuffer.visualCursor = [0, 0];
|
||||
mockBuffer.visualCursor = [0, cursorCol];
|
||||
mockBuffer.visualScrollRow = 0;
|
||||
};
|
||||
|
||||
it('should snapshot collapsed image path', async () => {
|
||||
|
||||
@@ -5,7 +5,14 @@
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import { useCallback, useEffect, useState, useRef, useMemo } from 'react';
|
||||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
useRef,
|
||||
useMemo,
|
||||
Fragment,
|
||||
} from 'react';
|
||||
import clipboardy from 'clipboardy';
|
||||
import { Box, Text, useStdout, type DOMElement } from 'ink';
|
||||
import { SuggestionsDisplay, MAX_WIDTH } from './SuggestionsDisplay.js';
|
||||
@@ -1820,24 +1827,45 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
height={Math.min(buffer.viewportHeight, scrollableData.length)}
|
||||
width="100%"
|
||||
>
|
||||
<ScrollableList
|
||||
ref={listRef}
|
||||
hasFocus={focus}
|
||||
data={scrollableData}
|
||||
renderItem={renderItem}
|
||||
estimatedItemHeight={() => 1}
|
||||
keyExtractor={(item) =>
|
||||
item.type === 'visualLine'
|
||||
? `line-${item.absoluteVisualIdx}`
|
||||
: `ghost-${item.index}`
|
||||
}
|
||||
width="100%"
|
||||
backgroundColor={listBackgroundColor}
|
||||
containerHeight={Math.min(
|
||||
buffer.viewportHeight,
|
||||
scrollableData.length,
|
||||
)}
|
||||
/>
|
||||
{isAlternateBuffer ? (
|
||||
<ScrollableList
|
||||
ref={listRef}
|
||||
hasFocus={focus}
|
||||
data={scrollableData}
|
||||
renderItem={renderItem}
|
||||
estimatedItemHeight={() => 1}
|
||||
fixedItemHeight={true}
|
||||
keyExtractor={(item) =>
|
||||
item.type === 'visualLine'
|
||||
? `line-${item.absoluteVisualIdx}`
|
||||
: `ghost-${item.index}`
|
||||
}
|
||||
width={inputWidth}
|
||||
backgroundColor={listBackgroundColor}
|
||||
containerHeight={Math.min(
|
||||
buffer.viewportHeight,
|
||||
scrollableData.length,
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
scrollableData
|
||||
.slice(
|
||||
buffer.visualScrollRow,
|
||||
buffer.visualScrollRow + buffer.viewportHeight,
|
||||
)
|
||||
.map((item, index) => {
|
||||
const actualIndex = buffer.visualScrollRow + index;
|
||||
const key =
|
||||
item.type === 'visualLine'
|
||||
? `line-${item.absoluteVisualIdx}`
|
||||
: `ghost-${item.index}`;
|
||||
return (
|
||||
<Fragment key={key}>
|
||||
{renderItem({ item, index: actualIndex })}
|
||||
</Fragment>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -112,48 +112,7 @@ exports[`<HistoryItemDisplay /> > gemini items (alternateBuffer=false) > should
|
||||
|
||||
exports[`<HistoryItemDisplay /> > gemini items (alternateBuffer=false) > should render a truncated gemini item 1`] = `
|
||||
"✦ Example code block:
|
||||
1 Line 1
|
||||
2 Line 2
|
||||
3 Line 3
|
||||
4 Line 4
|
||||
5 Line 5
|
||||
6 Line 6
|
||||
7 Line 7
|
||||
8 Line 8
|
||||
9 Line 9
|
||||
10 Line 10
|
||||
11 Line 11
|
||||
12 Line 12
|
||||
13 Line 13
|
||||
14 Line 14
|
||||
15 Line 15
|
||||
16 Line 16
|
||||
17 Line 17
|
||||
18 Line 18
|
||||
19 Line 19
|
||||
20 Line 20
|
||||
21 Line 21
|
||||
22 Line 22
|
||||
23 Line 23
|
||||
24 Line 24
|
||||
25 Line 25
|
||||
26 Line 26
|
||||
27 Line 27
|
||||
28 Line 28
|
||||
29 Line 29
|
||||
30 Line 30
|
||||
31 Line 31
|
||||
32 Line 32
|
||||
33 Line 33
|
||||
34 Line 34
|
||||
35 Line 35
|
||||
36 Line 36
|
||||
37 Line 37
|
||||
38 Line 38
|
||||
39 Line 39
|
||||
40 Line 40
|
||||
41 Line 41
|
||||
42 Line 42
|
||||
... 42 hidden (Ctrl+O) ...
|
||||
43 Line 43
|
||||
44 Line 44
|
||||
45 Line 45
|
||||
@@ -167,48 +126,7 @@ exports[`<HistoryItemDisplay /> > gemini items (alternateBuffer=false) > should
|
||||
|
||||
exports[`<HistoryItemDisplay /> > gemini items (alternateBuffer=false) > should render a truncated gemini_content item 1`] = `
|
||||
" Example code block:
|
||||
1 Line 1
|
||||
2 Line 2
|
||||
3 Line 3
|
||||
4 Line 4
|
||||
5 Line 5
|
||||
6 Line 6
|
||||
7 Line 7
|
||||
8 Line 8
|
||||
9 Line 9
|
||||
10 Line 10
|
||||
11 Line 11
|
||||
12 Line 12
|
||||
13 Line 13
|
||||
14 Line 14
|
||||
15 Line 15
|
||||
16 Line 16
|
||||
17 Line 17
|
||||
18 Line 18
|
||||
19 Line 19
|
||||
20 Line 20
|
||||
21 Line 21
|
||||
22 Line 22
|
||||
23 Line 23
|
||||
24 Line 24
|
||||
25 Line 25
|
||||
26 Line 26
|
||||
27 Line 27
|
||||
28 Line 28
|
||||
29 Line 29
|
||||
30 Line 30
|
||||
31 Line 31
|
||||
32 Line 32
|
||||
33 Line 33
|
||||
34 Line 34
|
||||
35 Line 35
|
||||
36 Line 36
|
||||
37 Line 37
|
||||
38 Line 38
|
||||
39 Line 39
|
||||
40 Line 40
|
||||
41 Line 41
|
||||
42 Line 42
|
||||
... 42 hidden (Ctrl+O) ...
|
||||
43 Line 43
|
||||
44 Line 44
|
||||
45 Line 45
|
||||
|
||||
@@ -93,7 +93,7 @@ exports[`InputPrompt > Highlighting and Cursor Display > single-line scenarios >
|
||||
exports[`InputPrompt > History Navigation and Completion Suppression > should not render suggestions during history navigation 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> second message
|
||||
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -120,30 +120,30 @@ exports[`InputPrompt > command search (Ctrl+R when not in shell) > expands and c
|
||||
exports[`InputPrompt > command search (Ctrl+R when not in shell) > renders match window and expanded view (snapshots) > command-search-render-collapsed-match 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
(r:) commit
|
||||
|
||||
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
git commit -m "feat: add search" in src/app
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > command search (Ctrl+R when not in shell) > renders match window and expanded view (snapshots) > command-search-render-expanded-match 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
(r:) commit
|
||||
|
||||
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
git commit -m "feat: add search" in src/app
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > image path transformation snapshots > should snapshot collapsed image path 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Image ...reenshot2x.png]
|
||||
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > image path transformation snapshots > should snapshot expanded image path when cursor is on it 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> @/path/to/screenshots/screenshot2x.png
|
||||
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
|
||||
@@ -293,8 +293,8 @@ describe('<ShellToolMessage />', () => {
|
||||
await waitUntilReady();
|
||||
const frame = lastFrame();
|
||||
// Since it's Executing, it might still constrain to ACTIVE_SHELL_MAX_LINES (10)
|
||||
// Actually let's just assert on the behaviour that happens right now (which is 10 lines)
|
||||
expect(frame.match(/Line \d+/g)?.length).toBe(10);
|
||||
// Actually let's just assert on the behaviour that happens right now (which is 100 lines because we removed the terminalBuffer check)
|
||||
expect(frame.match(/Line \d+/g)?.length).toBe(100);
|
||||
unmount();
|
||||
});
|
||||
|
||||
|
||||
@@ -444,8 +444,8 @@ describe('<ToolMessage />', () => {
|
||||
constrainHeight: true,
|
||||
},
|
||||
width: 80,
|
||||
config: makeFakeConfig({ useAlternateBuffer: false }),
|
||||
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
|
||||
config: makeFakeConfig({ useAlternateBuffer: true }),
|
||||
settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
|
||||
},
|
||||
);
|
||||
const output = lastFrame();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import { renderWithProviders } from '../../../test-utils/render.js';
|
||||
import { waitFor } from '../../../test-utils/async.js';
|
||||
import { createMockSettings } from '../../../test-utils/settings.js';
|
||||
import { ToolResultDisplay } from './ToolResultDisplay.js';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
@@ -351,9 +352,10 @@ describe('ToolResultDisplay', () => {
|
||||
|
||||
expect(output).not.toContain('Line 1');
|
||||
expect(output).not.toContain('Line 2');
|
||||
expect(output).toContain('Line 3');
|
||||
expect(output).not.toContain('Line 3');
|
||||
expect(output).toContain('Line 4');
|
||||
expect(output).toContain('Line 5');
|
||||
expect(output).toContain('hidden');
|
||||
expect(output).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
@@ -391,4 +393,86 @@ describe('ToolResultDisplay', () => {
|
||||
await expect(renderResult).toMatchSvgSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('stays scrolled to the bottom when lines are incrementally added', async () => {
|
||||
const createAnsiLine = (text: string) => [
|
||||
{
|
||||
text,
|
||||
fg: '',
|
||||
bg: '',
|
||||
bold: false,
|
||||
italic: false,
|
||||
underline: false,
|
||||
dim: false,
|
||||
inverse: false,
|
||||
isUninitialized: false,
|
||||
},
|
||||
];
|
||||
|
||||
let currentLines: AnsiOutput = [];
|
||||
|
||||
// Start with 3 lines, max lines 5. It should fit without scrolling.
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
currentLines.push(createAnsiLine(`Line ${i}`));
|
||||
}
|
||||
|
||||
const renderResult = await renderWithProviders(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={currentLines}
|
||||
terminalWidth={80}
|
||||
maxLines={5}
|
||||
availableTerminalHeight={5}
|
||||
overflowDirection="top"
|
||||
/>,
|
||||
{
|
||||
config: makeFakeConfig({ useAlternateBuffer: false }),
|
||||
settings: createMockSettings({ ui: { useAlternateBuffer: false } }),
|
||||
uiState: { constrainHeight: true, terminalHeight: 10 },
|
||||
},
|
||||
);
|
||||
|
||||
const { waitUntilReady, rerender, lastFrame, unmount } = renderResult;
|
||||
await waitUntilReady();
|
||||
|
||||
// Verify initial render has the first 3 lines
|
||||
expect(lastFrame()).toContain('Line 1');
|
||||
expect(lastFrame()).toContain('Line 3');
|
||||
|
||||
// Incrementally add lines up to 8. Max lines is 5.
|
||||
// So by the end, it should only show lines 4-8.
|
||||
for (let i = 4; i <= 8; i++) {
|
||||
currentLines = [...currentLines, createAnsiLine(`Line ${i}`)];
|
||||
rerender(
|
||||
<ToolResultDisplay
|
||||
resultDisplay={currentLines}
|
||||
terminalWidth={80}
|
||||
maxLines={5}
|
||||
availableTerminalHeight={5}
|
||||
overflowDirection="top"
|
||||
/>,
|
||||
);
|
||||
// Wait for the new line to be rendered
|
||||
await waitFor(() => {
|
||||
expect(lastFrame()).toContain(`Line ${i}`);
|
||||
});
|
||||
}
|
||||
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
// The component should have automatically scrolled to the bottom.
|
||||
// Lines 1, 2, 3, 4 should be scrolled out of view.
|
||||
expect(output).not.toContain('Line 1');
|
||||
expect(output).not.toContain('Line 2');
|
||||
expect(output).not.toContain('Line 3');
|
||||
expect(output).not.toContain('Line 4');
|
||||
// Lines 5, 6, 7, 8 should be visible along with the truncation indicator.
|
||||
expect(output).toContain('hidden');
|
||||
expect(output).toContain('Line 5');
|
||||
expect(output).toContain('Line 8');
|
||||
|
||||
expect(output).toMatchSnapshot();
|
||||
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { DiffRenderer } from './DiffRenderer.js';
|
||||
import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js';
|
||||
import { AnsiOutputText, AnsiLineText } from '../AnsiOutput.js';
|
||||
import { SlicingMaxSizedBox } from '../shared/SlicingMaxSizedBox.js';
|
||||
import { MaxSizedBox } from '../shared/MaxSizedBox.js';
|
||||
import { theme } from '../../semantic-colors.js';
|
||||
import {
|
||||
type AnsiOutput,
|
||||
@@ -51,7 +52,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
||||
hasFocus = false,
|
||||
overflowDirection = 'top',
|
||||
}) => {
|
||||
const { renderMarkdown } = useUIState();
|
||||
const { renderMarkdown, constrainHeight } = useUIState();
|
||||
const isAlternateBuffer = useAlternateBuffer();
|
||||
|
||||
const availableHeight = calculateToolContentMaxLines({
|
||||
@@ -209,30 +210,73 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
|
||||
|
||||
if (Array.isArray(resultDisplay)) {
|
||||
const limit = maxLines ?? availableHeight ?? ACTIVE_SHELL_MAX_LINES;
|
||||
const listHeight = Math.min(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(resultDisplay as AnsiOutput).length,
|
||||
limit,
|
||||
);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
const data = resultDisplay as AnsiOutput;
|
||||
|
||||
const initialScrollIndex =
|
||||
overflowDirection === 'bottom' ? 0 : SCROLL_TO_ITEM_END;
|
||||
// Calculate list height: if not constrained, use full data length.
|
||||
// If constrained (e.g. alternate buffer), limit to available height
|
||||
// to ensure virtualization works and fits within the viewport.
|
||||
const listHeight = !constrainHeight
|
||||
? data.length
|
||||
: Math.min(data.length, limit);
|
||||
|
||||
return (
|
||||
<Box width={childWidth} flexDirection="column" maxHeight={listHeight}>
|
||||
<ScrollableList
|
||||
width={childWidth}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
data={resultDisplay as AnsiOutput}
|
||||
renderItem={renderVirtualizedAnsiLine}
|
||||
estimatedItemHeight={() => 1}
|
||||
keyExtractor={keyExtractor}
|
||||
initialScrollIndex={initialScrollIndex}
|
||||
hasFocus={hasFocus}
|
||||
fixedItemHeight={true}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
if (isAlternateBuffer) {
|
||||
const initialScrollIndex =
|
||||
overflowDirection === 'bottom' ? 0 : SCROLL_TO_ITEM_END;
|
||||
|
||||
return (
|
||||
<Box width={childWidth} flexDirection="column" maxHeight={listHeight}>
|
||||
<ScrollableList
|
||||
width={childWidth}
|
||||
containerHeight={listHeight}
|
||||
data={data}
|
||||
renderItem={renderVirtualizedAnsiLine}
|
||||
estimatedItemHeight={() => 1}
|
||||
fixedItemHeight={true}
|
||||
keyExtractor={keyExtractor}
|
||||
initialScrollIndex={initialScrollIndex}
|
||||
hasFocus={hasFocus}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
} else {
|
||||
let displayData = data;
|
||||
let hiddenLines = 0;
|
||||
|
||||
if (constrainHeight && data.length > listHeight) {
|
||||
hiddenLines = data.length - listHeight;
|
||||
if (overflowDirection === 'top') {
|
||||
displayData = data.slice(hiddenLines);
|
||||
} else {
|
||||
displayData = data.slice(0, listHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box width={childWidth} flexDirection="column">
|
||||
<MaxSizedBox
|
||||
maxHeight={constrainHeight ? listHeight : undefined}
|
||||
maxWidth={childWidth}
|
||||
overflowDirection={overflowDirection}
|
||||
additionalHiddenLinesCount={hiddenLines}
|
||||
>
|
||||
{displayData.map((item, index) => {
|
||||
const actualIndex =
|
||||
(overflowDirection === 'top' ? hiddenLines : 0) + index;
|
||||
return (
|
||||
<Box
|
||||
key={keyExtractor(item, actualIndex)}
|
||||
height={1}
|
||||
overflow="hidden"
|
||||
>
|
||||
<AnsiLineText line={item} />
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</MaxSizedBox>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ASB Mode Handling (Interactive/Fullscreen)
|
||||
|
||||
@@ -29,11 +29,12 @@ describe('ToolResultDisplay Overflow', () => {
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
expect(output).not.toContain('Line 1');
|
||||
expect(output).not.toContain('Line 2');
|
||||
expect(output).toContain('Line 3');
|
||||
expect(output).toContain('Line 4');
|
||||
expect(output).toContain('Line 5');
|
||||
expect(output).toContain('Line 1');
|
||||
expect(output).toContain('Line 2');
|
||||
expect(output).not.toContain('Line 3');
|
||||
expect(output).not.toContain('Line 4');
|
||||
expect(output).not.toContain('Line 5');
|
||||
expect(output).toContain('hidden');
|
||||
unmount();
|
||||
});
|
||||
|
||||
@@ -57,9 +58,10 @@ describe('ToolResultDisplay Overflow', () => {
|
||||
|
||||
expect(output).not.toContain('Line 1');
|
||||
expect(output).not.toContain('Line 2');
|
||||
expect(output).toContain('Line 3');
|
||||
expect(output).not.toContain('Line 3');
|
||||
expect(output).toContain('Line 4');
|
||||
expect(output).toContain('Line 5');
|
||||
expect(output).toContain('hidden');
|
||||
unmount();
|
||||
});
|
||||
|
||||
@@ -95,11 +97,10 @@ describe('ToolResultDisplay Overflow', () => {
|
||||
|
||||
expect(output).toContain('Line 1');
|
||||
expect(output).toContain('Line 2');
|
||||
expect(output).toContain('Line 3');
|
||||
expect(output).not.toContain('Line 3');
|
||||
expect(output).not.toContain('Line 4');
|
||||
expect(output).not.toContain('Line 5');
|
||||
// ScrollableList uses a scroll thumb rather than writing "hidden"
|
||||
expect(output).toContain('█');
|
||||
expect(output).toContain('hidden');
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
+19
-4
@@ -1,18 +1,33 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="37" viewBox="0 0 920 37">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="920" height="88" viewBox="0 0 920 88">
|
||||
<style>
|
||||
text { font-family: Consolas, "Courier New", monospace; font-size: 14px; dominant-baseline: text-before-edge; white-space: pre; }
|
||||
</style>
|
||||
<rect width="920" height="37" fill="#000000" />
|
||||
<rect width="920" height="88" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="18" y="2" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">✓</text>
|
||||
<text x="45" y="2" fill="#ffffff" textLength="45" lengthAdjust="spacingAndGlyphs" font-weight="bold">edit </text>
|
||||
<text x="99" y="2" fill="#afafaf" textLength="63" lengthAdjust="spacingAndGlyphs">test.ts</text>
|
||||
<text x="171" y="2" fill="#d7afff" textLength="18" lengthAdjust="spacingAndGlyphs">→ </text>
|
||||
<text x="189" y="2" fill="#d7afff" textLength="72" lengthAdjust="spacingAndGlyphs" text-decoration="underline">Accepted</text>
|
||||
<text x="171" y="2" fill="#d7afff" textLength="90" lengthAdjust="spacingAndGlyphs">→ Accepted</text>
|
||||
<text x="270" y="2" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">(</text>
|
||||
<text x="279" y="2" fill="#d7ffd7" textLength="18" lengthAdjust="spacingAndGlyphs">+1</text>
|
||||
<text x="297" y="2" fill="#afafaf" textLength="18" lengthAdjust="spacingAndGlyphs">, </text>
|
||||
<text x="315" y="2" fill="#ff87af" textLength="18" lengthAdjust="spacingAndGlyphs">-1</text>
|
||||
<text x="333" y="2" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">)</text>
|
||||
<rect x="54" y="34" width="9" height="17" fill="#5f0000" />
|
||||
<text x="54" y="36" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">1</text>
|
||||
<rect x="63" y="34" width="9" height="17" fill="#5f0000" />
|
||||
<rect x="72" y="34" width="9" height="17" fill="#5f0000" />
|
||||
<text x="72" y="36" fill="#ff87af" textLength="9" lengthAdjust="spacingAndGlyphs">-</text>
|
||||
<rect x="81" y="34" width="9" height="17" fill="#5f0000" />
|
||||
<rect x="90" y="34" width="27" height="17" fill="#5f0000" />
|
||||
<text x="90" y="36" fill="#e5e5e5" textLength="27" lengthAdjust="spacingAndGlyphs">old</text>
|
||||
<rect x="54" y="51" width="9" height="17" fill="#005f00" />
|
||||
<text x="54" y="53" fill="#afafaf" textLength="9" lengthAdjust="spacingAndGlyphs">1</text>
|
||||
<rect x="63" y="51" width="9" height="17" fill="#005f00" />
|
||||
<rect x="72" y="51" width="9" height="17" fill="#005f00" />
|
||||
<text x="72" y="53" fill="#d7ffd7" textLength="9" lengthAdjust="spacingAndGlyphs">+</text>
|
||||
<rect x="81" y="51" width="9" height="17" fill="#005f00" />
|
||||
<rect x="90" y="51" width="27" height="17" fill="#005f00" />
|
||||
<text x="90" y="53" fill="#0000ee" textLength="27" lengthAdjust="spacingAndGlyphs">new</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.4 KiB |
+31
-1
@@ -7,12 +7,21 @@ exports[`DenseToolMessage > Toggleable Diff View (Alternate Buffer) > hides diff
|
||||
|
||||
exports[`DenseToolMessage > Toggleable Diff View (Alternate Buffer) > shows diff content by default when NOT in alternate buffer mode 1`] = `
|
||||
" ✓ test-tool test.ts → Accepted
|
||||
|
||||
1 - old line
|
||||
1 + new line
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`DenseToolMessage > Visual Regression > matches SVG snapshot for a Rejected tool call 1`] = `" - read_file Reading important.txt"`;
|
||||
|
||||
exports[`DenseToolMessage > Visual Regression > matches SVG snapshot for an Accepted file edit with diff stats 1`] = `" ✓ edit test.ts → Accepted (+1, -1)"`;
|
||||
exports[`DenseToolMessage > Visual Regression > matches SVG snapshot for an Accepted file edit with diff stats 1`] = `
|
||||
" ✓ edit test.ts → Accepted (+1, -1)
|
||||
|
||||
1 - old
|
||||
1 + new
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`DenseToolMessage > does not render result arrow if resultDisplay is missing 1`] = `
|
||||
" o test-tool Test description
|
||||
@@ -26,11 +35,17 @@ exports[`DenseToolMessage > flattens newlines in string results 1`] = `
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for Edit tool using confirmationDetails 1`] = `
|
||||
" ? Edit styles.scss → Confirming
|
||||
|
||||
1 - body { color: blue; }
|
||||
1 + body { color: red; }
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for Errored Edit tool 1`] = `
|
||||
" x Edit styles.scss → Failed (+1, -1)
|
||||
|
||||
1 - old line
|
||||
1 + new line
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -45,21 +60,33 @@ exports[`DenseToolMessage > renders correctly for ReadManyFiles results 1`] = `
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for Rejected Edit tool 1`] = `
|
||||
" - Edit styles.scss → Rejected (+1, -1)
|
||||
|
||||
1 - old line
|
||||
1 + new line
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for Rejected Edit tool with confirmationDetails and diffStat 1`] = `
|
||||
" - Edit styles.scss → Rejected (+1, -1)
|
||||
|
||||
1 - body { color: blue; }
|
||||
1 + body { color: red; }
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for Rejected WriteFile tool 1`] = `
|
||||
" - WriteFile config.json → Rejected
|
||||
|
||||
1 - old content
|
||||
1 + new content
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for WriteFile tool 1`] = `
|
||||
" ✓ WriteFile config.json → Accepted (+1, -1)
|
||||
|
||||
1 - old content
|
||||
1 + new content
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -75,6 +102,9 @@ exports[`DenseToolMessage > renders correctly for error status with string messa
|
||||
|
||||
exports[`DenseToolMessage > renders correctly for file diff results with stats 1`] = `
|
||||
" ✓ test-tool test.ts → Accepted (+15, -6)
|
||||
|
||||
1 - old line
|
||||
1 + diff content
|
||||
"
|
||||
`;
|
||||
|
||||
|
||||
+14
-27
@@ -4,7 +4,7 @@
|
||||
</style>
|
||||
<rect width="920" height="445" fill="#000000" />
|
||||
<g transform="translate(10, 10)">
|
||||
<text x="0" y="2" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 26 </text>
|
||||
<text x="0" y="2" fill="#afafaf" textLength="234" lengthAdjust="spacingAndGlyphs">... 26 hidden (Ctrl+O) ...</text>
|
||||
<text x="0" y="19" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 27 </text>
|
||||
<text x="0" y="36" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 28 </text>
|
||||
<text x="0" y="53" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 29 </text>
|
||||
@@ -16,31 +16,18 @@
|
||||
<text x="0" y="155" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 35 </text>
|
||||
<text x="0" y="172" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 36 </text>
|
||||
<text x="0" y="189" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 37 </text>
|
||||
<text x="0" y="206" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 38 </text>
|
||||
<text x="675" y="206" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">▄</text>
|
||||
<text x="0" y="223" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 39 </text>
|
||||
<text x="675" y="223" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="240" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 40 </text>
|
||||
<text x="675" y="240" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="257" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 41 </text>
|
||||
<text x="675" y="257" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="274" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 42 </text>
|
||||
<text x="675" y="274" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="291" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 43 </text>
|
||||
<text x="675" y="291" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="308" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 44 </text>
|
||||
<text x="675" y="308" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="325" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 45 </text>
|
||||
<text x="675" y="325" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="342" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 46 </text>
|
||||
<text x="675" y="342" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="359" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 47 </text>
|
||||
<text x="675" y="359" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="376" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 48 </text>
|
||||
<text x="675" y="376" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="393" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 49 </text>
|
||||
<text x="675" y="393" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="410" fill="#ffffff" textLength="675" lengthAdjust="spacingAndGlyphs">Line 50 </text>
|
||||
<text x="675" y="410" fill="#333333" textLength="9" lengthAdjust="spacingAndGlyphs">█</text>
|
||||
<text x="0" y="206" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 38 </text>
|
||||
<text x="0" y="223" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 39 </text>
|
||||
<text x="0" y="240" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 40 </text>
|
||||
<text x="0" y="257" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 41 </text>
|
||||
<text x="0" y="274" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 42 </text>
|
||||
<text x="0" y="291" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 43 </text>
|
||||
<text x="0" y="308" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 44 </text>
|
||||
<text x="0" y="325" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 45 </text>
|
||||
<text x="0" y="342" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 46 </text>
|
||||
<text x="0" y="359" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 47 </text>
|
||||
<text x="0" y="376" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 48 </text>
|
||||
<text x="0" y="393" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 49 </text>
|
||||
<text x="0" y="410" fill="#ffffff" textLength="900" lengthAdjust="spacingAndGlyphs">Line 50 </text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 5.0 KiB |
+41
-30
@@ -33,15 +33,24 @@ exports[`ToolResultDisplay > renders string result as plain text when renderOutp
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ToolResultDisplay > stays scrolled to the bottom when lines are incrementally added 1`] = `
|
||||
"... 4 hidden (Ctrl+O) ...
|
||||
Line 5
|
||||
Line 6
|
||||
Line 7
|
||||
Line 8
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ToolResultDisplay > truncates ANSI output when maxLines is provided 1`] = `
|
||||
"Line 3
|
||||
Line 4 █
|
||||
Line 5 █
|
||||
"... 3 hidden (Ctrl+O) ...
|
||||
Line 4
|
||||
Line 5
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ToolResultDisplay > truncates ANSI output when maxLines is provided, even if availableTerminalHeight is undefined 1`] = `
|
||||
"Line 26
|
||||
"... 26 hidden (Ctrl+O) ...
|
||||
Line 27
|
||||
Line 28
|
||||
Line 29
|
||||
@@ -53,34 +62,36 @@ Line 34
|
||||
Line 35
|
||||
Line 36
|
||||
Line 37
|
||||
Line 38 ▄
|
||||
Line 39 █
|
||||
Line 40 █
|
||||
Line 41 █
|
||||
Line 42 █
|
||||
Line 43 █
|
||||
Line 44 █
|
||||
Line 45 █
|
||||
Line 46 █
|
||||
Line 47 █
|
||||
Line 48 █
|
||||
Line 49 █
|
||||
Line 50 █"
|
||||
Line 38
|
||||
Line 39
|
||||
Line 40
|
||||
Line 41
|
||||
Line 42
|
||||
Line 43
|
||||
Line 44
|
||||
Line 45
|
||||
Line 46
|
||||
Line 47
|
||||
Line 48
|
||||
Line 49
|
||||
Line 50"
|
||||
`;
|
||||
|
||||
exports[`ToolResultDisplay > truncates very long string results 1`] = `
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa… █
|
||||
"... 250 hidden (Ctrl+O) ...
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
aaaaaaaaaaaaaaa
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -115,7 +115,7 @@ export const MaxSizedBox: React.FC<MaxSizedBoxProps> = ({
|
||||
[id, removeOverflowingId],
|
||||
);
|
||||
|
||||
if (effectiveMaxHeight === undefined) {
|
||||
if (effectiveMaxHeight === undefined && totalHiddenLines === 0) {
|
||||
return (
|
||||
<Box flexDirection="column" width={maxWidth}>
|
||||
{children}
|
||||
|
||||
@@ -1224,7 +1224,7 @@ export class Config implements McpContext, AgentLoopContext {
|
||||
this.useRipgrep = params.useRipgrep ?? true;
|
||||
this.useBackgroundColor = params.useBackgroundColor ?? true;
|
||||
this.useAlternateBuffer = params.useAlternateBuffer ?? false;
|
||||
this.useTerminalBuffer = params.useTerminalBuffer ?? true;
|
||||
this.useTerminalBuffer = params.useTerminalBuffer ?? false;
|
||||
this.useRenderProcess = params.useRenderProcess ?? true;
|
||||
this.enableInteractiveShell = params.enableInteractiveShell ?? false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user