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 对话当成可撤销的多轮编辑会话来用。

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

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

Xiaoye