From 7dedcbfd71aebb67b8be63fb9e06f7db2cb1605f Mon Sep 17 00:00:00 2001 From: ytahdn <1294726970@qq.com> Date: Tue, 8 Sep 2026 09:12:00 +0000 Subject: [PATCH] fix(web-shell): stop surfacing SSE backpressure warning in transcript (#11340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The daemon's slow_client_warning frame reports this SSE subscriber's event queue backing up — a transport diagnostic, not a user-facing failure. Rendering it as a chat status read as a broken connection mid-turn and sent users refreshing or abandoning sessions during normal tool execution. Log the queue watermarks to the console instead; client_evicted remains the real disconnect signal and keeps its own error path. Co-authored-by: 钉萁 --- .../src/daemon/ui/normalizer.ts | 18 +++++++------ .../sdk-typescript/test/unit/daemonUi.test.ts | 25 +++++++++++++------ 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/packages/sdk-typescript/src/daemon/ui/normalizer.ts b/packages/sdk-typescript/src/daemon/ui/normalizer.ts index eda6e4b89a3..f1f77af1247 100644 --- a/packages/sdk-typescript/src/daemon/ui/normalizer.ts +++ b/packages/sdk-typescript/src/daemon/ui/normalizer.ts @@ -190,13 +190,17 @@ export function normalizeDaemonEvent( }, ]; case 'slow_client_warning': - return [ - { - ...base, - type: 'status', - text: 'SSE stream is lagging', - }, - ]; + // The daemon reports this SSE subscriber's queue backing up — a + // transport diagnostic, not a user-facing failure. Surfacing it as a + // transcript status reads as a broken connection mid-turn, so log the + // queue watermarks to the console instead; `client_evicted` remains the + // real disconnect signal and flows through its own error path. Fires at + // most once per overflow episode (daemon-side hysteresis). + if (typeof console !== 'undefined') { + // eslint-disable-next-line no-console -- intentional diagnostic for subscriber backpressure + console.warn?.('[daemon-ui] SSE stream is lagging', event.data); + } + return []; case 'stream_error': { const errorKind = asDaemonErrorKind(getString(event.data, 'errorKind')); return [ diff --git a/packages/sdk-typescript/test/unit/daemonUi.test.ts b/packages/sdk-typescript/test/unit/daemonUi.test.ts index 0912df3f29f..763578dbf26 100644 --- a/packages/sdk-typescript/test/unit/daemonUi.test.ts +++ b/packages/sdk-typescript/test/unit/daemonUi.test.ts @@ -2436,14 +2436,23 @@ describe('daemon UI normalizer and transcript reducer', () => { data: { reason: 'slow' }, }), ).toMatchObject([{ type: 'error', recoverable: true, text: 'slow' }]); - expect( - normalizeDaemonEvent({ - id: 54, - v: 1, - type: 'slow_client_warning', - data: {}, - }), - ).toMatchObject([{ type: 'status', text: 'SSE stream is lagging' }]); + const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined); + try { + expect( + normalizeDaemonEvent({ + id: 54, + v: 1, + type: 'slow_client_warning', + data: { queueSize: 200, maxQueued: 256 }, + }), + ).toEqual([]); + expect(warn).toHaveBeenCalledWith('[daemon-ui] SSE stream is lagging', { + queueSize: 200, + maxQueued: 256, + }); + } finally { + warn.mockRestore(); + } expect( normalizeDaemonEvent({ id: 55,