前言¶
在本地調試或長時間運行 DSH(DeepSeek Harness)時,側邊欄的會話列表會逐漸積累大量廢棄會話。只刪磁盤上的 session*.jsonl 文件,內存裏還保留着進程內的會話條目和 Agent 引用,導致列表裏仍然出現這條記錄,點進去還能讀到內存內容。此外,投影緩存、工作區記賬與全文索引裏的殘留也會一直存在。dsh-session-purge 插件通過右鍵菜單提供了一套完整的清理流程,刪除時會話目錄、投影緩存、工作區記賬、進程內會話條目與 Agent 引用,以及全文索引,確保隻影響目標會話。
插件定位¶
devve-1/dsh-session-purge 是 DeepSeek Harness 的客戶端插件,由維護者 DEVVE-1 開發。它通過側邊欄右鍵菜單提供“刪除會話”入口,二次確認後清理該會話的所有持久化痕跡,同時保證其他會話不受影響。
核心功能¶
刪除範圍¶
刪除操作覆蓋以下位置:
- 會話目錄:
$DSH_HOME/sessions/<project>/<sessionId>/,包括所有代際的session*.jsonl[.zstd],目錄刪空後順帶回收空掉的 project 目錄。 - 投影緩存:
$DSH_HOME/storages/session_projcache/sessions/<sessionId>.json,先走 storageDomain 的內存表寫鏈,再兜底刪除文件。 - 工作區記賬:
$DSH_HOME/storages/workspace.json中該會話在sessionIds、pinnedSessionIds、archivedSessionIds裏的全部引用。 - 進程內狀態:
ctx.sessions與ctx.agents中的活條目,觸發session/disposed事件,客戶端會話列表同步移除該行。 - 全文索引:主動觸發一次索引對賬,讓該會話的 FTS 記錄立刻消失。
附件($DSH_HOME/attachments)與派生圖片緩存($DSH_HOME/cache)是多會話共享的,不會清理。
安全邊界¶
- 會話 id 先過正則
^[A-Za-z0-9][A-Za-z0-9._-]*$(長度 ≤ 200),再映射成單個路徑段;刪除前斷言目標確實是會話根目錄下以該 id 命名的一級目錄,杜絕路徑穿越。 - 不以“運行時還持有這個 Agent”爲拒絕條件。DSH 的 Agent 註冊表會把進程內打開過的會話一直持有着,真正該攔的是“有東西在跑”,由
workspace/session-activity報出。 - 會話有在跑的工作(turn / job / subagent / schedule):確認後走和歸檔同一條
workspace/session-stop通道,然後輪詢等待清空(默認最多 4s,可用settleMs調),停不乾淨就報session-active且不動任何文件。 - 刪除前先把活會話摘掉。會話列表是把進程內還活着的會話無條件並進來的,只刪磁盤的話列表裏會一直留着這一行、點開還能看到內存裏的內容。摘掉之後
session/disposed會發出去,客戶端自行去掉那一行,jsonl 後端關掉寫句柄。 - 摘活會話會讓寫句柄異步收尾(
writer.close()把緩衝落一次盤),所以刪完文件後進行自適應複查:默認每 40ms 探一次會話目錄,連續兩輪乾淨才收工(從沒摘過活會話的只要一輪),總預算residualBudgetMs(默認 1.5s)兜底,清掉的都記進residualPaths。 - 搜索索引對賬給
searchBudgetMs(默認 800ms)的同步預算:冷索引第一次對賬可能要讀一遍全部會話日誌,超預算就中止並把對賬丟到後臺繼續,響應不等它。索引本來就在每次查詢前自行對齊,所以延遲清掉不會讓被刪內容被搜出來。 - 被刪的 id 進一個進程內墓碑集合,並掛一條
agent/pre-step攔門(形狀同歸檔會話的 gate),遲到的投遞只會以blocked收場。 - HTTP 接口只在 webServer 上註冊一條 exact 路由
/session-purge,並要求:POST+application/json+Host必須是迴環地址(localhost/127.x/::1)+Origin與Host同源 +Sec-Fetch-Site不能是cross-site。不設置任何 CORS 頭。
接口¶
POST /session-purge
content-type: application/json
{ "sessionId": "session-...", "stop": true }
200 { "ok": true, "result": { sessionId, removedPaths, residualPaths, projectionCache,
detachedWorkspaces, detachedLive, searchReconciled,
activityStopped, liveAgent, elapsedMs } }
409 { "ok": false, "code": "session-active", "message": "...", "activity": [...] }
400 / 403 / 405 / 413 / 415 / 500 其餘校驗失敗
searchReconciled 取 done(索引已對完賬)/ background(超預算轉後臺)/ unavailable(索引不可用或被關閉)。elapsedMs 是這次刪除在 Host 側的實際耗時。
安裝與啓用¶
插件包已經是一個可直接加載的 bundle(package.json 的 dsh.bundle.patch + dsh.client),Host 半邊 lib/index.js、瀏覽器半邊 lib/client.js 都是最終產物,無需構建。
通過 plugin_manager 安裝¶
從 GitHub 倉庫裝(plugin_manager 的 install_bundle 支持 git 地址):
install_bundle target = https://github.com/DEVVE-1/dsh-session-purge
本地目錄裝(target 填本目錄的絕對路徑):
install_bundle target = <本目錄絕對路徑>
通過本地腳本安裝¶
進入插件目錄,用運行時自帶的 pnpm 把本目錄作爲 file: 依賴裝進 profile:
cd <本目錄>
$node = "$env:DSH_HOME\dsh-runtimes\dsh-primary-runtime\dependencies\node\bin\node.exe"
& $node .\install.mjs --dry-run
& $node .\install.mjs # 默認 desktop profile,可加 --profile <name>
腳本會:用 pnpm 把包名追加到 dsh.profile.bundles → 按哈希把包內容同步進安裝目錄 → 複查。它要寫 profile 目錄(在 DSH 工作區之外),所以只能由你自己執行。
手動安裝¶
cd $env:DSH_HOME\profiles\desktop
pnpm add file:<本目錄絕對路徑>
然後把包名加進 profile package.json 的 dsh.profile.bundles:
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"session-purge"
]
}
}
Live profile 會即時 recompose;否則重啓應用。裝好後刷新一次頁面,瀏覽器半邊纔會進入模塊表。
典型用法¶
安裝完成後,在左側邊欄右鍵點擊某個會話,菜單裏會出現「刪除會話」選項。點擊後彈出二次確認框,確認後執行刪除。該會話及其所有痕跡會被清理,其他會話保持不變。
適用場景與注意¶
- 適合需要頻繁清理廢棄會話的 DSH 本地開發場景。
- 插件以當前 DSH 進程權限運行,安裝前建議檢查源碼與許可證。
- 插件依賴內部形狀(
store+detachEntered),上游改結構時會靜默降級而不是報錯。 - 刪除時如果會話有在跑的工作,會先嚐試停止,停不乾淨則拒刪並返回
session-active。
結尾¶
dsh-session-purge 通過側邊欄右鍵菜單提供了一套完整的會話清理流程,確保刪除會話時所有持久化痕跡都被清乾淨,不影響其他會話。如需查看源碼或更新版本,可訪問插件目錄或 GitHub 倉庫。