mirror of
https://github.com/stablyai/orca.git
synced 2026-10-17 08:03:14 +00:00
fix(terminal): reset kitty mirror on fresh spawn to cover replaced-PTY late exits
The exit handler resets the per-pane kitty keyboard mirror, but a late exit from a replaced PTY takes the stale-transport early return and skips it — so a restart-in-place could leak the old TUI's kitty flags into the fresh shell, kitty-encoding Option chords the shell cannot parse. A fresh spawn is by definition a new process with kitty state at zero, so startFreshSpawn now resets the reused tracker itself, alongside the other per-pane mode state it already clears. Reattach paths are untouched, so a live TUI's mirrored flags still survive reconnects.
This commit is contained in:
@@ -920,6 +920,32 @@ describe('connectPanePty', () => {
|
||||
)
|
||||
})
|
||||
|
||||
// Why: a late exit from a replaced PTY takes the stale-transport early
|
||||
// return in onExit and skips the kitty mirror reset there — a fresh spawn
|
||||
// must therefore reset the reused per-pane tracker itself, or a
|
||||
// restart-in-place leaks the old TUI's kitty flags into a fresh shell.
|
||||
it('resets a stale kitty keyboard mirror when spawning a fresh PTY', async () => {
|
||||
const { connectPanePty } = await import('./pty-connection')
|
||||
const { TerminalKittyKeyboardModeTracker } =
|
||||
await import('../../../../shared/terminal-kitty-keyboard-mode-tracker')
|
||||
const transport = createMockTransport()
|
||||
transportFactoryQueue.push(transport)
|
||||
const staleTracker = new TerminalKittyKeyboardModeTracker()
|
||||
staleTracker.scan('\x1b[>1u')
|
||||
expect(staleTracker.flags).toBe(1)
|
||||
// Why: a unique tab id keeps this pane's key clear of pendingSpawnByPaneKey
|
||||
// entries from other tests, so the connect deterministically fresh-spawns.
|
||||
const deps = createDeps({
|
||||
tabId: 'tab-kitty-fresh-spawn',
|
||||
paneKittyKeyboardModesRef: { current: new Map([[91, staleTracker]]) }
|
||||
})
|
||||
|
||||
connectPanePty(createPane(91) as never, createManager(91) as never, deps as never)
|
||||
await flushAsyncTicks()
|
||||
|
||||
expect(staleTracker.flags).toBe(0)
|
||||
})
|
||||
|
||||
it('threads the resolved local project runtime into IPC terminal transport options', async () => {
|
||||
const { connectPanePty } = await import('./pty-connection')
|
||||
const transport = createMockTransport()
|
||||
|
||||
@@ -3771,6 +3771,11 @@ export function connectPanePty(
|
||||
): void => {
|
||||
clearPaneMode2031State()
|
||||
clearHiddenOutputRestoreState()
|
||||
// Why: a fresh spawn is a new process with kitty keyboard flags at
|
||||
// zero. The exit-handler reset alone is not enough: a late exit from a
|
||||
// replaced PTY takes the stale-transport early return and skips it, so
|
||||
// a restart-in-place would leak the old TUI's flags into a fresh shell.
|
||||
kittyKeyboardModes.reset()
|
||||
prepareFreshShellViewportForSpawn(options)
|
||||
if (connectionId && startupOverride?.command) {
|
||||
// Why: SSH providers use `command` only as spawn metadata; the renderer
|
||||
|
||||
Reference in New Issue
Block a user