From ff4e478fcc839a6d4e2f67e5ce8c554b17066900 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Mon, 4 May 2026 14:51:53 -0500 Subject: [PATCH] fix(tui): require explicit alt bit for escape-based alt chords Hermes-ink reports bare Escape as meta=true+escape=true on some terminals, so a configured alt+escape binding was firing on bare Esc. Require an explicit key.alt bit when the configured named key is escape so plain Esc stays plain Esc; kitty-style alt+escape still fires. --- ui-tui/src/__tests__/platform.test.ts | 10 ++++++++++ ui-tui/src/lib/platform.ts | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ui-tui/src/__tests__/platform.test.ts b/ui-tui/src/__tests__/platform.test.ts index aa73de75a89..6f77c619751 100644 --- a/ui-tui/src/__tests__/platform.test.ts +++ b/ui-tui/src/__tests__/platform.test.ts @@ -270,6 +270,16 @@ describe('parseVoiceRecordKey (#18994)', () => { expect(isVoiceToggleKey({ ctrl: false, meta: false, super: true }, 'b', superB)).toBe(true) }) + it('alt+escape does not fire on bare Esc meta-shape', async () => { + const { isVoiceToggleKey, parseVoiceRecordKey } = await importPlatform('darwin') + const altEscape = parseVoiceRecordKey('alt+escape') + + // Some terminals surface bare Esc as meta=true + escape=true. + expect(isVoiceToggleKey({ ctrl: false, escape: true, meta: true, super: false }, '', altEscape)).toBe(false) + // Explicit alt bit (kitty-style) still fires the configured chord. + expect(isVoiceToggleKey({ alt: true, ctrl: false, escape: true, meta: false, super: false }, '', altEscape)).toBe(true) + }) + it('rejects matches when Shift is held (different chord than configured)', async () => { const { isVoiceToggleKey, parseVoiceRecordKey } = await importPlatform('linux') diff --git a/ui-tui/src/lib/platform.ts b/ui-tui/src/lib/platform.ts index 1bdbfd3ac2d..0eb372d345f 100644 --- a/ui-tui/src/lib/platform.ts +++ b/ui-tui/src/lib/platform.ts @@ -322,7 +322,12 @@ export const isVoiceToggleKey = ( // protocols. Guard against ctrl/super bits so a chord like // Ctrl+Alt+ or Cmd+Alt+ doesn't spuriously fire the // alt binding. - return (key.alt === true || key.meta) && !key.ctrl && key.super !== true + // + // Bare Escape on hermes-ink can arrive as ``key.meta=true`` on some + // terminals, so a configured ``alt+escape`` must not match that shape; + // require an explicit alt bit for escape chords (Copilot round-7 + // follow-up on #19835). + return (key.alt === true || (key.meta && key.escape !== true)) && !key.ctrl && key.super !== true case 'ctrl': // Require the Ctrl bit AND a clear Alt/Super so a chord like // Ctrl+Alt+ / Ctrl+Cmd+ doesn't spuriously match