dsh-checkpoints:爲 DeepSeek Harness 提供按輪次持久化的工作區檢查點與可預覽回滾

前言

在 DeepSeek Harness(DSH)裏用 Web UI 讓模型改代碼時,常見情況是:某一輪改錯了,你希望只撤回這一輪,或者把工作區恢復到更早某一輪結束時的樣子,並且先看 diff 再決定是否寫回磁盤。

DSH 自帶的 @deepseek-ai/dsh-workspace-changes 會記錄一輪裏改了哪些文件並展示 diff,但快照放在 Session 的臨時目錄裏,Session 或 Host 結束就沒了,也沒有回滾能力。dsh-checkpoints 在此基礎上增加影子 git 倉庫(重啓後仍在)和可按文件勾選、帶預覽的回滾,行爲上接近 Cursor 的檢查點體驗。

下面介紹這個由 tower666 維護、歸類爲工作流的 bundle 插件如何安裝、能做什麼,以及使用時需要注意的安全邊界。

這是什麼

dsh-checkpoints(npm 包名同名,當前資料中的版本爲 1.1.0,MIT 許可證)是面向 DSH Web 平臺的 bundle:安裝後會寫入 profile,Host 重啓後加載。

它在 Harness 主目錄下維護與真實工作區隔離的 shadow git 倉庫,在每一輪對話的 turn/start 與 turn/end 各拍一次快照,並把該輪變更文件列表記入目錄旁的 catalog;Web 頁在每個已完成輪次下展示一行操作入口,同時暴露 /api/checkpoints.* 接口,並把同等能力以 workspace_checkpoint 工具交給模型(寫盤前走 DSH 審批)。

與 workspace-changes 的差別

能力 dsh-workspace-changes(官方插件) dsh-checkpoints
記錄每輪 diff 有 有(並持久化)
快照存放 Session 臨時目錄 $DSH_HOME/workspace-checkpoints
重啓後保留 否 是
回滾 / 撤銷 無 有,支持預覽與按文件勾選

升級 bundle 時 README 寫明尚無自動升級路徑:需先移除再安裝新版本;但 $DSH_HOME/workspace-checkpoints 下的檢查點在移除與重裝後仍會保留,對話側歷史可繼續用。

核心功能

快照與目錄

  • 在 turn/start、turn/end 把工作區快照寫入 shadow 倉庫,並把該輪變更文件列表寫入 catalog。
  • 默認存儲目錄爲 $DSH_HOME/workspace-checkpoints(可通過 mount 配置 storeDir 覆蓋)。

Web UI 上每個輪次一行

最新一輪與更早輪次提供的動作不同:

