mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-14 15:21:01 -07:00
feat: Fix flickering in iTerm + scrolling + performance issues.
- Refactors history display using Ink's <Static> component to prevent flickering and improve performance by rendering completed items statically. - Introduces ConsolePatcher component to capture and display console.log, console.warn, and console.error output within the Ink UI, addressing native handling issues. - Introduce a new content splitting mechanism to work better for static items. Basically when content gets too long we will now split content into multiple blocks for Gemini messages to ensure that we can statically cache larger pieces of history. Fixes: - https://b.corp.google.com/issues/411450097 - https://b.corp.google.com/issues/412716309
This commit is contained in:
committed by
N. Taylor Mullen
parent
aa65a4a1fc
commit
5be89befef
85
packages/cli/src/ui/components/ConsolePatcher.tsx
Normal file
85
packages/cli/src/ui/components/ConsolePatcher.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, Key } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import util from 'util';
|
||||
|
||||
interface ConsoleMessage {
|
||||
id: Key;
|
||||
type: 'log' | 'warn' | 'error';
|
||||
content: string;
|
||||
}
|
||||
|
||||
// Using a module-level counter for unique IDs.
|
||||
// This ensures IDs are unique across messages.
|
||||
let messageIdCounter = 0;
|
||||
|
||||
export const ConsoleOutput: React.FC = () => {
|
||||
const [messages, setMessages] = useState<ConsoleMessage[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const originalConsoleLog = console.log;
|
||||
const originalConsoleWarn = console.warn;
|
||||
const originalConsoleError = console.error;
|
||||
|
||||
const formatArgs = (args: unknown[]): string => util.format(...args);
|
||||
const addMessage = (type: 'log' | 'warn' | 'error', args: unknown[]) => {
|
||||
setMessages((prevMessages) => [
|
||||
...prevMessages,
|
||||
{
|
||||
id: `console-msg-${messageIdCounter++}`,
|
||||
type,
|
||||
content: formatArgs(args),
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
// It's patching time
|
||||
console.log = (...args: unknown[]) => addMessage('log', args);
|
||||
console.warn = (...args: unknown[]) => addMessage('warn', args);
|
||||
console.error = (...args: unknown[]) => addMessage('error', args);
|
||||
|
||||
return () => {
|
||||
console.log = originalConsoleLog;
|
||||
console.warn = originalConsoleWarn;
|
||||
console.error = originalConsoleError;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
{messages.map((msg) => {
|
||||
const textProps: { color?: string } = {};
|
||||
let prefix = '';
|
||||
|
||||
switch (msg.type) {
|
||||
case 'warn':
|
||||
textProps.color = 'yellow';
|
||||
prefix = 'WARN: ';
|
||||
break;
|
||||
case 'error':
|
||||
textProps.color = 'red';
|
||||
prefix = 'ERROR: ';
|
||||
break;
|
||||
case 'log':
|
||||
default:
|
||||
prefix = 'LOG: ';
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box key={msg.id}>
|
||||
<Text {...textProps}>
|
||||
{prefix}
|
||||
{msg.content}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user