DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-file-history

c

dsh-file-history

Manifest valid

DeepSeek Harness plugin: back up a file before an agent's write/edit overwrites it. Per-project .dsh-backup, file_history restore tool, top-bar status panel, per-project switch.

UI (client)

dsh-file-history

test license

A DeepSeek Harness plugin that backs up a file before an agent's write/edit overwrites it. Per-project .dsh-backup/ (filename + timestamp, last N generations), a file_history tool to list / diff / restore single files or a whole turn, a top-bar panel that shows whether it is alive, and a per-project switch. If a backup cannot be made, the write is refused (fail-closed). 中文说明见下。

DeepSeek Harness 的「改前自动备份」插件:让 agent 改文件这件事从"靠自觉备份"变成"harness 兜底"。

  • 任何 write / edit 覆盖已存在文件之前,自动把原文逐字节备份进项目内的 .dsh-backup/;
  • 备份文件名 = 源文件名 + 时间戳 + 原扩展名,按源文件路径镜像存放;
  • 每个源文件只保留最近 5 轮(maxGenerations,可就地调整),另加天数与容量两层兜底;
  • 备份失败就拦下这次写入(fail-closed),不会出现"没备份却照样改坏";
  • 模型侧有 file_history 工具(list / show / restore / revert_turn),系统提示里也常驻几行说明, agent 知道备份系统的存在、位置与恢复方式;
  • 运行状况标志:.dsh-backup/_dsh-file-history/status.json(时间戳每次备份/还原刷新)。

为什么需要它

harness 原生只有 dsh-atomic-write(写入原子)和 dsh-fs-observation-policy(先读后写)—— 原子不等于可撤销。文件被覆盖或删掉之后,唯一的补救是让模型重读上下文再写一遍: 既烧 token,又可能二次改错。本插件把原文留在工具层,回滚变成一次工具调用(或一次文件复制)。

备份长什么样

<项目根>/.dsh-backup/
├── src/lib/nested.20260917-095500.ts      # 子目录按源路径镜像
├── src/lib/nested.20260917-095500.ts.json # 该备份的元数据
├── demo.20260917-095500.txt
├── demo.20260917-095500.txt.json
└── _dsh-file-history/
    ├── status.json                        # ★ 运行状况标志
    └── manifest.jsonl                     # 快照/还原/回退审计流水

~/.dsh/file-history/<工作区>/<文件签名>/<时间戳>/content   # 仅“项目外文件”的兜底目录

恢复方式三选一:file_history(action="restore", path=...)、file_history(action="revert_turn")(整轮), 或直接把人能看懂的备份文件复制回原位。

目录

文件作用
lib/index.js宿主半边:tools/pre-execute 备份 + file_history 工具 + 系统提示公告 + 保留策略 + 客户端 RPC 路由
lib/client.js客户端半边:右上角「备份」状态芯片 + 悬停面板(实时流水 / 统计 / 总开关)
package.json插件清单(dsh.client 段声明浏览器半边,依赖 @deepseek-ai/cordis、@deepseek-ai/schemastery)
install.ps1安装/卸载到指定 dsh profile(写 node_modules + 登记 cordis.patch.yml,自动备份原文件)
selftest.mjs离线自测:假 ctx 驱动已安装副本,60 项断言(宿主加载路径、schema 契约、客户端 RPC、项目级开关)
host-contract-check.mjs真依赖契约检查:在 profile 内加载真实 schemastery/timer 语义,9 项断言
monitor.ps1命令行观测面板:一次看清 / -Watch 实时盯梢 / -Scan 扫全机
after-restart-check.ps1重启后体检:插件是否已加载、备份目录是否已创建
verify.ps1端到端验证:起一个独立 headless dsh,让真实 agent 改坏再还原
e2e/patch.yml端到端验证用的临时 patch

可视化观测:右上角状态芯片

装上客户端半边后,会话右上角(「时间戳开 / 记忆库开」那排旁边)会多一个备份芯片:

  • 灯色:🟢 最近 2 分钟内有备份 · 🔵 已启用但暂时没动作 · 🔴 有错误(含最近一次失败原因)· ⚪ 读不到状态。
  • 芯片文字:当前占用(现存备份的总大小,会随 5 代清理降下来),不是历史累计次数;悬停提示里另给「份数 / 累计次数」。
  • 点击展开面板:最后活动时间 / 备份次数 / 保留代数 / 占用 · 统计 / 最近一次备份与还原的完整路径 / 实时流水(每 2 秒刷新,格式 时间 · 动作 · 文件名,鼠标悬停看备份文件路径)/ 一键开关。
  • 面板关着时每 30 秒轮询一次(只更新灯色,开销可忽略);开着时每 2 秒。
  • 数据来源与命令行面板完全一致:status.json + manifest.jsonl,通过宿主路由 POST /dsh-file-history/api 读取。
  • 同一个开关也出现在「设置 → 通用」里(与记忆库的入口一致)。

