前言¶
DeepSeek Harness(DSH)在構建多輪對話與智能體系統時,經常需要看到整個會話的完整上下文。默認情況下,DSH 只在當前會話內維護事件日誌,缺乏對歷史會話的統一投影與可調用的只讀查詢能力。dsh-session-recall 爲 DSH 提供了一份有界、零模型的會話史書,並支持按當前 harness 精確版本打開上游那 5 個只讀會話歷史工具。
是什麼¶
- 名稱:dsh-session-recall
- 維護者:xingzoudefengye
- 分類:記憶
- 許可證:MIT
- 核心價值:
- 會話史書:對會話事件日誌的純函數投影,不落盤、不建索引、不跑後臺任務,硬性渲染預算 6,000 字符。
- 上游工具開關:以腳本方式安裝並掛載
@deepseek-ai/dsh-tool-session-query與@deepseek-ai/dsh-session-query-sqlite,版本與@deepseek-ai/dsh-base完全相等。
兼容性¶
- 平臺:Windows 10/11(PowerShell)、macOS(zsh)、Linux(bash/zsh)
- Node:
>=22 - DSH:需要宿主提供
defineTool、ctx.tools.register、cordis 的Service,以及session.snapshotEvents()能力
安裝與啓用¶
1. 安裝史書(必選)¶
dsh plugin --profile web add github:xingzoudefengye/dsh-session-recall
安裝後重啓宿主:
dsh web
2. 啓用上游 5 個只讀歷史工具(可選)¶
在任意目錄執行(PowerShell 與 zsh 通用):
node "$HOME/.dsh/profiles/web/node_modules/dsh-session-recall/scripts/enable-read-tools.mjs" web
(若設置了 DSH_HOME,把 $HOME/.dsh 換成 $env:DSH_HOME。)
該腳本完成四件事:
1. 從 profile 的 @deepseek-ai/dsh-base 讀取 harness 版本;若 manifest 不存在,回退到 dsh --version。
2. 在 profile 目錄裏 pnpm add 兩個包:@deepseek-ai/dsh-tool-session-query 與 @deepseek-ai/dsh-session-query-sqlite,版本與 harness 精確相等。
3. 把 cordis.patch.yml 備份成 cordis.patch.yml.bak-<YYYYMMDD-HHMMSS>,再追加一個 optional-session-search 隔離組。
4. 打印掛載成功提示,並要求重啓。
之後同樣重啓:
dsh web
macOS/Linux 也可以使用 bash 版:
~/.dsh/profiles/web/node_modules/dsh-session-recall/scripts/enable-read-tools.sh web
驗證與自檢¶
運行自檢腳本(在已安裝的 profile 裏):
node "$HOME/.dsh/profiles/web/node_modules/dsh-session-recall/scripts/check.mjs" web
它檢查三件事:兩個史書 row 是否在合成樹裏;上游讀工具是否已掛載;若已掛載,兩個包的版本是否與 harness 精確相等。退出碼 0 表示沒有 FAIL,1 表示有 FAIL(或 profile / dsh 不存在)。
示例輸出(已掛載):
ok: session-chronicle is in the composed tree
ok: tool-session-chronicle is in the composed tree
ok: upstream read tools are mounted (harness 0.2.1-rc.2)
ok: @deepseek-ai/dsh-tool-session-query@0.2.1-rc.2 matches the harness
ok: @deepseek-ai/dsh-session-query-sqlite@0.2.1-rc.2 matches the harness
示例輸出(未掛載):
ok: session-chronicle is in the composed tree
ok: tool-session-chronicle is in the composed tree
note: upstream read tools are not mounted (run scripts/enable-read-tools.mjs web to add them)
示例輸出(版本漂移):
FAIL: @deepseek-ai/dsh-tool-session-query@0.2.0-rc.2 does not match the harness (0.2.1-rc.2) — re-run scripts/enable-read-tools.mjs web
開發自檢(純離線):
npm test
配置¶
史書參數(每次調用)¶
| 參數 | 類型 | 默認 | 作用 |
|---|---|---|---|
lastTurns |
integer | 不傳 = 全部 | 只返回最新的 N 條回合記錄;非正整數按不傳處理。 |
maxChars |
integer | 6000 |
返回文本的字符預算,上限也是 6000;低於 64 時按 64 渲染。 |
maxChars 限制的是渲染出來的史書文本;API 返回的對象另有 12000 字符的傳輸上限,不會爲了它刪除讀者還有額度容納的回合。
掛載點¶
bundle 默認在 cordis.patch.yml 中插入兩行:
- insert:
- id: session-chronicle
name: 'dsh-session-recall/service'
- id: tool-session-chronicle
name: 'dsh-session-recall/tool'
session-chronicle提供ctx.sessionChronicle服務,供其他插件消費,本身不佔模型請求。tool-session-chronicle註冊模型可調用的session_chronicle工具,每個請求多一個 tool schema。
只想關掉模型工具、保留服務,可在 profile 的 cordis.patch.yml 裏按 id 覆蓋:
- id: tool-session-chronicle
disabled: true
讀工具開關¶
enable-read-tools.mjs 追加的組長如下:
- insert:
- id: optional-session-search
name: cordis:group
group: true
isolate:
sessionQuery: true
config:
- id: optional-session-query-sqlite
name: '@deepseek-ai/dsh-session-query-sqlite'
config:
path: ':memory:'
openAt: first-search
- id: optional-tool-session-query
name: '@deepseek-ai/dsh-tool-session-query'
isolate.sessionQuery 讓這個組擁有獨立的 sessionQuery,profile 裏原有的 sessionQuery 保持自身配置;組內使用 :memory: 索引,且在第一次搜索時纔打開(openAt: first-search)。
代價:這 5 個工具是上游的 opt-in 功能,每個模型請求固定多出 5 個 tool schema 加一段引導文字,即使這一輪根本不搜歷史。不需要跨會話檢索就不要開。
卸載¶
1. 移除插件¶
dsh plugin --profile web remove dsh-session-recall
2. 撤銷讀工具(如果開過)¶
腳本每次追加前都寫了備份,恢復最近一份即可。
PowerShell:
$patch = "$HOME/.dsh/profiles/web/cordis.patch.yml"
$bak = Get-ChildItem "$patch.bak-*" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
Copy-Item $bak.FullName $patch
zsh:
cd ~/.dsh/profiles/web
cp "$(ls -t cordis.patch.yml.bak-* | head -1)" cordis.patch.yml
也可以手工編輯 cordis.patch.yml,刪掉以 # --- dsh-session-recall: ... 開頭的那一段——它下面的 - insert: 裏就是 optional-session-search 組,直到 name: '@deepseek-ai/dsh-tool-session-query' 爲止。
如果不再需要這兩個上游包,順手移除:
dsh plugin --profile web remove @deepseek-ai/dsh-tool-session-query @deepseek-ai/dsh-session-query-sqlite
3. 重啓¶
dsh web
磁盤上剩下什麼¶
cordis.patch.yml.bak-*備份文件(腳本寫的,不會自動清理,可手刪)。- 若跳過了上面的可選移除:profile 的
node_modules、package.json、pnpm-lock.yaml裏仍有那兩個上游包。 - 會話日誌本身:史書不寫任何數據,插件卸載不會刪除或改變
~/.dsh下的會話記錄。 - 插件自己的
node_modules/dsh-session-recall會隨dsh plugin remove一起消失。
排錯¶
| 現象 | 原因 | 處理 |
|---|---|---|
插件裝好了,模型看不到 session_chronicle |
插件在宿主啓動時 import;dsh plugin add 只改 profile,不會熱加載新包 |
完全退出並重啓 dsh web。刷新瀏覽器頁面不算重啓宿主。 |
改了 lib/*.js,行爲沒變 |
Node 的 ESM 模塊緩存按進程生效,宿主還拿着舊模塊 | 重啓宿主。不需要清緩存或重裝。 |
dsh plugin add 超時、403 或卡住 |
dsh plugin 把參數轉發給 pnpm,需要同時訪問 GitHub 與 npm registry;代理或純內網會失敗 |
換到能訪問的網絡重試,或先給 pnpm 配好代理與 registry。 |
| 讀工具已掛載,但模型調不到 | 宿主沒重啓;或兩個包沒裝進 profile;或版本漂移 | 先重啓,再跑 node scripts/check.mjs web。not installed 就重跑 enable-read-tools.mjs;版本不等就重裝。 |
check 報版本不匹配 |
兩個上游包必須與 @deepseek-ai/dsh-base 精確相等。它們與 harness 同批發布,rc 與 rc 之間也可能不兼容,所以檢查用字符串嚴格相等,而不是 semver 範圍 |
重跑 node scripts/enable-read-tools.mjs web,它會按當前 harness 版本重裝。 |
| 新會話裏史書是空的 | 史書只記錄真人開過的回合(source.kind === "user");注入的上下文、工具結果、子 agent 消息都不算。新會話還沒有真人消息時就是 0 條 |
先發一條真人消息;回合進行中會顯示「回合進行中」,結束之後纔有結論。空史書會明確寫「本會話還沒有記錄到帶真實用戶輸入的回合」。 |
本地路徑安裝後報找不到 @deepseek-ai/cordis |
dsh plugin add /abs/path 裝的是 link: 依賴,ESM 跟隨軟鏈到倉庫真實路徑後,解析不到 profile 的 node_modules |
開發時先跑 node scripts/dev-link.mjs;正常安裝請用 github: 地址。 |
scripts/*.sh 在 Windows 報 set: pipefail: invalid option name |
腳本在 Windows 上不應直接執行,應使用同名 .mjs 文件 |
適用場景與注意¶
- 適合需要按會話時間軸回溯上下文、在當前會話內投影歷史事件、或需要調用上游只讀歷史工具的場景。
- 插件以當前 dsh 進程權限運行,安裝前應檢查源碼與許可證。
- 上游工具屬於 opt-in 功能,開啓後每個模型請求固定多出 5 個 tool schema 與一段引導文字,僅在需要跨會話檢索時開啓。
- 史書不寫入任何數據,卸載不會影響
~/.dsh下的會話記錄。