mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-12 21:03:05 -07:00
fix(cli): prevent terminal escape sequences from leaking on exit (#22682)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -13,12 +13,14 @@ import {
|
|||||||
disableModifyOtherKeys,
|
disableModifyOtherKeys,
|
||||||
enableBracketedPasteMode,
|
enableBracketedPasteMode,
|
||||||
disableBracketedPasteMode,
|
disableBracketedPasteMode,
|
||||||
|
disableMouseEvents,
|
||||||
} from '@google/gemini-cli-core';
|
} from '@google/gemini-cli-core';
|
||||||
import { parseColor } from '../themes/color-utils.js';
|
import { parseColor } from '../themes/color-utils.js';
|
||||||
|
|
||||||
export type TerminalBackgroundColor = string | undefined;
|
export type TerminalBackgroundColor = string | undefined;
|
||||||
|
|
||||||
const TERMINAL_CLEANUP_SEQUENCE = '\x1b[<u\x1b[>4;0m\x1b[?2004l';
|
const TERMINAL_CLEANUP_SEQUENCE =
|
||||||
|
'\x1b[<u\x1b[>4;0m\x1b[?2004l\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l';
|
||||||
|
|
||||||
export function cleanupTerminalOnExit() {
|
export function cleanupTerminalOnExit() {
|
||||||
try {
|
try {
|
||||||
@@ -33,6 +35,7 @@ export function cleanupTerminalOnExit() {
|
|||||||
disableKittyKeyboardProtocol();
|
disableKittyKeyboardProtocol();
|
||||||
disableModifyOtherKeys();
|
disableModifyOtherKeys();
|
||||||
disableBracketedPasteMode();
|
disableBracketedPasteMode();
|
||||||
|
disableMouseEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TerminalCapabilityManager {
|
export class TerminalCapabilityManager {
|
||||||
|
|||||||
@@ -72,6 +72,46 @@ describe('cleanup', () => {
|
|||||||
expect(asyncFn).toHaveBeenCalledTimes(1);
|
expect(asyncFn).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should run cleanupFunctions BEFORE draining stdin and BEFORE runSyncCleanup', async () => {
|
||||||
|
const callOrder: string[] = [];
|
||||||
|
|
||||||
|
// Cleanup function
|
||||||
|
registerCleanup(() => {
|
||||||
|
callOrder.push('cleanup');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sync cleanup function (e.g. setRawMode(false))
|
||||||
|
registerSyncCleanup(() => {
|
||||||
|
callOrder.push('sync');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mock stdin.resume to track drainStdin
|
||||||
|
const originalResume = process.stdin.resume;
|
||||||
|
process.stdin.resume = vi.fn().mockImplementation(() => {
|
||||||
|
callOrder.push('drain');
|
||||||
|
return process.stdin;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mock stdin properties for drainStdin
|
||||||
|
const originalIsTTY = process.stdin.isTTY;
|
||||||
|
Object.defineProperty(process.stdin, 'isTTY', {
|
||||||
|
value: true,
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await runExitCleanup();
|
||||||
|
} finally {
|
||||||
|
process.stdin.resume = originalResume;
|
||||||
|
Object.defineProperty(process.stdin, 'isTTY', {
|
||||||
|
value: originalIsTTY,
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(callOrder).toEqual(['drain', 'drain', 'sync', 'cleanup']);
|
||||||
|
});
|
||||||
|
|
||||||
it('should continue running cleanup functions even if one throws an error', async () => {
|
it('should continue running cleanup functions even if one throws an error', async () => {
|
||||||
const errorFn = vi.fn().mockImplementation(() => {
|
const errorFn = vi.fn().mockImplementation(() => {
|
||||||
throw new Error('test error');
|
throw new Error('test error');
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ export function registerTelemetryConfig(config: Config) {
|
|||||||
|
|
||||||
export async function runExitCleanup() {
|
export async function runExitCleanup() {
|
||||||
// drain stdin to prevent printing garbage on exit
|
// drain stdin to prevent printing garbage on exit
|
||||||
// https://github.com/google-gemini/gemini-cli/issues/1680
|
// https://github.com/google-gemini/gemini-cli/issues/16801
|
||||||
await drainStdin();
|
await drainStdin();
|
||||||
|
|
||||||
runSyncCleanup();
|
runSyncCleanup();
|
||||||
|
|||||||
Reference in New Issue
Block a user