dsh-lag-guard:把長會話的歷史窗口收到 120 條,別讓幾兆工具 schema 撐爆首幀

前言

DeepSeek Harness(下稱 DSH)的會話會越跑越長。點開一條積累了很久的會話,常見的現象是:界面先愣幾秒,接着一片白,然後整個 DSH 沒了。換別的會話就正常,重裝、清緩存都沒用——因爲卡死發生在數據已經取回來、正準備畫到屏幕上的那幾秒,不在網絡,也不在模型。

dsh-lag-guard 就是衝着這個來的。它是社區維護者 456erddgr 寫的一個客戶端插件,只做一件事:讓很長的會話能正常打開。下面介紹它測出的原因、它怎麼修,以及裝上之後你能看到什麼。

先看證據:打開一個會話到底搬了多少東西

作者自己的會話 DSH 安裝與快速啓動 解壓後 5.3MB,共 1087 條事件、176 條 user/assistant 消息。而 DSH 打開會話時的取數參數是寫死的:

// dsh-api-session-controller/lib/client.js:2177
const HISTORY_PAGE_OPTIONS = { maxMessages: 500, turnWindow: { minMessages: 50, minTurns: 2 } };

176 條沒到 500,於是「首頁」就等於「全部」,一次搬進 484 條事件 / 3290.8KB,佔全會話的 61.7%。其中 request/header 只有 4 條,卻佔了 2510.9KB、約 47.1%;單條 header.tools 裏是 201 個工具的完整 JSON schema,627KB。也就是說,將近一半的傳輸量,是把當時所有工具的說明書全文抄了一遍,而這類事件每輪請求都會攢一份。

再疊加另外兩層:

// dsh-client-ui-chat/lib/client.js:290-300
useVirtualizer({
  getItemKey: (i) => items[i]?.turn ?? i,
  estimateSize: () => TURN_SPACING_PX,
  measureElement: () => TURN_SPACING_PX,   // 動態測量被關掉了
});

虛擬化按 turn 切,而該會話只有 7 個 turn,肥瘦極不均(turn1 375 條事件 1.2MB,turn5 309 條 1.6MB),窗口裏就那麼幾塊,等於整塊整塊地畫。

// dsh-client-ui-conversation/lib/client.js:1641
const toolsChanged = previous !== undefined && JSON.stringify(previous.tools) !== JSON.stringify(prompt.tools);

每次視圖重建都要對窗口裏 3 條 header、合計數百個 schema 做一次純 JSON.stringify 比較,耗時 13.4ms,併產出 3.6MB 臨時字符串。問題不在渲染次數(notifier 是 microtask 合批的),也不在 dsh-chunked-list(那只是持久化鏈表),而是 3.3MB 數據、不虛擬化的 turn、反覆 13.4ms 序列化一起落在首幀同步路徑上,主線程被佔死。

它怎麼修

Host 側改不了,typert 註冊表碰上重名會直接拋錯。插件改落在瀏覽器側:會話控制器的客戶端包導出了 SessionEventStream,而它的 follow() 是所有歷史取數的必經之路(開窗首頁、斷檔修復、實時追加都走這一個 async generator),readPage() 走的是旁邊的分頁接口。插件包住這兩個方法,做兩件事。

1、把請求收緊。默認 maxMessages 從 500 收到 120,turnWindow 從 {50, 2} 收到 {20, 1}。取較小值,不會把手動設的更小窗口放大,也保證 minMessages <= maxMessages——不滿足這個不等式會被 Host 的 validatePageRequest 整頁拒成 gateway/bad-request。

2、把幀瘦身。request/header.tools 序列化後超過 20 萬字符,就換成空數組,留下 toolsDropped(原來幾個)和 toolsChars(原來多大);單條 tool/result 超過 128KB 就截斷並標 contentTruncated(兜底,作者那個會話裏 0 命中)。

同一個會話改完的對比:

窗口參數 搬入事件 體積 再丟掉 tools 對比全量
500 / 50,2(原樣) 484 3290.8KB — 61.7%
120 / 20,1(默認) 175 1604.9KB 350.5KB −78%
50 / 10,1(更猛) 67 770.2KB 143.0KB −81%

安裝與啓用

