dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DSH 配置快照与回滚:危险操作前自动留痕,附带独立还原脚本,DSH 起不来时也能救回。仅 Windows;还原脚本为 .bat,需 Node.js。
DSH 配置的快照与回滚。自动留痕、出问题能查、坏了能退回。
保证 DSH 本体能启动、能输入输出、功能正常。 不管会话聊天内容和用户自己装的插件(那些不在快照范围内)。
DSH 的三次真实事故(2026-10-13 循环依赖、2026-10-17 两次崩溃)都是配置文件被改坏:
事故 · 形态 · 本插件能救吗 10-13 · cordis.patch.yml 抄错,形成循环依赖 · ✅ 能 10-17 · 插件缺 exports["./client"] · ✅ 能 10-17 · patch 被截断成 828 B · ✅ 能(已实测)
实测数据(2026-10-19):
破坏后:bundles 12 → 3,patch 60712 B → 828 B
DSH 启动失败:YAMLException,输出 2,247 B
回滚后:5/5 文件 SHA256 全部恢复
DSH 启动正常,输出 83,254 B,零错误只有 5 个配置文件(共约 119 KB):
pnpm-workspace.yaml
compatibility.json
pnpm-lock.yaml
package.json
cordis.patch.yml ← 热重载的,回滚时最后写明确不碰:node_modules/、插件源码、会话记录、cordis.yml(每次启动被重写)、$DSH_HOME/cordis.patch.yml(home 层,只检测不修)。
类型 · 何时建 · 保留 · 计入 50 配额 每日 daily/ · 每天第一次启动 · 3 份 · ❌ 独立 滚动 rolling/ · 每轮对话结束 + 距上次 ≥2h + 内容变了 · 3 份 · ❌ 独立 手动/回滚前/装插件前后 checkpoints/ · 用户点按钮 / 回滚前 / 装插件前后自动 · 50 份 · ✅
保留 3 份每日的理由:每天的 daily 是在「启动成功」后才建的。 如果今天启动就崩了,今天的快照根本没建成 —— 只能靠昨天、前天的兜底。
这是最实用的功能:不管用户装什么插件,装前装后各存一份。
DSH 的 dsh-plugin-manager 有两个事件,时序如下(源码已核实):
用户点「安装插件」
↓
this.change(async (result) => {
const files = await this.readRestoredFiles() ← DSH 自己也在备份
announce("installing", {...}) ← ★ 磁盘还干净!我在这里存「装前」
run = await this.runPnpm(["add", spec]) ← 真正改磁盘
announce("applying")
})
emit("plugin-manager/changed") ← 全部完成,我在这里存「装后」+ 体检事件 · 时机 · 我做什么 `plugin-manager/install-state`(phase=installing) · pnpm add 之前 · 存 「装插件前 HH:mm」 `plugin-manager/changed` · 安装完成后 · 存 「安装插件后 HH:mm」 + 立刻体检
📅 每日快照 2026-10-19
📌 装插件前 2026-10-19 19:55 ← 装之前,磁盘干净的状态
📌 安装插件后 2026-10-19 19:55 ← 装之后,可能已经坏了装完发现 DSH 起不来 → 一键回滚到「装插件前」→ 精确恢复。
installing,用 requestId 去重装插件前 …19:55②)设置 → 「FK回滚设置」
双击 还原DSH配置.bat —— 不依赖 DSH,只依赖 node.exe。
脚本内置 5 级 node 探测链(本机 PATH 里没有 node):
1. $DSH_HOME/dsh-runtimes/*/dependencies/node/bin/node.exe
2. 盘符根目录扫描(找 resources/runtime/primary-runtime/...)
3. 注册表反查安装路径
4. PATH 里的 node
5. 询问用户输入找不到就退出,绝不修改任何文件。
DSH 是 Electron 桌面应用,`F5` / `Ctrl+R` 不会重新加载页面。 (那是浏览器行为;Electron 在这里没注册 reload 快捷键。)
你想做的事 · 正确做法 让回滚后的配置生效 · 点面板里的「立即重启 DSH」按钮,或关掉窗口重开 让插件面板的代码改动生效 · 同样是重启 DSH 只是想刷新面板数据 · 点面板里的「刷新」按钮(不需要重启)
本插件的面板里,所有需要「重启才生效」的操作都会明确告诉你,并提供「立即重启」按钮。
v1.3.0 起:重启能力已内置,不需要额外安装任何重启插件。
实现见lib/restart.mjs(WMI 创建助手 →taskkill /T杀进程树 → 自动重开)。
自动重启只在 Windows 桌面版 DSH 下可用(需要 Electron 的 IPC 通道)。
命令行启动的 dsh web、或其他平台,按钮会明确提示「请手动重启」并说明原因。node dsh-rollback.mjs <命令> [选项]⚠️ 如果你的 PATH 里没有 node,可以用 DSH 自带的运行时(路径随安装位置不同):
<DSH安装目录>\resources\runtime\primary-runtime\dependencies\node\bin\node.exe不确定的话,直接双击同目录下的 还原DSH配置.bat —— 它会自动探测 node 和 DSH 目录。
命令 · 作用 list · 列出快照(按类型分组) show · 快照详情 status · 当前状态摘要 check · 静态体检(--json / --home-layer) diagnose · 诊断(含 home 层排查顺序) snapshot · 手动创建(--name / --note / --daily) restore · 还原到指定快照 restore --last-good · 自动选最佳 restore --dry-run · 只显示会改什么 trace [文件] · 改动溯源(--days N) sessions · 列出最近会话 prune · 清理过期快照 oplog · 查看操作日志
退出码:0 成功 · 4 无可用快照 · 5 权限/占用 · 7 需人工 · 8 部分成功
快照的可靠性分 5 级。按「配置指纹」记录启动历史(不是按快照对象,这样内容相同的快照共享验证):
等级 · 判据 verified-strong · 同指纹启动成功 ≥3 次且 0 失败 verified · 同指纹启动成功 ≥1 次 static-ok · 静态体检通过,但从未被启动验证 failed · 曾启动失败 broken · 静态体检有 fatal
--last-good 按这个顺序降级选点:verified-strong → verified → static-ok → failed。
$DSH_HOME\cordis.patch.yml(home 层,实测 132 B,由第三方插件 dsh-skin 自动生成) 叠加在 profile 层之后,优先级更高。它坏了 DSH 起不来,而:
本插件能检测(home-layer-unparsable fatal),但不修。
所以:profile 层体检全绿但 DSH 起不来时,第一件事查这个文件。
node dsh-rollback.mjs check --home-layer红线 · 原因 绝不自动回滚 · 会掩盖真问题 不改 DSH 本体 · 更新即失效 不碰 node_modules · pnpm 的领地 会话日志绝对只读 · 那是用户的核心数据 回滚前必须先快照 · 防点错 两阶段写入 + 固定顺序 · patch 最后写,避免中间态触发热重载 apply() 全包 try/catch · 本插件出问题不能拖垮 DSH session/event 带 { global: true } · 否则收不到别的会话的事件 异常绝不冒泡 · 不能因为体检打断用户对话
验收标准:故意破坏 lib/client.js、entry.js,或直接删掉本插件 → DSH 仍能正常启动。
dsh-data/plugin-src/dsh-fk-rollback/
├── package.json 插件清单(exports 含 ./client)
├── cordis.patch.yml bundle patch(name 必须等于包名)
├── entry.js Host 半边(钩子 + HTTP 端点)
├── lib/
│ ├── core.mjs 快照/还原/指纹/保留
│ ├── check.mjs 体检(自实现 YAML 子集)
│ ├── trace.mjs 会话溯源(只读)
│ └── client.js Client 半边(设置面板)
├── dsh-rollback.mjs 命令行脚本(零第三方依赖)
├── 还原DSH配置.bat 一键还原(5 级 node 探测)
└── README.md快照存放:$DSH_HOME/rollback-snapshots// (在 profile 外面 —— profile 内会跟着一起坏)
node:fs/path/crypto/zlibcordis.patch.yml 里有 !!js 自定义标签,完整解析器反而要额外注册 tag)@deepseek-ai/* 这类 install-scope 包在 profiles/node_modules(共享层),不在 profile 层;那层里可能有指向 DSH 安装目录的悬空符号链接 —— DSH 自身能从 asar 解析,所以不是错误node_modules 有 150 个顶层包,而带 dsh 字段的只有 14 个用户指出的原设计缺陷:
「用户肯定希望的是,将23号启动快照固化为.bat,而不是继续保留22号旧的固化脚本」
22号:用户手动「设为 .bat」固化 B 快照
→ meta.fixedBy = 'user'
23号:开机,自动建当天 daily
启动钩子调 autoFixDaily()
→ 看到 fixedBy === 'user'
→ 直接跳过,永不覆盖
结果:.bat 一直还原 22 号那份陈旧配置
用户早就忘了自己固化过,也不知道为什么 .bat 是旧的问题本质:把「用户手动操作过一次」当成了「永久意图」,但这个意图会随时间失效。
默认:每次启动都跟着当天 daily 走
.bat 永远还原「今天启动时的那份配置」 ← 这才是用户真实期望
可选:显式钉住(pin=true)
用户明确说「我就要这一份,别动」时才保留字段 · 值 · 含义 fixedBy · 'user' / 'auto-daily' · 谁写的这份副本(仅记录) pin · true / false · 是否钉住(决定启动时会不会被替换) replacedFrom · 对象 / null · 上次被替换掉的副本,供追溯
⚠️ 关键:判断是否跳过,只看 `pin`,不再看 `fixedBy`。