宿主接口契约(踩过坑,务必按这个写)

这两条是 2026-09-17 两次真实加载失败的根因,已写进 host-contract-check.mjs 做回归:

  1. ctx.settings.register(ns, schema, options) 的 schema 必须是 schemastery Schema,不能是工厂函数。 宿主 dsh-settings 的 resolve() 是 schema(mergeLayers(base, section)) —— 把合并后的配置对象 当参数调用 schema。写成 (s) => s.object({...}) 时 s 就是那个普通配置对象, 于是 s.boolean() 不存在 → TypeError: s.boolean is not a function(插件一加载就炸)。 正确写法(与 dsh-memory-db 一致):import s from '@deepseek-ai/schemastery' + s.object({...})。
  2. 用到 ctx.setTimeout / ctx.timeout 就必须 inject: ['tools','settings','timer']。 这些方法由 cordis-plugin-timer 通过 ctx.mixin 混入,没 inject 会报 cannot get property "timer" without inject;另外 ctx.setTimeout 已 deprecated,统一用 ctx.timeout。

安装

方式 A:克隆仓库 + 安装脚本(最直观)

git clone https://github.com/cuteG41cute/dsh-file-history.git
cd dsh-file-history
powershell -ExecutionPolicy Bypass -File install.ps1 -Profile web -Force
# 然后重启 dsh 服务 / 桌面版窗口

方式 B:pnpm 直接装(不落源码)

dsh plugin --profile web add github:cuteG41cute/dsh-file-history
# 然后在 profile 的 cordis.patch.yml 里加:
#   - insert:
#       - id: dsh-file-history
#         name: 'dsh-file-history'
#         inject: [tools, settings, timer, agents]
# 最后重启 dsh 服务

也可以 npm 方式:npm publish 之后 dsh plugin --profile web add dsh-file-history。

重启是必须的:宿主侧 @deepseek-ai/cordis-plugin-hmr 在 dsh-base 里 disabled: true, 改 cordis.patch.yml 不会热加载新插件(客户端插件 HMR 是另一回事);客户端面板还多一步刷新页面。

卸载:powershell -ExecutionPolicy Bypass -File install.ps1 -Remove(已产生的备份不会被删除)。

自测与验证

# 1) 装依赖(只有跑测试需要)
npm install

# 2) 离线自测,秒级,60 项断言(假 ctx)
node selftest.mjs

# 3) 真依赖契约检查(仓库内或已安装目录都能跑;找不到 schemastery 会回退到 DSH profile 里那份)
node host-contract-check.mjs

# 4) 重启后的体检 + 端到端(起独立实例,不动正在运行的 3080 服务)
powershell -ExecutionPolicy Bypass -File after-restart-check.ps1
powershell -ExecutionPolicy Bypass -File verify.ps1

注意:本机 PowerShell 7(pwsh)不在 PATH 上,脚本一律用系统自带的 powershell.exe(Windows PowerShell 5.1)执行。

所有 .ps1 必须带 UTF-8 BOM:Windows PowerShell 5.1 对无 BOM 的脚本按 ANSI(GBK) 解码, 脚本里的中文注释/字符串会变成乱码并直接把语法搞坏(Unexpected token)。 用编辑器保存时选「UTF-8 with BOM」,或命令行补一次:

$f = 'monitor.ps1'
$text = [System.IO.File]::ReadAllText($f, [System.Text.Encoding]::UTF8)
[System.IO.File]::WriteAllText($f, $text, [System.Text.UTF8Encoding]::new($true))

另外:用 Start-Process 传带空格的路径会被参数拆分吃掉一段, 所以 monitor.ps1 支持用环境变量 FH_PROJECT 指定项目目录。

配置(~/.dsh/settings.yaml → file-history 段,改动热生效)

开关是项目级的:enabled 是全局默认,projects 是逐项目覆盖(键=项目目录绝对路径,小写规范化)。 生效值 = 项目覆盖 > 全局默认。右上角面板和「设置 → 通用」里都能直接切当前项目,并能在两种状态间来回。

