前言¶
長 DSH 會話最終會達到一個大小,此時原生壓縮停止工作。其機制值得精確說明,因爲這是導致失敗永久化的原因:
- 壓縮會將整個被陰影覆蓋的區域作爲輸入重放,提交給一次總結請求。
- 上游提供商對單個請求的提示強制執行硬上限。
- 一旦會話超過該上限,壓縮請求本身就會超過上限。
- 因此,壓縮每次都會失敗,永遠不會治癒溢出。
會話隨後無法被壓縮,無法被繼續,並且——因爲簡單的交接實現以相同方式構建總結請求——也無法被交接。這就是死鎖。/handoff 存在以打破它。
是什麼¶
這是一個 DSH 插件,用於在舊會話變得不可用之前,將其記憶傳遞給新會話。
- 維護者:iuuuuuuuu
- 類別:記憶
- 許可證:MIT
- 核心價值:解決會話因上下文溢出而陷入死鎖的問題,通過總結與傳遞實現記憶保全。
安裝與啓用¶
安裝插件需要指定目標配置文件。
dsh plugin --profile <name> add /path/to/dsh-session-handoff
安裝後必須重啓 DSH 才能生效。DSH 的加載器緩存機制決定了這一點:如果不重啓,修改插件源碼或新增插件不會在運行中的宿主生效。
重啓後,日誌中應顯示安裝成功的標誌:
[session-handoff] installed: /handoff registered, pressure monitor active (upstream limit 1048576)
核心功能¶
上下文壓力監控¶
插件在每個回合邊界測量會話的 token 壓力,並與兩個獨立上限進行比對,取其中較緊者作爲綁定上限:
- 模型上下文窗口:從會話使用的模型配置讀取,代表模型本身接受的大小。
- 上游提示限制:配置項,代表提供者對單次請求的接受上限。
後者是導致會話崩潰的實際原因,且無法從前者推導得出。當壓力越過策略階梯時,插件會向會話注入通知,告知測量值、綁定上限以及退出路徑。該通知是模型面向的上下文,不會自發開啓新回合,且對增長和時間進行了限流。
自動會話交接¶
自動交接默認開啓;自動歸檔默認關閉。
當會話因三種獨立原因變得不可用時,會觸發自動交接:
- 壓力:測量壓力達到閾值。
- 超時:會話持續時間過長。
- 會話死亡:上游服務返回錯誤。
交接運行在一個事務中:讀取會話 -> 提取四層記憶 -> 有界總結 -> 創建繼承路由與工作目錄的新會話 -> 交付種子作爲新會話的第一回合 -> 歸檔舊會話 -> 釋放舊會話事件樹。新會話會立即開始工作。
記憶保全¶
設計問題在於攜帶什麼。插件提取四層記憶,按成本排序:
- 逐字事實:正則提取,精確,成本爲零。
- 之前的檢查點:會話已成功寫入的
compaction/end總結,精確,成本爲零。 - 近期轉述:對話的尾部,逐字,精確,成本爲零。
- 敘述總結:模型生成的總結,改寫,需要一次處理。
前三層精確層永遠不會被丟棄以騰出空間給改寫層;只有改寫層會被截斷,且僅截斷中間部分。逐字尾部獲得種子預算的保留份額,而非與散文競爭。
憑證脫敏¶
逐字層是副本,會複製會話曾經回顯的內容。爲防止憑證泄露,插件在寫入前會根據形狀進行脫敏:移除 bearer tokens、sk- / ghp_ / github_pat_ / xox / AKIA 密鑰、JWT、PEM 私鑰、password= 賦值以及內聯連接字符串密碼。事實層也會被脫敏,因爲路徑可能包含密鑰。
典型用法¶
使用以下命令進行手動操作:
/handoff hand this conversation off to a fresh session
/handoff-status show the measurement, the binding ceiling, and the trigger state
執行 /handoff 會打印一份報告:
Handed off `session-9ef22e43-…` to `session-e7d70ba3-…`.
- read: 32286 messages, 117541 events
- memory: 240 facts, 0 checkpoints
- summarize: 70 chunk(s), source=map-reduce, 18422 chars
- seed: 21544 chars (~5386 tokens)
- create: session-e7d70ba3-…
- archive: session-9ef22e43-…
The source session is archived; it stays readable in the sidebar.
注意:歸檔操作在最後執行,因此如果早期步驟失敗,源會話仍然完整可用。
實現細節與注意事項¶
歸檔與釋放的區別¶
歸檔是一種可見性變更:會話 ID 加入歸檔集,使其在側邊欄的默認視圖中隱藏。其日誌仍留在磁盤上,保持可讀性,取消歸檔可恢復其確切位置。歸檔不刪除任何內容,也不釋放內存。
釋放規則:會話只有在被歸檔後才能被釋放。
釋放調用 SessionStore.remove(id),執行存儲的官方分離生命週期。這會從 ctx.sessions(會話事件樹)中移除會話,但不會從 ctx.agents(Agent)中移除。Agent 註冊表是純 Map,沒有公共移除方法,且由 Agent 循環調用,插件無法調用。因此,釋放會話會移除事件樹,但其 Agent 仍持有對樹的引用,磁盤日誌也保持不變。
適用場景與注意¶
該插件適合長對話場景,特別是上游提供商對單次請求有嚴格限制,而模型配置的上下文窗口遠大於此限制的情況。
- 安裝生效:安裝後必須重啓 DSH。
- 內存管理:理解歸檔僅改變可見性,釋放僅移除會話樹,Agent 仍持有引用。
- 權限:插件以當前 DSH 進程權限運行,安裝前應檢查源碼與許可證。
結語¶
/handoff 插件通過主動的上下文壓力監控與記憶保全機制,解決了 DSH 會話在上下文溢出時的死鎖問題。它將“無法繼續”的對話轉化爲可繼承的種子,確保工作流不會因單次會話的膨脹而中斷。
- 目錄頁:https://www.skillhub.cn/plugins/iuuuuuuuu/dsh-session-handoff
- GitHub 倉庫:https://github.com/iuuuuuuuu/dsh-session-handoff