插件市場裏搜 lag-guard(或者 卡、卡頓)就能看到,點安裝即可。手動安裝命令來自 README:

dsh plugin --profile desktop add github:456erddgr/dsh-lag-guard

裝完要重啓 DSH。重啓後點開那個一直卡你的會話,控制台應該會多一行:

[lag-guard] session-77a714c5-... opened with 175 events, dropped 627KB of tool schemas in 29ms

沒出現這行說明沒加載上,去 profile 的 package.json 裏看 dsh.profile.bundles 有沒有 dsh-lag-guard。

典型用法:調窗口和看省了多少

想自己調參數,改 profile 的 cordis.patch.yml。注意補丁會整體替換 config,沒寫的鍵回默認值:

- id: dsh-lag-guard
  config:
    maxMessages: 80          # 更省,首屏更短
    minMessages: 10
    minTurns: 1
    maxHeaderToolsChars: 50000

想臨時改回來、不落盤,在渲染進程控制台裏執行,立即生效:

globalThis.__DSH_LAG_GUARD__ = { maxMessages: 500, minMessages: 50, minTurns: 2, maxHeaderToolsChars: Infinity };

想量化它省了多少,跑自帶的指標收集器:

node tools/sink.mjs          # 本地 17891 端口收數據,寫 tools/metrics.jsonl
node tools/sink.mjs --flush  # 彙總:開了幾次、搬了多少事件、砍了多少 KB schema、最長卡頓

數據只發到 127.0.0.1,不聯網、不上報。想撤掉就把 dependencies 和 dsh.profile.bundles 裏的 dsh-lag-guard 刪掉,pnpm install 後重啓。

會丟什麼、不影響什麼

丟的都不是正文,數據一條沒刪:

  • 首屏歷史變短,更早的內容點「加載更早」再取。
  • 超大 schema 的那幾次請求,Chat 裏「工具集已變更」的小徽標會失效(tools 變空數組,比較結果恆爲「沒變」)。
  • Trajectory 頁籤裏那幾條請求的「工具列表 / 工具差異」視圖會是空的,同一原因。
  • 單條超過 128KB 的工具輸出會截斷顯示並標註。

不影響的:會話日誌文件、Host 的分頁與校驗、模型上下文、工具實際執行、projections、實時流、其它會話。

驗證和已知短板

插件自帶的測試不拿 mock 騙自己:它把 DSH 真實的 dsh-api-session-controller/lib/client.js 丟進 node:vm 跑起來(只 stub 掉 window.__ModuleLoader__ 和三個依賴),再加載插件,用真實會話事件驅動 follow 和 readPage:

node test/verify.mjs --asar <path to @deepseek-ai> --session <path to session.v4.jsonl>

輸出爲 21 項契約全綠,包括「open request clamps maxMessages 500 -> 120」「request/header tools are dropped before publication」「a second module load does not stack wrappers」等。

幾句需要說清楚的短板:

  • 體積數字是精確的,手感不是。作者沒做端到端幀率對比,重啓後還卡不卡以你的體感爲準;還卡就把 maxMessages 調到 50 再試。
  • 它修的是「傳輸 + 首幀」這一層。如果卡頓來自別處(比如某個第三方插件在會話打開時做重型工作),它最多減輕,救不了。
  • 上游一改就失效。依賴的是 SessionEventStream 的導出和 follow / readPage 的形態。哪天 DSH 改了名,install() 會返回 false 並安靜地什麼都不做——不會弄崩 DSH,但也不會幫你。

README 裏給出的版本信息:package.json 爲 0.2.0,更新日誌只寫到 0.1.1 與 0.1.0。許可證 MIT。項目不修改 DSH 安裝目錄裏的任何文件,全部邏輯在一個 253 行的文件裏。

適用場景與提醒

適合經常打開又長又重的歷史會話、且已在排查首幀卡頓的 DSH 用戶。它以當前 DSH 進程權限在瀏覽器側運行,裝之前建議先讀一遍源碼與許可證,確認與你環境的兼容。

這是社區目錄收錄的第三方插件,由 456erddgr 維護,與 DeepSeek / 幻方無官方從屬關係。目錄頁在 https://www.skillhub.cn/plugins/456erddgr/dsh-lag-guard,源碼在 https://github.com/456erddgr/dsh-lag-guard。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