DeepSeek Harness 會話整理插件:可恢復刪除與分叉編輯

前言

DeepSeek Harness(DSH)目前對會話的操作只有「歸檔」:歸檔只是把會話 id 記進 archivedSessionIds,日誌目錄原封不動。這就帶來兩個問題:一是真正的刪除能力缺失,二是已經發出的請求無法修改。

tazewell/dsh-session-tidy 插件補上了這兩點:把會話移入可恢復的 7 天回收站,以及通過 fork 分支的方式修改已經發送的請求。

插件簡介

tazewell/dsh-session-tidy 是一個 DSH 工作流插件,提供兩個核心能力:

  • 可恢復刪除:刪除會話時,文件移動到 ~/.dsh/session-trash/entries/<時間戳>-<會話 id>/,7 天內可恢復,過期後惰性清理。
  • 分叉編輯:在任意一條用戶消息上點擊鉛筆圖標,修改後 fork 一個分支會話,原會話根據選項移入回收站或保留。

安裝

插件包名爲 dsh-session-tidy,版本 1.0.0。

插件管理器(推薦):使用插件管理器的 install_bundle 指向包目錄(或解壓後的目錄),或在插件市場裏按包名安裝。管理器會負責 profile 的 package.json、cordis.patch.yml 與依賴。

手動登記:在 ~/.dsh/profiles/<profile>/package.json 裏添加:

"dependencies": { "dsh-session-tidy": "^1.0.0" },
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-session-tidy"] } }

然後在 profile 目錄安裝依賴並重啓 DSH。

會話刪除與恢復

側邊欄每個會話的懸浮操作區和「…」菜單各有一個刪除入口。

  1. 點擊刪除 → 確認對話框顯示會話標題。
  2. 確認後 Host 先停止該會話正在跑的任務(子代理、後臺命令、定時提醒),再把它移入回收站,並清掉投影緩存。
  3. 側邊欄底部的垃圾桶按鈕打開回收站,可以:
    - 恢復:文件回到原來的會話目錄、重新掛回原工作區、解除歸檔;
    - 徹底刪除:立即刪掉回收站裏的目錄,不可恢復;
    - 清空回收站:刪除全部記錄(會二次確認)。

當前正在主視圖打開的會話不能刪除:對話框會提示先切換到其他會話。

存儲位置與保留期

~/.dsh/session-trash/entries/<時間戳>-<會話 id>/
  meta.json      # id、標題、原工作區、刪除時間、字節數
  session/       # 原來的會話目錄

回收站保留 7 天,過期條目在下次打開回收站時惰性清理。

安全機制

  • 刪除只發生在 ~/.dsh 內,路徑會做目錄逃逸校驗。
  • 接口只接受本機迴環調用、同源請求並帶 x-dsh-plugin: session-tidy 頭,杜絕任意網頁或局域網客戶端調用。

修改已經發送的請求

每條用戶消息下面(時間、複製按鈕那一行)都多了一個鉛筆圖標:鼠標移到那條消息上纔會顯現,點它就改這條請求——不必是最後一條。

  1. 點擊某條消息的鉛筆 → 對話框「修改這條請求」裏就顯示這條請求的原文,可以直接改。
  2. 確認後插件在該請求之前 fork 出一個分支會話,把改好的內容寫進新會話的輸入框草稿,並自動切過去。分支的歷史正好停在「這條請求之前」,所以這條提問和它後面(以及它自己的半截回答)都不會帶過去。
  3. 在分支裏看過沒問題就回車發送。

切點規則

切點取的是上一條已完成 turn 的結尾(turn/end 的 seq),不是「消息 seq − 1」:用戶消息前面還有它自己那條 turn 的 turn/start、step/start,按 seq − 1 切會讓宿主給這個空 turn 補一個「forked」結束,界面上就會多出一行沒有內容的「已完成,用時 1 秒」。規則還會跳過這種空 turn(兩條 turn-tail 相鄰),所以之前編輯留下的空殼會在下一次編輯時一起丟掉。

原會話處理

對話框裏有一個默認勾選的選項「把原會話移入回收站(7 天內可恢復)」:

  • 勾選(默認):分支沿用原會話的標題,原會話進回收站,側邊欄裏看起來就是「同一個會話被改掉了」;想找回來隨時去回收站恢復。
  • 取消勾選:原會話保留,分支標題加 (1) 後綴,兩個會話並存,可以對照。

如果原會話移入回收站失敗(比如文件一時被佔用),分支照常保留並提示原因,不會因爲回收失敗把已建好的分支丟掉。

爲什麼 fork

DSH 目前沒有「原地截斷會話日誌」的能力(只能歸檔、不能回退),fork 是唯一能「替換掉這條請求」又不丟歷史的方式。

限制

  • 只能取回文本:附件、@ 引用的 chip 不會跟着過去(正文會保留)。
  • 會話正在跑的時候鉛筆置灰(先停止,再編輯);沒有可編輯文本(比如只發了圖片)的消息不顯示。
  • 改的是較早的消息時,那條消息之後的對話只存在於原會話裏——所以默認把原會話放進回收站,取消勾選就能兩邊都留着。
  • 草稿是寫給分支會話的,取消編輯不會污染當前會話的草稿。
  • 分支和原會話共享同一條前綴歷史,所以上下文是連續的。

結構說明

  • index.js — Host 入口:解析 DSH home、註冊 /plugin/session-tidy 前綴路由,刪除前調用 workspaceRegistry.archiveSession(id, { stopActivity: true }),恢復後重新 attachSession 並 unarchiveSession。
  • lib/trash.js — 回收站存儲:移動(跨盤迴退到複製+刪除)、meta、恢復、清理、過期。
  • lib/routes.js — HTTP 層:GET trash、POST delete|restore|purge|empty,含同源與請求頭校驗。
  • client.js — 瀏覽器側:會話行刪除按鈕、菜單項、側邊欄底部回收站入口、每條用戶消息的懸停鉛筆(注入到官方氣泡操作行)、確認框 / 回收站對話框 / Toast(全部使用 --dsw-alias-* 主題變量,跟隨明暗主題)。
  • cordis.patch.yml — bundle patch,插入 session-tidy 這一行。

測試與驗證

運行測試:

node --test "test/*.test.mjs"

38 個用例覆蓋回收站存儲、HTTP 路由(迴環/同源校驗、回滾、錯誤碼)、Host 註冊,Client 的插槽註冊與詞典完整性,以及消息鉛筆的注入 / 禁用 / 取值、彈窗內直接編輯、空內容禁用確認、fork 切點(上一條 turn/end、跳過空 turn)、草稿寫入(寫入的是改後文本)、原會話入回收站與失敗提示。

已安裝到 desktop profile 並現場確認 /plugin/session-tidy/trash 返回 {"ok":true,"entries":[]},說明 Host 半已生效;瀏覽器內的最終視覺呈現需要在實際頁面裏確認。

適用場景

適合需要頻繁清理會話、或者需要修改已發送請求的 DSH 用戶。插件以當前 dsh 進程權限運行,安裝前應檢查源碼與許可證(MIT)。

後續計劃

  • 空會話 / 空分支批量清理
  • 分支血緣標記與「回到原會話」
  • 編輯時帶上附件與 @ 引用
  • 批量清理面板(按工作區篩選、按大小排序、批量刪除)
  • 導出會話、存儲佔用統計

目錄

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

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

小夜