From 791cb10fe4cc9a6735cbeba92c9eb5213a902979 Mon Sep 17 00:00:00 2001 From: m4air Date: Mon, 7 Sep 2026 16:32:56 -0700 Subject: [PATCH] fix(terminal): avoid repeated waits on stalled snapshot providers --- ...-output-restored-provider-snapshot.test.ts | 24 +++++++++++++++++-- ...ze-terminal-buffer-from-available-state.ts | 3 ++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/runtime/hidden-output-restored-provider-snapshot.test.ts b/src/main/runtime/hidden-output-restored-provider-snapshot.test.ts index a6d986a9a75..83c9fc88827 100644 --- a/src/main/runtime/hidden-output-restored-provider-snapshot.test.ts +++ b/src/main/runtime/hidden-output-restored-provider-snapshot.test.ts @@ -76,7 +76,16 @@ describe('hidden-output recovery after provider reattach', () => { it('falls back to retained renderer history when a deep provider request stalls', async () => { vi.useFakeTimers() const runtime = createRuntime() - const serializeProviderBuffer = vi.fn(() => new Promise(() => {})) + let settleProvider!: (value: null) => void + const serializeProviderBuffer = vi + .fn() + .mockImplementationOnce( + () => + new Promise((resolve) => { + settleProvider = resolve + }) + ) + .mockResolvedValue({ data: 'provider recovered', cols: 80, rows: 24, seq: 10 }) runtime.setPtyController({ write: () => true, kill: () => true, @@ -94,9 +103,20 @@ describe('hidden-output recovery after provider reattach', () => { source: 'renderer' }) const retry = runtime.serializeHiddenOutputRecoveryBuffer('pty-1', { scrollbackRows: 100000 }) - await vi.advanceTimersByTimeAsync(AUTHORITATIVE_TERMINAL_SNAPSHOT_TIMEOUT_MS) + let retrySettled = false + void retry.then(() => { + retrySettled = true + }) + await vi.advanceTimersByTimeAsync(0) + expect(retrySettled).toBe(true) await expect(retry).resolves.toMatchObject({ data: 'retained SSH history' }) expect(serializeProviderBuffer).toHaveBeenCalledTimes(1) + settleProvider(null) + await vi.advanceTimersByTimeAsync(0) + await expect( + runtime.serializeHiddenOutputRecoveryBuffer('pty-1', { scrollbackRows: 100000 }) + ).resolves.toMatchObject({ data: 'provider recovered' }) + expect(serializeProviderBuffer).toHaveBeenCalledTimes(2) }) it('uses retained provider modes instead of the pre-attach redraw suffix', async () => { diff --git a/src/main/runtime/orca-runtime-serialize-terminal-buffer-from-available-state.ts b/src/main/runtime/orca-runtime-serialize-terminal-buffer-from-available-state.ts index f566d8d2c03..b6eda4acf0f 100644 --- a/src/main/runtime/orca-runtime-serialize-terminal-buffer-from-available-state.ts +++ b/src/main/runtime/orca-runtime-serialize-terminal-buffer-from-available-state.ts @@ -61,7 +61,8 @@ export class OrcaRuntimeWithSerializeTerminalBufferFromAvailableState extends Or } // Bound optional deep-history acquisition without duplicating an outstanding provider request. const provider = await this.serializeProviderTerminalBuffer(ptyId, opts, { - timeoutMs: AUTHORITATIVE_TERMINAL_SNAPSHOT_TIMEOUT_MS + timeoutMs: AUTHORITATIVE_TERMINAL_SNAPSHOT_TIMEOUT_MS, + retireOnTimeout: true }) if (provider) { return provider