You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug report: Web client freezes at "Loading history…" and the page becomes unresponsive after a session grows large
Summary
Opening the dsh web app (or re-opening the workspace / restarting the host) freezes at the "载入历史… / Loading history…" step and the page becomes unresponsive for many seconds. It is not caused by a recent change — it appears progressively ("freezes halfway through using it") as the currently active session accumulates streaming events. The larger the session, the longer the freeze.
Environment
Product: dsh web client (@deepseek-ai/dsh-client-web) served by the host dsh process
Version: current master (post dsh-0.1.1-rc.2)
Platform: Windows (host + browser)
Backend: dsh-session-persistence-jsonl (zstd)
Browser: Chromium-based
Steps to reproduce
Use dsh web inside a workspace for a while — enough for one or more turns to stream a large amount of reasoning and/or tool-call argument deltas (e.g. a long agent run).
Reload the page, or restart the host and re-open the workspace (the previously selected session is auto-opened).
Observe the conversation view stuck at "载入历史… / Loading history…"; the page does not respond to clicks or scrolling for several seconds (or indefinitely until the request settles).
Expected behavior
History loads responsively regardless of how long the session is; the page stays interactive while loading.
Actual behavior
The page freezes at the history-loading step and becomes unresponsive. Measured on two real sessions:
Session
Storage rows (JSONL)
Expanded events
Tail-50-message page events
A
30,062
535,316
47,855
B
—
559,123
78,516
Both the host and the browser main thread are blocked:
Host (single-threaded Node event loop):session.history for a detached session synchronously decodes the entire log (persistence.inspect → loadStored → scanLog) and then folds every projection unit over all events (detachedProjectionsFor → registry.restore({}, events, 0)). During this multi-second block every RPC the page depends on (session list, mux, etc.) is queued, so the page appears frozen.
Browser (main thread): the client receives tens of thousands of events in one history page and processes them all synchronously — ConversationNodeAssembler.replaceWindow/flush and the un-virtualized ChatView (order.map(...) mounting every node) — freezing the UI.
Root cause analysis
1. A history "page" is bounded by message count, not event count
paginate in packages/host/apiproxy/src/api-proxy.ts counts only user/message and assistant/message events (MESSAGE_TYPES), capped at maxMessages (default 50). Every other event in the seq range — including assistant/chunk streaming deltas — is included without limit. One turn's delta stream can contain tens of thousands of events, so the "last 50 messages" can span ~48K–78K events.
2. Packed chunk rows are expanded on every read
assistant/chunk deltas are stored compactly as text-chunks / reasoning-chunks / tool-call-chunks storage rows (packages/core/session/src/chunk-rows.ts), but decodeStorageRecord expands each row back into the individual events on load. Measured session A expands to 535,316 events dominated by:
tool-call-chunks → 292,317 expanded events
reasoning-chunks → 209,144 expanded events
text-chunks → 25,679 expanded events
3. Both sides choke
Server:session.history (detached path) → inspectServable → persistence.inspect → scanLog (sync decode+expand of the whole log) + detachedProjectionsFor (fold over all events). The host event loop blocks for seconds; all concurrent RPCs stall.
Client: the tail page of 48K–78K events is fed to the conversation assembler and the un-virtualized chat renderer on the main thread, freezing the page.
4. Compaction does not help
compaction/prune removes old messages, but the delta chunks inside retained messages are not removed, so long-running sessions inevitably accumulate enough deltas to cross the threshold.
Suggested labels
Issue Type: Bug
area/web (client freeze), possibly area/api (host RPC gateway) and the session area
Additional notes
The freeze reproduces on the auto-selected (previously active) session at startup; archiving old sessions does not help because the affected session is the current one and session.list already reads only log headers.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Bug report: Web client freezes at "Loading history…" and the page becomes unresponsive after a session grows large
Summary
Opening the dsh web app (or re-opening the workspace / restarting the host) freezes at the "载入历史… / Loading history…" step and the page becomes unresponsive for many seconds. It is not caused by a recent change — it appears progressively ("freezes halfway through using it") as the currently active session accumulates streaming events. The larger the session, the longer the freeze.
Environment
@deepseek-ai/dsh-client-web) served by the hostdshprocessdsh-0.1.1-rc.2)dsh-session-persistence-jsonl(zstd)Steps to reproduce
Expected behavior
History loads responsively regardless of how long the session is; the page stays interactive while loading.
Actual behavior
The page freezes at the history-loading step and becomes unresponsive. Measured on two real sessions:
Both the host and the browser main thread are blocked:
session.historyfor a detached session synchronously decodes the entire log (persistence.inspect→loadStored→scanLog) and then folds every projection unit over all events (detachedProjectionsFor→registry.restore({}, events, 0)). During this multi-second block every RPC the page depends on (session list, mux, etc.) is queued, so the page appears frozen.ConversationNodeAssembler.replaceWindow/flushand the un-virtualizedChatView(order.map(...)mounting every node) — freezing the UI.Root cause analysis
1. A history "page" is bounded by message count, not event count
paginateinpackages/host/apiproxy/src/api-proxy.tscounts onlyuser/messageandassistant/messageevents (MESSAGE_TYPES), capped atmaxMessages(default 50). Every other event in the seq range — includingassistant/chunkstreaming deltas — is included without limit. One turn's delta stream can contain tens of thousands of events, so the "last 50 messages" can span ~48K–78K events.2. Packed chunk rows are expanded on every read
assistant/chunkdeltas are stored compactly astext-chunks/reasoning-chunks/tool-call-chunksstorage rows (packages/core/session/src/chunk-rows.ts), butdecodeStorageRecordexpands each row back into the individual events on load. Measured session A expands to 535,316 events dominated by:tool-call-chunks→ 292,317 expanded eventsreasoning-chunks→ 209,144 expanded eventstext-chunks→ 25,679 expanded events3. Both sides choke
session.history(detached path) →inspectServable→persistence.inspect→scanLog(sync decode+expand of the whole log) +detachedProjectionsFor(fold over all events). The host event loop blocks for seconds; all concurrent RPCs stall.4. Compaction does not help
compaction/pruneremoves old messages, but the delta chunks inside retained messages are not removed, so long-running sessions inevitably accumulate enough deltas to cross the threshold.Suggested labels
area/web(client freeze), possiblyarea/api(host RPC gateway) and the session areaAdditional notes
session.listalready reads only log headers.All reactions