diff --git a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts index d0b63186d48..328a2d15386 100644 --- a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts +++ b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.test.ts @@ -889,6 +889,25 @@ describe('createRemoteRuntimePtyTransport', () => { transport.destroy?.() }) + it('forwards an empty authoritative snapshot so a cached parked viewport clears', async () => { + const { createRemoteRuntimePtyTransport } = await import('./remote-runtime-pty-transport') + const onReplayData = vi.fn() + const transport = createRemoteRuntimePtyTransport('env-1', { + worktreeId: 'wt-1', + tabId: 'web-terminal-host-tab-1', + leafId: 'pane:1' + }) + + const connect = transport.connect({ url: '', callbacks: { onReplayData } }) + await vi.waitFor(() => expect(subscriptionSendBinary).toHaveBeenCalled()) + emitSnapshot(latestSubscribePayload().streamId, '') + await connect + + expect(onReplayData).toHaveBeenCalledOnce() + expect(onReplayData).toHaveBeenCalledWith('') + transport.destroy?.() + }) + it('keeps the current mirror input queue when an older connect settles', async () => { const healthyRuntimeCall = runtimeCall.getMockImplementation() let releaseFirstActivation = (): void => {} diff --git a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts index b0a3ed893ac..a50fbb1a200 100644 --- a/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts +++ b/src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts @@ -1858,8 +1858,8 @@ export function createRemoteRuntimePtyTransport( } }, onSnapshot: (data, meta) => { - // Why: an empty snapshot can still carry a pending mid-escape tail that must replay so the next live chunk completes it. - if ((data || meta?.pendingEscapeTailAnsi) && isCurrentSubscription()) { + // Why: an empty snapshot is still authoritative and must clear a cached parked viewport. + if (isCurrentSubscription()) { if (subscribedPtyId && bufferPtyShutdownReplayData(subscribedPtyId, data)) { return }