diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index af8c1ae0ac..68294c6bf7 100755 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -988,6 +988,8 @@ export async function loadCliConfig( trustedFolder, useBackgroundColor: settings.ui?.useBackgroundColor, useAlternateBuffer: settings.ui?.useAlternateBuffer, + useTerminalBuffer: settings.ui?.terminalBuffer, + useRenderProcess: settings.ui?.renderProcess, useRipgrep: settings.tools?.useRipgrep, enableInteractiveShell: settings.tools?.shell?.enableInteractiveShell, shellToolInactivityTimeout: settings.tools?.shell?.inactivityTimeout, diff --git a/packages/cli/src/config/settingsSchema.ts b/packages/cli/src/config/settingsSchema.ts index aec521317c..2526d7842d 100644 --- a/packages/cli/src/config/settingsSchema.ts +++ b/packages/cli/src/config/settingsSchema.ts @@ -723,6 +723,24 @@ const SETTINGS_SCHEMA = { 'Use an alternate screen buffer for the UI, preserving shell history.', showInDialog: true, }, + renderProcess: { + type: 'boolean', + label: 'Render Process', + category: 'UI', + requiresRestart: true, + default: true, + description: 'Enable Ink render process for the UI.', + showInDialog: true, + }, + terminalBuffer: { + type: 'boolean', + label: 'Terminal Buffer', + category: 'UI', + requiresRestart: true, + default: true, + description: 'Use the new terminal buffer architecture for rendering.', + showInDialog: true, + }, useBackgroundColor: { type: 'boolean', label: 'Use Background Color', diff --git a/packages/cli/src/test-utils/mockConfig.ts b/packages/cli/src/test-utils/mockConfig.ts index e1505df970..39b5fff06e 100644 --- a/packages/cli/src/test-utils/mockConfig.ts +++ b/packages/cli/src/test-utils/mockConfig.ts @@ -174,6 +174,8 @@ export const createMockConfig = (overrides: Partial = {}): Config => getHasAccessToPreviewModel: vi.fn().mockReturnValue(false), validatePathAccess: vi.fn().mockReturnValue(null), getUseAlternateBuffer: vi.fn().mockReturnValue(false), + getUseTerminalBuffer: vi.fn().mockReturnValue(false), + getUseRenderProcess: vi.fn().mockReturnValue(false), ...overrides, }) as unknown as Config; diff --git a/packages/cli/src/ui/components/Help.test.tsx b/packages/cli/src/ui/components/Help.test.tsx index ed685f76c9..058fb0db55 100644 --- a/packages/cli/src/ui/components/Help.test.tsx +++ b/packages/cli/src/ui/components/Help.test.tsx @@ -72,7 +72,7 @@ describe('Help Component', () => { expect(output).toContain('Keyboard Shortcuts:'); expect(output).toContain('Ctrl+C'); - expect(output).toContain('Ctrl+S'); + expect(output).toContain('Shift+Tab'); expect(output).toContain('Page Up/Page Down'); unmount(); }); diff --git a/packages/cli/src/ui/key/keyBindings.ts b/packages/cli/src/ui/key/keyBindings.ts index c84f189664..8bab4bbc9d 100644 --- a/packages/cli/src/ui/key/keyBindings.ts +++ b/packages/cli/src/ui/key/keyBindings.ts @@ -84,6 +84,7 @@ export enum Command { SHOW_IDE_CONTEXT_DETAIL = 'app.showIdeContextDetail', TOGGLE_MARKDOWN = 'app.toggleMarkdown', TOGGLE_COPY_MODE = 'app.toggleCopyMode', + TOGGLE_MOUSE_MODE = 'app.toggleMouseMode', TOGGLE_YOLO = 'app.toggleYolo', CYCLE_APPROVAL_MODE = 'app.cycleApprovalMode', SHOW_MORE_LINES = 'app.showMoreLines', @@ -104,6 +105,9 @@ export enum Command { UNFOCUS_BACKGROUND_SHELL = 'background.unfocus', UNFOCUS_BACKGROUND_SHELL_LIST = 'background.unfocusList', SHOW_BACKGROUND_SHELL_UNFOCUS_WARNING = 'background.unfocusWarning', + DUMP_FRAME = 'app.dumpFrame', + START_RECORDING = 'app.startRecording', + STOP_RECORDING = 'app.stopRecording', } /** @@ -379,7 +383,8 @@ export const defaultKeyBindingConfig: KeyBindingConfig = new Map([ [Command.SHOW_FULL_TODOS, [new KeyBinding('ctrl+t')]], [Command.SHOW_IDE_CONTEXT_DETAIL, [new KeyBinding('ctrl+g')]], [Command.TOGGLE_MARKDOWN, [new KeyBinding('alt+m')]], - [Command.TOGGLE_COPY_MODE, [new KeyBinding('ctrl+s')]], + [Command.TOGGLE_COPY_MODE, [new KeyBinding('f9')]], + [Command.TOGGLE_MOUSE_MODE, [new KeyBinding('ctrl+s')]], [Command.TOGGLE_YOLO, [new KeyBinding('ctrl+y')]], [Command.CYCLE_APPROVAL_MODE, [new KeyBinding('shift+tab')]], [Command.SHOW_MORE_LINES, [new KeyBinding('ctrl+o')]], @@ -390,6 +395,9 @@ export const defaultKeyBindingConfig: KeyBindingConfig = new Map([ [Command.RESTART_APP, [new KeyBinding('r'), new KeyBinding('shift+r')]], [Command.SUSPEND_APP, [new KeyBinding('ctrl+z')]], [Command.SHOW_SHELL_INPUT_UNFOCUS_WARNING, [new KeyBinding('tab')]], + [Command.DUMP_FRAME, [new KeyBinding('f8')]], + [Command.START_RECORDING, [new KeyBinding('f6')]], + [Command.STOP_RECORDING, [new KeyBinding('f7')]], // Background Shell Controls [Command.BACKGROUND_SHELL_ESCAPE, [new KeyBinding('escape')]], @@ -501,6 +509,7 @@ export const commandCategories: readonly CommandCategory[] = [ Command.SHOW_IDE_CONTEXT_DETAIL, Command.TOGGLE_MARKDOWN, Command.TOGGLE_COPY_MODE, + Command.TOGGLE_MOUSE_MODE, Command.TOGGLE_YOLO, Command.CYCLE_APPROVAL_MODE, Command.SHOW_MORE_LINES, @@ -524,6 +533,9 @@ export const commandCategories: readonly CommandCategory[] = [ Command.UNFOCUS_BACKGROUND_SHELL, Command.UNFOCUS_BACKGROUND_SHELL_LIST, Command.SHOW_BACKGROUND_SHELL_UNFOCUS_WARNING, + Command.DUMP_FRAME, + Command.START_RECORDING, + Command.STOP_RECORDING, ], }, ]; @@ -604,6 +616,7 @@ export const commandDescriptions: Readonly> = { [Command.SHOW_IDE_CONTEXT_DETAIL]: 'Show IDE context details.', [Command.TOGGLE_MARKDOWN]: 'Toggle Markdown rendering.', [Command.TOGGLE_COPY_MODE]: 'Toggle copy mode when in alternate buffer mode.', + [Command.TOGGLE_MOUSE_MODE]: 'Toggle mouse mode (scrolling and clicking).', [Command.TOGGLE_YOLO]: 'Toggle YOLO (auto-approval) mode for tool calls.', [Command.CYCLE_APPROVAL_MODE]: 'Cycle through approval modes: default (prompt), auto_edit (auto-approve edits), and plan (read-only). Plan mode is skipped when the agent is busy.', @@ -633,6 +646,9 @@ export const commandDescriptions: Readonly> = { 'Move focus from background shell list to Gemini.', [Command.SHOW_BACKGROUND_SHELL_UNFOCUS_WARNING]: 'Show warning when trying to move focus away from background shell.', + [Command.DUMP_FRAME]: 'Dump the current frame as a snapshot.', + [Command.START_RECORDING]: 'Start recording the session.', + [Command.STOP_RECORDING]: 'Stop recording the session.', }; const keybindingsSchema = z.array( diff --git a/packages/cli/src/ui/key/keyMatchers.test.ts b/packages/cli/src/ui/key/keyMatchers.test.ts index ab12ca1ddf..2a3709350f 100644 --- a/packages/cli/src/ui/key/keyMatchers.test.ts +++ b/packages/cli/src/ui/key/keyMatchers.test.ts @@ -346,6 +346,11 @@ describe('keyMatchers', () => { }, { command: Command.TOGGLE_COPY_MODE, + positive: [createKey('f9')], + negative: [createKey('f8'), createKey('f10')], + }, + { + command: Command.TOGGLE_MOUSE_MODE, positive: [createKey('s', { ctrl: true })], negative: [createKey('s'), createKey('s', { alt: true })], }, diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index d8898e1e3b..da44d6fdd6 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -638,6 +638,8 @@ export interface ConfigParameters { trustedFolder?: boolean; useBackgroundColor?: boolean; useAlternateBuffer?: boolean; + useTerminalBuffer?: boolean; + useRenderProcess?: boolean; useRipgrep?: boolean; enableInteractiveShell?: boolean; skipNextSpeakerCheck?: boolean; @@ -841,6 +843,8 @@ export class Config implements McpContext, AgentLoopContext { private readonly skipNextSpeakerCheck: boolean; private readonly useBackgroundColor: boolean; private readonly useAlternateBuffer: boolean; + private readonly useTerminalBuffer: boolean; + private readonly useRenderProcess: boolean; private shellExecutionConfig: ShellExecutionConfig; private readonly extensionManagement: boolean = true; private readonly extensionRegistryURI: string | undefined; @@ -1157,6 +1161,8 @@ 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 ?? false; + this.useRenderProcess = params.useRenderProcess ?? true; this.enableInteractiveShell = params.enableInteractiveShell ?? false; this.skipNextSpeakerCheck = params.skipNextSpeakerCheck ?? true; this.shellExecutionConfig = { @@ -3115,6 +3121,14 @@ export class Config implements McpContext, AgentLoopContext { return this.useAlternateBuffer; } + getUseTerminalBuffer(): boolean { + return this.useTerminalBuffer; + } + + getUseRenderProcess(): boolean { + return this.useRenderProcess; + } + getEnableInteractiveShell(): boolean { return this.enableInteractiveShell; }