dsh-plugin-updater
Safe one-click plugin updater for DeepSeek Harness (dsh): backup, verified update with real boot smoke test, auto-rollback, and a launch-aware restart button. 深度求索 Harness 插件安全一键更新器
- Stars
- 0
- Language
- JavaScript
- Created
- Sep 9, 2026
- Updated
- Sep 9, 2026
Introduction
dsh-plugin-updater
DeepSeek Harness(dsh)插件安全一键更新器:清单、备份、经过验证的更新、失败自动回滚、手动回滚,以及一个懂你启动方式的重启按钮。
目标只有一个 —— 更新永远不把 dsh 搞坏。做不到"更新后一定能启动"的更新,会被自动回滚到更新前。

为什么需要它
dsh 的插件是 profile 目录里的 pnpm 依赖,组合成 dsh.profile.bundles 层叠。直接 pnpm up --latest(或某些市场类插件的"一键更新")有几个经典翻车点:
| 翻车点 | 本插件的对策 |
|---|---|
| pnpm 中途失败,profile 半残 | 更新前先备份 package.json / pnpm-lock.yaml / pnpm-workspace.yaml / cordis.patch.yml 四件套 |
| 更新后从不验证,重启才发现起不来 | 更新后 dsh --dump-config 组合校验 + 在临时端口真实启动一次,看到 dsh web: 才算通过(约 1–2 秒) |
只跑 pnpm 不做 bundles 对账,新版插件丢了 dsh.bundle 声明 | 复刻 dsh plugin 官方 reconcile 规则,层列表与实际安装同步 |
| 校验失败没有退路 | 任何一步失败 → 自动还原备份 → pnpm install --frozen-lockfile → 再校验 → 报告"已回滚" |
--latest 把精确锁定改写 | pnpm add name@版本 分组执行,精确锁定走 --save-exact 保持锁定风格;锁定插件默认不勾选 |
| 动了不该动的核心包 | 只更新第三方依赖;内置 @deepseek-ai/* bundle 不是依赖,天然不受影响 |
功能特性
- 插件清单 — 插件名、当前版本、可升级版本、
已锁定(精确版本)/已弃用/本地依赖徽章,一键刷新(pnpm outdated)。 - 两种更新模式 —
升级到最新版(默认)与仅范围内(不改版本约束);跨大版本时给出醒目提示。 - 一键更新所选 — 勾选、二次确认、实时进度日志、逐插件
旧 → 新结果汇报。 - 自动回滚 + 手动回滚 — 失败自动还原;设置页里任选一个历史备份回滚(保留最近 10 份),回滚同样经过校验。
- 懂启动方式的重启按钮 — 自动检测 dsh 的启动方式:
- systemd 用户服务(如
dsh-web.service)→systemctl --user restart,由 systemd 监护停止与拉起,无端口竞态; - 前台 / nohup / tmux 启动 → 分离的重新拉起器:等旧进程优雅退出后,以相同 argv / cwd / env 重新执行;
- 重启期间页面断连属预期,服务恢复后设置页自动刷新。
- systemd 用户服务(如
- 操作历史 — 每次更新/回滚的结果落在
<profile>/.dsh-plugin-updater/history.jsonl,设置页可见。 - 命令行恢复通道 — dsh 起不来时
bin/dpu.mjs照常可用。
安装
以 web profile 为例(dsh ≥ 0.1.0-rc.5,Node ≥ 20):
# 方式一:直接从 GitHub 安装
dsh plugin --profile web add github:dp419936514/dsh-plugin-updater
# 方式二:clone 后以本地路径安装(便于自行修改)
git clone https://github.com/dp419936514/dsh-plugin-updater ~/.dsh/plugins/dsh-plugin-updater
dsh plugin --profile web add ~/.dsh/plugins/dsh-plugin-updater
重启 dsh web 后,设置页出现「插件更新」分区。卸载:dsh plugin --profile web remove dsh-plugin-updater。
方式二以
link:依赖安装,改源码后重跑一次add(或在该 profile 目录pnpm install)并重启即可生效;从 GitHub 更新本插件自身:重跑方式一的add命令。
使用
设置页
设置 → 插件更新:
- 打开即自动读取清单;也可点右上「刷新清单」;
- 勾选要更新的插件(精确锁定的默认不勾,标
已锁定),选模式; - 「一键更新所选」→ 二次确认 → 看进度日志(pnpm 输出、组合校验、启动冒烟逐条可见);
- 成功后点「重启 dsh」生效;失败则已自动回滚,日志里写明原因;
- 需要时在回滚区选任意备份一键回滚。
命令行(dsh 起不来时的恢复通道)
cd ~/.dsh/plugins/dsh-plugin-updater # 或 clone 目录
node bin/dpu.mjs check # 清单与可更新项(默认 profile 自动检测)
node bin/dpu.mjs update --yes # 升级所有可升级插件(精确锁定的跳过)
node bin/dpu.mjs update --targets dsh-cost-meter --yes # 只更一个(含锁定插件)
node bin/dpu.mjs rollback # 回滚到最新备份
node bin/dpu.mjs backups # 备份列表与操作历史
node bin/dpu.mjs restart [--unit dsh-web.service] --yes # 重启 systemd 用户服务
行配置(可选)
在 profile 的 cordis.patch.yml 里覆盖:
- id: plugin-updater
config:
profile: web # 管理哪个 profile(默认自动检测本插件所在 profile)
bootVerify: true # 更新后是否真实启动冒烟(默认开;关掉只剩组合校验)
环境变量:DPU_RESTART_MODE=self|systemd 与 DPU_RESTART_UNIT=<name> 可强制重启方式。
工作原理
lib/engine.js 纯 Node 管线:清单/备份/分组 pnpm add/bundles 对账/双重校验/回滚/历史
lib/index.js 宿主半:webServer 前缀路由 /plugin-updater/api(loopback+同源栏,与 /api 网关同款)
lib/client.js 浏览器半:lazy-CJS 工厂格式,注册「插件更新」设置分区
bin/dpu.mjs CLI 恢复通道
校验两段式:--dump-config 抓组合层错误(缺包/坏 patch/配置 schema);--port 0 --no-open 冒烟抓激活错误(行未激活、服务冲突、client bundle 缺失);非 web profile(静默启动)则用"存活即通过"的探活窗口。
FAQ
Q: 和直接 pnpm up --latest 有什么本质区别?
A: 备份、锁定风格保持、bundles 对账、双重校验、失败自动回滚。pnpm up 只负责把文件改掉,后面的五件事它都不做 —— 而翻车恰恰都在这五件里。
Q: 更新过程中途断电/被杀怎么办?
A: 备份目录(<profile>/.dsh-plugin-updater/backups/<时间戳>/)里躺着四件套,node bin/dpu.mjs rollback 一条命令还原 + 冻结锁重装 + 校验。
Q: 为什么更新完要重启? A: 运行中的 dsh 已把旧版本加载进内存;新版在重启后生效。设置页的「重启 dsh」按钮会按检测到的启动方式(systemd / 自重启)替你完成。
English
A safe one-click plugin updater for DeepSeek Harness (dsh) profiles. Before touching anything it backs up the four files an update can affect; after updating it reconciles dsh.profile.bundles exactly like dsh plugin does, then verifies the profile twice — once via --dump-config composition, once by really booting it on an ephemeral port and watching for the dsh web: URL line. Any failure triggers automatic rollback (restore + frozen-lockfile reinstall + re-verification). Exact version pins are preserved (--save-exact), pinned plugins are opt-in, in-box @deepseek-ai/* bundles are never touched. Ships a settings-section UI, a launch-context-aware restart button (systemd user unit or detached self-relaunch), and a CLI (bin/dpu.mjs) usable as a recovery channel when a profile no longer boots.