file-history:
  enabled: true                  # 全局默认开关(没有单独设置过的项目用它)
  projects:                      # 逐项目覆盖:{ "<项目目录>": true | false }
    c:\work\my-proj: false
  maxFileBytes: 2097152          # 超过只记指纹(默认 2MB)
  maxGenerations: 5              # 每个源文件保留最近几代(默认 5 轮)
  maxAgeDays: 30                 # 备份保留天数
  maxProjectBytes: 536870912     # 单个项目备份区容量上限(默认 512MB)
  announceInPrompt: true         # 把备份系统写进系统提示
  gitignoreBackups: true         # 自动把 .dsh-backup/ 加进项目 .gitignore

面板里的三个操作(对应 RPC set-enabled / reset-project):

操作效果
关闭/开启本项目备份写 projects[<当前项目>],只影响这个项目
改为跟随全局默认unset projects[<当前项目>],回到跟随 enabled
全局默认:开/关 → 切换写 enabled,只影响没有单独设置过的项目

关键实现决策

  1. 不改写工具参数:tools/pre-execute 无法改写 exec.arguments,所以不做"挡下写入再由插件代写"—— 那会丢掉 harness 原生的 read-before-write 校验与展示层 diff 卡片。这里只做旁路备份 + 校验,原工具照常执行。
  2. fail-closed:备份读失败/并发修改 → deny 本次写入,并把原因回给模型。
  3. 同轮分组用 rootCallId:一次助手消息里的多次 write/edit 共享 rootCallId,revert_turn 按它成组回退; 同一文件多代时回退到本轮最早那代(即本轮开始时的样子)。
  4. 备份逐字节保存:不做行尾/编码转换,restore 是原样写回。
  5. 代数上限就地执行:每次备份后立刻把该源文件收敛到最近 N 代(不是只靠小时级 sweep),短时间连改也不会堆积。
  6. 自身免疫 + git 卫生:.dsh-backup/ 内的文件不再被备份;从工作区向上找最近的 git 根 (工作区常是仓库的子目录),把带相对路径的条目追加进那个 .gitignore。
  7. 项目外文件不污染无关目录:落到用户主目录的兜底区,由同一个 file_history 工具统一索引。
  8. 按宿主真实契约写:见上文「宿主接口契约」——schema 用 s.object(...) 而不是工厂函数, 定时器用 ctx.timeout 且声明 inject: ['tools','settings','timer']。离线自测只覆盖调用约定, 真依赖语义由 host-contract-check.mjs 在 profile 内保证。

技能与排查

同机已安装配套技能:~/.dsh/skills/dsh-file-history/SKILL.md(含完整行为规则、排障表、file_history 用法)。

Comments

Loading…

Similar plugins

deepseek-harness-rewind

by zoyluoblue

dsh plugin: snapshot your workspace every turn and restore the files to any earlier point. A rewind/undo for DeepSeek Harness coding sessions — your own git repo is never touched.

Manifest valid

★ 0

MIT

TypeScript

Aug 19, 2026

dsh plugin --profile web add @zoytown/dsh-rewind

by Yazzyk

DeepSeek Harness (dsh) 插件:在 Web GUI 里手动点选文件或目录,屏蔽 agent 对它们的读取、搜索、写入与编辑。A dsh plugin that denies an agent read/search/write/edit access to chosen files and directories, picked from the plugin's own We

Security & AuditDevelopment & InfrastructureManifest valid

★ 2

MIT

JavaScript

Oct 10, 2026

dsh plugin --profile web add dsh-file-shield

by jackylong1987

DeepSeek Harness (DSH) web plugin: upload manager, workspace output files with preview/edit/maximize, skill docs browser, account balance, and turn-ruler history navigation.

Manifest valid

★ 0

MIT

JavaScript

Sep 25, 2026

dsh plugin --profile web add dsh-long-plugins

by caishengshuo

Every file, one version before it breaks. A DSH plugin: snapshots a file the instant before an agent rewrites it, with a per-session GUI timeline where any point can be restored in one click.

Terminal & ClientsManifest valid

★ 0

MIT

JavaScript

Oct 24, 2026

dsh plugin --profile web add dsh-beforewrite

by ZSeven-W

DeepSeek Harness (DSH) plugin: a read-only ledger for the plugins you already have installed — a capability inventory with file:line evidence, declared-vs-detected reconciliation, cross-profile versio

Security & AuditManifest valid

★ 25

↓ 101/wk

MIT

JavaScript

Nov 1, 2026

dsh plugin --profile web add @zseven-w/dsh-harbor

by xusuyang030218

DSH (DeepSeek Harness) file preview & editor plugin: in-browser workspace file tree, multi-format preview, online editing, version history, search. DSH 文件预览插件。

UI & ExperienceManifest valid

★ 0

MIT

JavaScript

Aug 24, 2026

dsh plugin --profile web add dsh-preview-ui