最新一輪    ⟲ N files changed in this turn   [Undo this turn's changes…]
更早輪次    ⟲ N files changed in this turn   [Revert to this turn…]
輪次位置 動作 基線 文件列表
最新 Undo this turn’s changes 本輪開始時的內容 僅本輪改過的文件
更早 Revert to this turn 該輪結束時的工作區 該輪結束與當前之間所有有差異的路徑

說明:歷史輪次行不提供「只撤銷某一輪、卻保留其後各輪改動」;在歷史位置上的語義是「回到這裏」。最新輪沒有「之後的輪次」,因此只提供撤銷本輪。

對話框會列出文件與行數、按需加載 unified diff 預覽、支持全選/全不選,只寫勾選中的文件。基線中不存在的路徑會標爲將刪除;超過大小限制的快照標爲不可回滾(not revertable)。應用後還可撤銷本次回滾本身。

兩類回滾語義

  1. Undo this turn’s changes:把本輪動過的文件恢復爲本輪開始時的內容;本輪未碰的文件不動。
  2. Revert to this turn:讓整個工作區等同該輪結束時的狀態;保留該輪及之前的改動,丟棄之後所有輪的改動。最新輪不顯示此項。

執行寫盤前,當前將被覆蓋的狀態會先被快照,因此上述操作本身也可以再 undo。

HTTP API

路由掛在 ctx.connection.fetch 下、位於 /api 內,受 Connection 鑑權,返回 no-cache JSON:

路由 方法 用途
/api/checkpoints.turns?sessionId= GET 某 Session 的全部已記錄輪次
/api/checkpoints.plan POST 生成回滾預覽(body:{sessionId, turn, side?, paths?};side: 'start' 默認表示撤銷該輪自身改動,side: 'end' 表示回到該輪結束態)
/api/checkpoints.diff?planId=&path= GET 某預覽 plan 下單文件的 unified diff
/api/checkpoints.restore POST 應用預覽({planId})
/api/checkpoints.undo POST 撤銷已應用的回滾({undoId})

回滾分兩階段:plan 只讀;返回的 planId 一次性有效,並在 planTtlMs(默認 600000 ms)後過期。若在預覽打開期間任一計劃內文件被改動,restore 會拒絕。路徑相對錄製的工作區根解析,絕對路徑或越界路徑會被拒絕。

模型工具

對外暴露 workspace_checkpoint 工具,寫操作經 ctx.approval.request(),由 Session 審批策略決定;'unavailable' 時失敗關閉。審批服務要求處於 open turn,Web 側則由對話框完成預覽與確認。

安裝與啓用

該包是 bundle:安裝即選中 profile,正在運行的 Host 需重啓一次後纔會加載。

從 npm(推薦)

dsh plugin --profile web add dsh-checkpoints

也可在 Web UI 的 Plugins → Add 填入包名,或通過 Creator 預設裏 plugin_manager 的 install_bundle,target 填 dsh-checkpoints。npm 包頁:https://www.npmjs.com/package/dsh-checkpoints。

從 git 指定版本

dsh plugin --profile web add git+https://github.com/tower666/dsh-checkpoints.git#v1.1.0

將上述 spec 作爲 install_bundle 的 target 亦可;需要不可變來源時可用 commit SHA 替代 tag。

從本地目錄

install_bundle 的 target 指向本倉庫絕對路徑。

運行環境

package.json 要求 dsh 引擎 ^0.2.1-rc.3、node >=20。

配置(Mount)

在 profile 中掛載示例:

- name: 'dsh-checkpoints'
  config:
    maxFileBytes: 2097152
字段 默認值 含義
storeDir $DSH_HOME/workspace-checkpoints shadow 倉庫與 catalog 目錄
timeoutMs 30000 單次 git 命令超時(毫秒)
outputMaxBytes 8388608 單次 git 輸出保留上限(字節)
maxFileBytes 2097152 回滾寫盤與 diff 的單文件快照上限;更大則 unsupported: oversized
maxDiffBytes 524288 單次預覽 unified diff 文本上限
maxTurnsPerSession 300 每 Session catalog 保留輪次上限,超出則丟棄最舊
planTtlMs 600000 未應用的預覽 plan 有效時長

bundle 刻意未聲明 Config schema:從工作區目錄安裝時無法依賴 Host 自帶的 schema 庫,非法配置會回落到上表默認值而非阻止激活。

安全模型(使用前宜知曉)

  • 不寫入用戶倉庫:快照命令的 GIT_DIR 指向 shadow 倉庫;用戶 .git 僅通過只讀 GIT_ALTERNATE_OBJECT_DIRECTORIES 掛接對象庫。集成測試對宿主 .git 樹做前後哈希比對。
  • 使用空的 GIT_CONFIG_GLOBAL,並設置 core.autocrlf=false、core.safecrlf=false,避免全局 git 配置改變字節級一致性。
  • 工作目錄即使不在任何 git 倉庫內,仍可建檢查點;shadow 倉庫自包含。
  • 大於 maxFileBytes 的 blob 會列出但不參與寫回。

插件以當前 DSH 進程權限運行;安裝前請自行審閱源碼與許可證(MIT),並在生產工作區先小範圍試用回滾流程。

存儲佈局(簡要)

$DSH_HOME/workspace-checkpoints/
  catalog.json                 # session → turn → {beforeTree, afterTree, files}
  empty-gitconfig
  repos/<sha1(workspace)>/     # 每個工作區一個 shadow 倉庫
    .git/
    index
    ...

適用場景

  • 在 DSH Web 上長對話改代碼,需要跨 Host 重啓仍能查看歷史輪次變更並回滾。
  • 希望先預覽 diff、再按文件勾選寫盤,而不是整目錄盲目還原。
  • 需要把檢查點能力以 API 或 workspace_checkpoint 工具納入自動化,並接受 DSH 審批門禁。

不宜期待:在不回到某一歷史結束態的前提下,單獨「摘掉」中間某一舊輪而保留其後改動——當前 UI 行動作不支持這種語義。

結尾

dsh-checkpoints 用持久 shadow git 與 catalog,補上了 DSH 原生 workspace-changes 在生命週期與回滾上的缺口;配合預覽、plan/restore 兩階段與對用戶倉庫的只讀隔離,適合把 Web 對話當成可撤銷的多輪編輯會話來用。

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

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

小夜