diff --git a/src/renderer/src/components/terminal-pane/pty-connection.test.ts b/src/renderer/src/components/terminal-pane/pty-connection.test.ts index e3b13ee0962..8e36d582247 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts @@ -24,6 +24,10 @@ async function flushAsyncTicks(count = 6): Promise { } } +// Why: rich hidden-model restore supersedes these legacy renderer-skip grammar +// assertions; PR #5170 deletes the grammar and removes this block entirely. +const itLegacyHiddenSkipGrammar = it.skip + const toastInfo = vi.fn() const LEAF_1 = '11111111-1111-4111-8111-111111111111' as const const LEAF_2 = '22222222-2222-4222-8222-222222222222' as const @@ -3368,48 +3372,51 @@ describe('connectPanePty', () => { expect(transport.sendInput).not.toHaveBeenCalled() }) - it('keeps non-visible local PTY bytes on the live xterm path for release', async () => { - const pendingTimeouts: (() => void)[] = [] - const originalSetTimeout = globalThis.setTimeout - globalThis.setTimeout = vi.fn((fn: () => void) => { - pendingTimeouts.push(fn) - return 999 as unknown as ReturnType - }) as unknown as typeof setTimeout + itLegacyHiddenSkipGrammar( + 'keeps non-visible local PTY bytes on the live xterm path for release', + async () => { + const pendingTimeouts: (() => void)[] = [] + const originalSetTimeout = globalThis.setTimeout + globalThis.setTimeout = vi.fn((fn: () => void) => { + pendingTimeouts.push(fn) + return 999 as unknown as ReturnType + }) as unknown as typeof setTimeout - try { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation( - async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' + try { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + + const pane = createPane(1) + const manager = createManager(1) + const deps = createDeps({ + isVisibleRef: { current: false } + }) + + connectPanePty(pane as never, manager as never, deps as never) + await flushAsyncTicks(6) + + expect(capturedDataCallback.current).not.toBeNull() + capturedDataCallback.current?.('hello\r\n') + expect(pane.terminal.write).not.toHaveBeenCalledWith('hello\r\n') + + for (const fn of pendingTimeouts) { + fn() } - ) - transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const deps = createDeps({ - isVisibleRef: { current: false } - }) - - connectPanePty(pane as never, manager as never, deps as never) - await flushAsyncTicks(6) - - expect(capturedDataCallback.current).not.toBeNull() - capturedDataCallback.current?.('hello\r\n') - expect(pane.terminal.write).not.toHaveBeenCalledWith('hello\r\n') - - for (const fn of pendingTimeouts) { - fn() + expect(pane.terminal.write).toHaveBeenCalledWith('hello\r\n') + } finally { + globalThis.setTimeout = originalSetTimeout } - - expect(pane.terminal.write).toHaveBeenCalledWith('hello\r\n') - } finally { - globalThis.setTimeout = originalSetTimeout } - }) + ) it('keeps visually rich hidden PTY bytes on the live xterm path', async () => { const { connectPanePty } = await import('./pty-connection') @@ -3787,82 +3794,92 @@ describe('connectPanePty', () => { expect(pane.terminal.write).toHaveBeenCalledWith('backgrounded document output\r\n') }) - it('keeps hidden Codex telemetry startup output parsing briefly', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { - command: 'wrapped-agent', - telemetry: { - agent_kind: 'codex', - launch_source: 'tab_bar_quick_launch', - request_kind: 'new' - } + itLegacyHiddenSkipGrammar( + 'keeps hidden Codex telemetry startup output parsing briefly', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' } - }) as never - ) - await flushAsyncTicks(6) + ) + transportFactoryQueue.push(transport) - expect(capturedDataCallback.current).not.toBeNull() + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { + command: 'wrapped-agent', + telemetry: { + agent_kind: 'codex', + launch_source: 'tab_bar_quick_launch', + request_kind: 'new' + } + } + }) as never + ) + await flushAsyncTicks(6) - capturedDataCallback.current?.('\x1b]11;?\x1b\\startup frame\r\n') + expect(capturedDataCallback.current).not.toBeNull() - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - '\x1b]11;?\x1b\\startup frame\r\n', - expect.any(Function) - ) + capturedDataCallback.current?.('\x1b]11;?\x1b\\startup frame\r\n') - binding.dispose() - }) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith( + '\x1b]11;?\x1b\\startup frame\r\n', + expect.any(Function) + ) - it('keeps hidden bare Codex startup commands parsing briefly', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) + binding.dispose() + } + ) - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) + itLegacyHiddenSkipGrammar( + 'keeps hidden bare Codex startup commands parsing briefly', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) - expect(capturedDataCallback.current).not.toBeNull() + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) - capturedDataCallback.current?.('\x1b]11;?\x1b\\startup frame\r\n') + expect(capturedDataCallback.current).not.toBeNull() - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - '\x1b]11;?\x1b\\startup frame\r\n', - expect.any(Function) - ) + capturedDataCallback.current?.('\x1b]11;?\x1b\\startup frame\r\n') - binding.dispose() - }) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith( + '\x1b]11;?\x1b\\startup frame\r\n', + expect.any(Function) + ) + + binding.dispose() + } + ) it('skips arbitrary hidden startup output parsing', async () => { const { connectPanePty } = await import('./pty-connection') @@ -3898,94 +3915,104 @@ describe('connectPanePty', () => { binding.dispose() }) - it('side-channel answers mode 2031 when hidden Codex output is snapshot-backed', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - mockStoreState = { - ...mockStoreState, - settings: { ...mockStoreState.settings, theme: 'light' } + itLegacyHiddenSkipGrammar( + 'side-channel answers mode 2031 when hidden Codex output is snapshot-backed', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + mockStoreState = { + ...mockStoreState, + settings: { ...mockStoreState.settings, theme: 'light' } + } + + const pane = createPane(1) + const manager = createManager(1) + const paneMode2031Ref = { current: new Map() } + const paneLastThemeModeRef = { current: new Map() } + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + paneMode2031Ref, + paneLastThemeModeRef, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) + + vi.useFakeTimers() + try { + capturedDataCallback.current?.('\x1b[?2031h') + vi.advanceTimersByTime(50) + + expect(transport.sendInput).toHaveBeenCalledWith('\x1b[?997;2n') + expect(paneMode2031Ref.current.get(1)).toBe(true) + expect(paneLastThemeModeRef.current.get(1)).toBe('light') + expect(pane.terminal.write).not.toHaveBeenCalledWith('\x1b[?2031h') + } finally { + vi.useRealTimers() + } + + binding.dispose() } + ) - const pane = createPane(1) - const manager = createManager(1) - const paneMode2031Ref = { current: new Map() } - const paneLastThemeModeRef = { current: new Map() } - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - paneMode2031Ref, - paneLastThemeModeRef, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) + itLegacyHiddenSkipGrammar( + 'answers hidden Codex mode 2031 subscribes split across becoming visible', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + mockStoreState = { + ...mockStoreState, + settings: { ...mockStoreState.settings, theme: 'light' } + } - vi.useFakeTimers() - try { - capturedDataCallback.current?.('\x1b[?2031h') - vi.advanceTimersByTime(50) + const isVisibleRef = { current: false } + const paneMode2031Ref = { current: new Map() } + const paneLastThemeModeRef = { current: new Map() } + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef, + paneMode2031Ref, + paneLastThemeModeRef, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) + + capturedDataCallback.current?.('\x1b[?20') + isVisibleRef.current = true + capturedDataCallback.current?.('31h') expect(transport.sendInput).toHaveBeenCalledWith('\x1b[?997;2n') expect(paneMode2031Ref.current.get(1)).toBe(true) expect(paneLastThemeModeRef.current.get(1)).toBe('light') - expect(pane.terminal.write).not.toHaveBeenCalledWith('\x1b[?2031h') - } finally { - vi.useRealTimers() + expect(pane.terminal.write).not.toHaveBeenCalledWith('31h', expect.any(Function)) + + binding.dispose() } - - binding.dispose() - }) - - it('answers hidden Codex mode 2031 subscribes split across becoming visible', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - mockStoreState = { - ...mockStoreState, - settings: { ...mockStoreState.settings, theme: 'light' } - } - - const isVisibleRef = { current: false } - const paneMode2031Ref = { current: new Map() } - const paneLastThemeModeRef = { current: new Map() } - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef, - paneMode2031Ref, - paneLastThemeModeRef, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) - - capturedDataCallback.current?.('\x1b[?20') - isVisibleRef.current = true - capturedDataCallback.current?.('31h') - - expect(transport.sendInput).toHaveBeenCalledWith('\x1b[?997;2n') - expect(paneMode2031Ref.current.get(1)).toBe(true) - expect(paneLastThemeModeRef.current.get(1)).toBe('light') - expect(pane.terminal.write).not.toHaveBeenCalledWith('31h', expect.any(Function)) - - binding.dispose() - }) + ) it('does not keep mode 2031 subscribed when a skipped hidden chunk unsubscribes last', async () => { const { connectPanePty } = await import('./pty-connection') @@ -4088,185 +4115,210 @@ describe('connectPanePty', () => { binding.dispose() }) - it('keeps only coalesced hidden Codex terminal queries on the live xterm path', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) + itLegacyHiddenSkipGrammar( + 'keeps only coalesced hidden Codex terminal queries on the live xterm path', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) - const coalescedChunk = `\x1b[c\x1b[?2026h\x1b[2J\x1b[H${'codex redraw '.repeat(8_000)}` - capturedDataCallback.current?.(coalescedChunk) + const coalescedChunk = `\x1b[c\x1b[?2026h\x1b[2J\x1b[H${'codex redraw '.repeat(8_000)}` + capturedDataCallback.current?.(coalescedChunk) - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith(coalescedChunk, expect.any(Function)) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith(coalescedChunk, expect.any(Function)) - binding.dispose() - }) + binding.dispose() + } + ) - it('keeps split hidden Codex terminal queries on the live xterm path', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) + itLegacyHiddenSkipGrammar( + 'keeps split hidden Codex terminal queries on the live xterm path', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) - capturedDataCallback.current?.('\x1b[') - capturedDataCallback.current?.(`c\x1b[?2026h${'codex redraw '.repeat(8_000)}`) + capturedDataCallback.current?.('\x1b[') + capturedDataCallback.current?.(`c\x1b[?2026h${'codex redraw '.repeat(8_000)}`) - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - `c\x1b[?2026h${'codex redraw '.repeat(8_000)}`, - expect.any(Function) - ) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith( + `c\x1b[?2026h${'codex redraw '.repeat(8_000)}`, + expect.any(Function) + ) - binding.dispose() - }) + binding.dispose() + } + ) - it('keeps hidden Codex terminal queries split after ESC on the live xterm path', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) + itLegacyHiddenSkipGrammar( + 'keeps hidden Codex terminal queries split after ESC on the live xterm path', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) - - capturedDataCallback.current?.('\x1b') - capturedDataCallback.current?.(`[c\x1b[?2026h${'codex redraw '.repeat(8_000)}`) - - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - `[c\x1b[?2026h${'codex redraw '.repeat(8_000)}`, - expect.any(Function) - ) - - binding.dispose() - }) - - it('flushes pending hidden Codex query prefixes when the pane becomes visible', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - - const isVisibleRef = { current: false } - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef, - startup: { command: 'codex' } - }) as never - ) - try { + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { command: 'codex' } + }) as never + ) await flushAsyncTicks(6) capturedDataCallback.current?.('\x1b') - isVisibleRef.current = true - capturedDataCallback.current?.('[c') + capturedDataCallback.current?.(`[c\x1b[?2026h${'codex redraw '.repeat(8_000)}`) expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) - } finally { - binding.dispose() - } - }) - - it('keeps split hidden-to-visible Codex stateful queries behind snapshot restore', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< - typeof vi.fn - > - getMainBufferSnapshot.mockResolvedValue({ - data: 'snapshot-before-cpr\r\n', - cols: 100, - rows: 30 - }) - - const isVisibleRef = { current: false } - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef, - startup: { command: 'codex' } - }) as never - ) - try { - await flushAsyncTicks(6) - - capturedDataCallback.current?.('\x1b[6') - isVisibleRef.current = true - capturedDataCallback.current?.('n') - await flushAsyncTicks(20) - - expect(pane.terminal.write).toHaveBeenCalledWith( - 'snapshot-before-cpr\r\n', + expect(pane.terminal.write).not.toHaveBeenCalledWith( + `[c\x1b[?2026h${'codex redraw '.repeat(8_000)}`, expect.any(Function) ) - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[6n', expect.any(Function)) - } finally { + binding.dispose() } - }) + ) + + itLegacyHiddenSkipGrammar( + 'flushes pending hidden Codex query prefixes when the pane becomes visible', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + + const isVisibleRef = { current: false } + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef, + startup: { command: 'codex' } + }) as never + ) + try { + await flushAsyncTicks(6) + + capturedDataCallback.current?.('\x1b') + isVisibleRef.current = true + capturedDataCallback.current?.('[c') + + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[c', expect.any(Function)) + } finally { + binding.dispose() + } + } + ) + + itLegacyHiddenSkipGrammar( + 'keeps split hidden-to-visible Codex stateful queries behind snapshot restore', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< + typeof vi.fn + > + getMainBufferSnapshot.mockResolvedValue({ + data: 'snapshot-before-cpr\r\n', + cols: 100, + rows: 30 + }) + + const isVisibleRef = { current: false } + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef, + startup: { command: 'codex' } + }) as never + ) + try { + await flushAsyncTicks(6) + + capturedDataCallback.current?.('\x1b[6') + isVisibleRef.current = true + capturedDataCallback.current?.('n') + await flushAsyncTicks(20) + + expect(pane.terminal.write).toHaveBeenCalledWith( + 'snapshot-before-cpr\r\n', + expect.any(Function) + ) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[6n', expect.any(Function)) + } finally { + binding.dispose() + } + } + ) it('keeps all visible bytes after a pending hidden ESC becomes non-query output', async () => { const { connectPanePty } = await import('./pty-connection') @@ -4312,49 +4364,54 @@ describe('connectPanePty', () => { } }) - it('keeps split stateful Codex queries live after becoming visible', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< - typeof vi.fn - > - getMainBufferSnapshot.mockResolvedValue({ - data: 'snapshot-before-visible\r\n', - cols: 100, - rows: 30 - }) + itLegacyHiddenSkipGrammar( + 'keeps split stateful Codex queries live after becoming visible', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< + typeof vi.fn + > + getMainBufferSnapshot.mockResolvedValue({ + data: 'snapshot-before-visible\r\n', + cols: 100, + rows: 30 + }) - const isVisibleRef = { current: false } - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef, - startup: { command: 'codex' } - }) as never - ) - try { - await flushAsyncTicks(6) + const isVisibleRef = { current: false } + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef, + startup: { command: 'codex' } + }) as never + ) + try { + await flushAsyncTicks(6) - capturedDataCallback.current?.('\x1b[') - isVisibleRef.current = true - capturedDataCallback.current?.('6n') - await flushAsyncTicks(20) + capturedDataCallback.current?.('\x1b[') + isVisibleRef.current = true + capturedDataCallback.current?.('6n') + await flushAsyncTicks(20) - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[6n', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith('6n', expect.any(Function)) - } finally { - binding.dispose() + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b[6n', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith('6n', expect.any(Function)) + } finally { + binding.dispose() + } } - }) + ) it('drops pending hidden Codex query prefixes when the PTY changes', async () => { const { connectPanePty } = await import('./pty-connection') @@ -4429,73 +4486,83 @@ describe('connectPanePty', () => { binding.dispose() }) - it('keeps split hidden Codex OSC color queries on the live xterm path', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) + itLegacyHiddenSkipGrammar( + 'keeps split hidden Codex OSC color queries on the live xterm path', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) - capturedDataCallback.current?.('\x1b]11;?') - capturedDataCallback.current?.(`\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`) + capturedDataCallback.current?.('\x1b]11;?') + capturedDataCallback.current?.(`\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`) - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - `\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`, - expect.any(Function) - ) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith( + `\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`, + expect.any(Function) + ) - binding.dispose() - }) + binding.dispose() + } + ) - it('keeps hidden Codex OSC color queries split before the prefix on the live xterm path', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) + itLegacyHiddenSkipGrammar( + 'keeps hidden Codex OSC color queries split before the prefix on the live xterm path', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { current: ((data: string) => void) | null } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const binding = connectPanePty( - pane as never, - manager as never, - createDeps({ - isVisibleRef: { current: false }, - startup: { command: 'codex' } - }) as never - ) - await flushAsyncTicks(6) + const pane = createPane(1) + const manager = createManager(1) + const binding = connectPanePty( + pane as never, + manager as never, + createDeps({ + isVisibleRef: { current: false }, + startup: { command: 'codex' } + }) as never + ) + await flushAsyncTicks(6) - capturedDataCallback.current?.('\x1b]') - capturedDataCallback.current?.(`11;?\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`) + capturedDataCallback.current?.('\x1b]') + capturedDataCallback.current?.(`11;?\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`) - expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - `11;?\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`, - expect.any(Function) - ) + expect(pane.terminal.write).toHaveBeenCalledWith('\x1b]11;?\x1b\\', expect.any(Function)) + expect(pane.terminal.write).not.toHaveBeenCalledWith( + `11;?\x1b\\\x1b[?2026h${'codex redraw '.repeat(8_000)}`, + expect.any(Function) + ) - binding.dispose() - }) + binding.dispose() + } + ) it('keeps later hidden Codex stateless terminal queries on the live xterm path', async () => { const { connectPanePty } = await import('./pty-connection') @@ -4594,52 +4661,57 @@ describe('connectPanePty', () => { binding.dispose() }) - it('writes ordinary hidden output live instead of proactively restoring a snapshot', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') - const capturedDataCallback: { - current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null - } = { current: null } - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' - }) - transportFactoryQueue.push(transport) - const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< - typeof vi.fn - > - const hidden = 'small-hidden-output\r\n' - const live = 'visible-after-hidden\r\n' - getMainBufferSnapshot.mockResolvedValue({ - data: `snapshot-with-${hidden}`, - cols: 100, - rows: 30, - seq: hidden.length + live.length - }) + itLegacyHiddenSkipGrammar( + 'writes ordinary hidden output live instead of proactively restoring a snapshot', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { + current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null + } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< + typeof vi.fn + > + const hidden = 'small-hidden-output\r\n' + const live = 'visible-after-hidden\r\n' + getMainBufferSnapshot.mockResolvedValue({ + data: `snapshot-with-${hidden}`, + cols: 100, + rows: 30, + seq: hidden.length + live.length + }) - const pane = createPane(1) - const manager = createManager(1) - const deps = createDeps({ - isVisibleRef: { current: false } - }) - const disposable = connectPanePty(pane as never, manager as never, deps as never) - await flushAsyncTicks(6) + const pane = createPane(1) + const manager = createManager(1) + const deps = createDeps({ + isVisibleRef: { current: false } + }) + const disposable = connectPanePty(pane as never, manager as never, deps as never) + await flushAsyncTicks(6) - capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) - expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden, expect.any(Function)) + capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) + expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden, expect.any(Function)) - ;(deps.isVisibleRef as { current: boolean }).current = true - capturedDataCallback.current?.(live, { - seq: hidden.length + live.length, - rawLength: live.length - }) - await flushAsyncTicks(20) + ;(deps.isVisibleRef as { current: boolean }).current = true + capturedDataCallback.current?.(live, { + seq: hidden.length + live.length, + rawLength: live.length + }) + await flushAsyncTicks(20) - expect(getMainBufferSnapshot).not.toHaveBeenCalled() - expect(pane.terminal.write).toHaveBeenCalledWith(hidden) - expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function)) - disposable.dispose() - }) + expect(getMainBufferSnapshot).not.toHaveBeenCalled() + expect(pane.terminal.write).toHaveBeenCalledWith(hidden) + expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function)) + disposable.dispose() + } + ) it('restores hidden Latin text from the main snapshot when the pane returns', async () => { const { connectPanePty } = await import('./pty-connection') @@ -4730,113 +4802,121 @@ describe('connectPanePty', () => { disposable.dispose() }) - it('writes ordinary hidden remote runtime output live instead of restoring a snapshot', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('remote:env-1@@terminal-1') - const capturedDataCallback: { - current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null - } = { current: null } - transport.serializeBuffer = vi.fn().mockResolvedValue({ - data: 'remote snapshot\r\n', - cols: 120, - rows: 40, - seq: 40, - source: 'headless' - }) - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'remote:env-1@@terminal-1' - }) - transportFactoryQueue.push(transport) - const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< - typeof vi.fn - > - - const pane = createPane(1) - const manager = createManager(1) - const deps = createDeps({ isVisibleRef: { current: false } }) - const disposable = connectPanePty(pane as never, manager as never, deps as never) - await flushAsyncTicks(6) - - const hidden = 'hidden remote output\r\n' - const live = 'visible remote output\r\n' - capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) - expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden, expect.any(Function)) - - ;(deps.isVisibleRef as { current: boolean }).current = true - capturedDataCallback.current?.(live, { - seq: 40 + live.length, - rawLength: live.length - }) - await flushAsyncTicks(20) - - expect(getMainBufferSnapshot).not.toHaveBeenCalled() - expect(transport.serializeBuffer).not.toHaveBeenCalled() - expect(pane.terminal.write).toHaveBeenCalledWith(hidden) - expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function)) - disposable.dispose() - }) - - it('keeps inactive split-pane hidden output live instead of deferring snapshot restore', async () => { - const { resetHiddenOutputRestoreSchedulerForTests } = - await import('./hidden-output-restore-scheduler') - let disposable: { dispose: () => void } | null = null - try { + itLegacyHiddenSkipGrammar( + 'writes ordinary hidden remote runtime output live instead of restoring a snapshot', + async () => { const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('pty-id') + const transport = createMockTransport('remote:env-1@@terminal-1') const capturedDataCallback: { current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null } = { current: null } + transport.serializeBuffer = vi.fn().mockResolvedValue({ + data: 'remote snapshot\r\n', + cols: 120, + rows: 40, + seq: 40, + source: 'headless' + }) transport.connect.mockImplementation( async ({ callbacks }: { callbacks: ConnectCallbacks }) => { capturedDataCallback.current = callbacks.onData ?? null - return 'pty-id' + return 'remote:env-1@@terminal-1' } ) transportFactoryQueue.push(transport) const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< typeof vi.fn > - getMainBufferSnapshot.mockResolvedValue({ - data: 'inactive snapshot\r\n', - cols: 100, - rows: 30, - seq: 64 - }) const pane = createPane(1) - const manager = createManager(2) - manager.getActivePane.mockReturnValue({ id: 2 }) + const manager = createManager(1) const deps = createDeps({ isVisibleRef: { current: false } }) - disposable = connectPanePty(pane as never, manager as never, deps as never) + const disposable = connectPanePty(pane as never, manager as never, deps as never) await flushAsyncTicks(6) - const hidden = 'hidden inactive output\r\n' - const live = 'visible inactive output\r\n' - expect(capturedDataCallback.current).not.toBeNull() + const hidden = 'hidden remote output\r\n' + const live = 'visible remote output\r\n' capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) + expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden, expect.any(Function)) + ;(deps.isVisibleRef as { current: boolean }).current = true capturedDataCallback.current?.(live, { - seq: hidden.length + live.length, + seq: 40 + live.length, rawLength: live.length }) - await flushAsyncTicks(4) - - expect(getMainBufferSnapshot).not.toHaveBeenCalled() - - // Why: inactive split restore is frame-spaced, so this waits past one - // scheduler tick without depending on fake timers for xterm callbacks. - await new Promise((resolve) => setTimeout(resolve, 30)) await flushAsyncTicks(20) expect(getMainBufferSnapshot).not.toHaveBeenCalled() + expect(transport.serializeBuffer).not.toHaveBeenCalled() expect(pane.terminal.write).toHaveBeenCalledWith(hidden) expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function)) - } finally { - disposable?.dispose() - resetHiddenOutputRestoreSchedulerForTests() + disposable.dispose() } - }) + ) + + itLegacyHiddenSkipGrammar( + 'keeps inactive split-pane hidden output live instead of deferring snapshot restore', + async () => { + const { resetHiddenOutputRestoreSchedulerForTests } = + await import('./hidden-output-restore-scheduler') + let disposable: { dispose: () => void } | null = null + try { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('pty-id') + const capturedDataCallback: { + current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null + } = { current: null } + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'pty-id' + } + ) + transportFactoryQueue.push(transport) + const getMainBufferSnapshot = window.api.pty.getMainBufferSnapshot as unknown as ReturnType< + typeof vi.fn + > + getMainBufferSnapshot.mockResolvedValue({ + data: 'inactive snapshot\r\n', + cols: 100, + rows: 30, + seq: 64 + }) + + const pane = createPane(1) + const manager = createManager(2) + manager.getActivePane.mockReturnValue({ id: 2 }) + const deps = createDeps({ isVisibleRef: { current: false } }) + disposable = connectPanePty(pane as never, manager as never, deps as never) + await flushAsyncTicks(6) + + const hidden = 'hidden inactive output\r\n' + const live = 'visible inactive output\r\n' + expect(capturedDataCallback.current).not.toBeNull() + capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) + ;(deps.isVisibleRef as { current: boolean }).current = true + capturedDataCallback.current?.(live, { + seq: hidden.length + live.length, + rawLength: live.length + }) + await flushAsyncTicks(4) + + expect(getMainBufferSnapshot).not.toHaveBeenCalled() + + // Why: inactive split restore is frame-spaced, so this waits past one + // scheduler tick without depending on fake timers for xterm callbacks. + await new Promise((resolve) => setTimeout(resolve, 30)) + await flushAsyncTicks(20) + + expect(getMainBufferSnapshot).not.toHaveBeenCalled() + expect(pane.terminal.write).toHaveBeenCalledWith(hidden) + expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function)) + } finally { + disposable?.dispose() + resetHiddenOutputRestoreSchedulerForTests() + } + } + ) it('drops a deferred inactive hidden restore when the pane is hidden again', async () => { const { resetHiddenOutputRestoreSchedulerForTests } = @@ -4896,59 +4976,64 @@ describe('connectPanePty', () => { } }) - it('does not retry remote snapshots for ordinary hidden runtime output', async () => { - const { connectPanePty } = await import('./pty-connection') - const transport = createMockTransport('remote:env-1@@terminal-1') - const capturedDataCallback: { - current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null - } = { current: null } - transport.serializeBuffer = vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce({ - data: 'remote recovered snapshot\r\n', - cols: 120, - rows: 40, - seq: 80, - source: 'headless' - }) - transport.connect.mockImplementation(async ({ callbacks }: { callbacks: ConnectCallbacks }) => { - capturedDataCallback.current = callbacks.onData ?? null - return 'remote:env-1@@terminal-1' - }) - transportFactoryQueue.push(transport) + itLegacyHiddenSkipGrammar( + 'does not retry remote snapshots for ordinary hidden runtime output', + async () => { + const { connectPanePty } = await import('./pty-connection') + const transport = createMockTransport('remote:env-1@@terminal-1') + const capturedDataCallback: { + current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null + } = { current: null } + transport.serializeBuffer = vi.fn().mockResolvedValueOnce(null).mockResolvedValueOnce({ + data: 'remote recovered snapshot\r\n', + cols: 120, + rows: 40, + seq: 80, + source: 'headless' + }) + transport.connect.mockImplementation( + async ({ callbacks }: { callbacks: ConnectCallbacks }) => { + capturedDataCallback.current = callbacks.onData ?? null + return 'remote:env-1@@terminal-1' + } + ) + transportFactoryQueue.push(transport) - const pane = createPane(1) - const manager = createManager(1) - const deps = createDeps({ isVisibleRef: { current: false } }) - const disposable = connectPanePty(pane as never, manager as never, deps as never) - await flushAsyncTicks(6) + const pane = createPane(1) + const manager = createManager(1) + const deps = createDeps({ isVisibleRef: { current: false } }) + const disposable = connectPanePty(pane as never, manager as never, deps as never) + await flushAsyncTicks(6) - const hidden = 'hidden remote output\r\n' - const firstLive = 'first visible output\r\n' - capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) + const hidden = 'hidden remote output\r\n' + const firstLive = 'first visible output\r\n' + capturedDataCallback.current?.(hidden, { seq: hidden.length, rawLength: hidden.length }) - ;(deps.isVisibleRef as { current: boolean }).current = true - capturedDataCallback.current?.(firstLive, { - seq: hidden.length + firstLive.length, - rawLength: firstLive.length - }) - await flushAsyncTicks(20) + ;(deps.isVisibleRef as { current: boolean }).current = true + capturedDataCallback.current?.(firstLive, { + seq: hidden.length + firstLive.length, + rawLength: firstLive.length + }) + await flushAsyncTicks(20) - expect(transport.serializeBuffer).not.toHaveBeenCalled() - expect(pane.terminal.write).not.toHaveBeenCalledWith( - expect.stringContaining('Orca skipped hidden terminal output'), - expect.any(Function) - ) - expect(pane.terminal.write).not.toHaveBeenCalledWith( - 'remote recovered snapshot\r\n', - expect.any(Function) - ) + expect(transport.serializeBuffer).not.toHaveBeenCalled() + expect(pane.terminal.write).not.toHaveBeenCalledWith( + expect.stringContaining('Orca skipped hidden terminal output'), + expect.any(Function) + ) + expect(pane.terminal.write).not.toHaveBeenCalledWith( + 'remote recovered snapshot\r\n', + expect.any(Function) + ) - await new Promise((resolve) => setTimeout(resolve, 80)) - await flushAsyncTicks(20) + await new Promise((resolve) => setTimeout(resolve, 80)) + await flushAsyncTicks(20) - expect(transport.serializeBuffer).not.toHaveBeenCalled() - expect(pane.terminal.write).toHaveBeenCalledWith(firstLive, expect.any(Function)) - disposable.dispose() - }) + expect(transport.serializeBuffer).not.toHaveBeenCalled() + expect(pane.terminal.write).toHaveBeenCalledWith(firstLive, expect.any(Function)) + disposable.dispose() + } + ) it('restores hidden backlog overflow from the main terminal snapshot on foreground output', async () => { const { connectPanePty } = await import('./pty-connection')