Repository navigation
Releases: FuriousKinght/dsh-fk-rollback
Release list
v1.5.1 — .bat 固化跟随最新 daily + 安装工具
本次更新
插件本体:.bat 固化副本不再「一次固化,永久冻结」
旧行为:手动固化过一次(fixedBy='user')后,启动钩子永久跳过,
.bat 一直还原那份陈旧配置 —— 用户自己都忘了。
新行为:默认跟着当天 daily 走,只有显式 pin=true 才冻结。
- 新增
pin字段(唯一决定是否被替换) - 新增
replacedFrom记录(可追溯换掉了哪一份) fix <id> --pin钉住 /fix --unpin取消 /fix --show查看- 面板
.bat卡片显示钉住状态 + 切换按钮 - 补上
--help里一直缺失的fix命令说明
打包与安装工具(不改插件运行逻辑)
- 修复包内缺
package.json导致 pnpm 装不上 - 修复
node_modules残留目录导致Symlink path is the same as the target path - 新增
install.mjs:幂等安装/修复助手(自动清理残留、写绝对路径 link、检测 DSH 是否运行) - 新增
安装.bat:双击即用(内部cd /d "%~dp0",避免在错误目录运行) .bat路径探测不再硬编码盘符,改为多级自动探测
实测
14/14 依赖链接有效
19/19 bundles 可解析
11/11 文件语法通过
CLI 全命令 exit=0
v1.5.1(2026-10-23)
修复:.bat 固化副本不再「一次固化,永久冻结」
用户指出现象:
「22号将 .bat 固化成 B 快照,23号开机自动建了当天启动快照,
这时 .bat 还会用 23号的吗?」
旧行为:不会。 因为只要手动固化过一次(fixedBy='user'),
启动钩子就永久跳过,.bat 一直还原 22 号那份陈旧配置 —— 而用户早忘了。
根因:把「操作过一次」当成「永久意图」,但该意图会随时间失效。
新行为:默认跟着当天 daily 走,只有显式 pin=true 才冻结。
- 新增
pin字段(默认 false) - 新增
replacedFrom记录(可追溯「换掉了哪一份」) fix <id>默认不钉住;fix <id> --pin才钉住- 新增
fix --pin/fix --unpin/fix --show - 面板
.bat卡片显示钉住状态 + 「钉住/取消钉住」按钮
实测 5 个场景全部通过(10 项断言):
① 22号固化B(不pin)→ 23号启动 → ✅ 换成23号daily,并记录 replacedFrom
② 显式 pin B → 23号启动 → ✅ 保持B,返回 pinned=true
③ --unpin → 启动 → ✅ 恢复跟随,换成最新daily
④ 同一份daily二次调用 → ✅ 跳过,不重写磁盘
⑤ fix --show → ✅ 显示钉住状态
v1.5.1 补记(2026-10-26):打包与安装工具修复
⚠️ 插件本体无任何改动。 以下改动只涉及打包方式与安装工具,
15 个插件文件的运行逻辑与 v1.5.1 完全一致。
修复安装阻断问题(插件本体无改动)
⚠️ 说明:本次改动只涉及「打包方式」与「安装工具」,
插件本体的 15 个文件逻辑与 v1.5.1 完全一致,未做任何功能修改。
① 包内缺 package.json(致命,导致朋友装不上)
根因:npm 的 files 数组按惯例不列 package.json 自己,
而自研打包脚本只遍历 files 数组 → 漏掉它。
后果:pnpm 不认为这是一个包,装不上。
修复:package.json 无条件打包。
② node_modules 里有残留目录 → Symlink path is the same as the target path
pnpm 源码 symlinkDir():
if (target === path) throw new Error('Symlink path is the same as the target path')
成因:插件被解压/复制到 node_modules 里(错误位置),
pnpm 判定为孤儿 → 挪到 .ignored → 重建链接时路径撞自己。
修复:install.mjs 自动识别并清理。
③ 在错误目录运行 → Cannot find module 'C:\install.mjs'
朋友在 C:\ 或 node_modules 里运行 node install.mjs,
当前目录没有那个文件。
修复:新增 安装.bat,双击即用(内部 cd /d "%~dp0" 先切到自身目录)。
④ 脚本在「要被删除的目录」里运行 → EPERM
Windows 不允许删除进程当前工作目录及其祖先。
修复:install.mjs 启动即 chdir 到用户主目录。
⑤ install.mjs 在 DSH 运行时留下半成品状态
DSH 运行时文件被占用,pnpm 装不上依赖,
留下「有声明、无链接」的半成品 → 下次启动报 cannot resolve profile bundle。
修复:先检测 DSH 进程,运行中则阻止(或要求 --config-only)。
新增两个安装工具(不参与插件运行)
install.mjs 命令行安装/修复器(幂等,可反复运行)
安装.bat 双击即用的包装(自动定位 node.exe 与本脚本)
v1.4.0 — 分组折叠 + client loader id 体检
本次更新
体检新增:client.js 模块 loader id 一致性检查
对应 2026-10-21 的真实事故:插件改名时 package.json 改了、client.js 的 __ModuleLoader__.load({ id }) 漏改,DSH 判定为两个模块注册同一 factory,抛 duplicate factory registration → 全量启动中止。
修复:分组显示「N 项」但列表为空
跨组翻页与分组冲突 —— 今天 13 项把第 1 页占满,「昨天 2 项」筛出 0 条。改为每组独立「显示更多」。
UI:所有分组都能折叠
v1.4.0(2026-10-21)
体检新增:client.js 的模块 loader id 一致性检查
对应 2026-10-21 的真实事故(OFM 插件改名不彻底):
package.json的name改成了dsh-fk-our-free-model- 但
client.js:22的__ModuleLoader__.load({ id: 'dsh-our-free-model' })漏改 - DSH 判定为「两个模块注册同一个 factory」
- 抛
client-modules: duplicate factory registration dsh-client-modules启动失败 → 全量启动中止,DSH 完全起不来
这类错误的特征是「静态看不出、启动才知道崩」,所以体检必须提前拦。
新增两个检查码:
| 码 | 级别 | 说明 |
|---|---|---|
client-loader-id-mismatch |
fatal | client.js 的 id 与包名不一致 —— DSH 会启动失败 |
client-exports-name-mismatch |
warn | client.js 的 exports.name 与包名风格不一致 |
修复:cordis.patch.yml 为 [] 时误报 YAML 语法错误
全新 profile 的 patch 可能就是一个空数组 [](或只有注释)。
之前会被判成 bad-yaml,让用户以为配置坏了。已修复。
UI:快照列表所有分组都能折叠
原来只有「更早」和「回滚记录」能折叠,今天/昨天是固定展开的。
现在四组都可以点标题折叠/展开,箭头 ▾ / ▸ 指示状态,
折叠时右侧显示「已折叠」。
修复:分组显示「N 项」但列表为空
用户反馈:「昨天显示有两项,但是不显示」
根因是 v1.4.0 加折叠时暴露的旧设计缺陷 —— 跨组翻页和分组互相冲突:
const primary = [...buckets.today, ...buckets.yesterday] // 15 项
const pageItems = primary.slice(0, 10) // 第1页只取 10 项今天有 13 项,第 1 页的 10 条全是今天的 → 「昨天」筛出 0 条,
但分组头的数字用的是全量 g.items.length = 2。
于是头显示「昨天 2 项」,下面一条都没有。
翻到第 2 页时反过来:「今天」只剩 3 项,看起来像今天只有 3 个快照。
修复方式:去掉跨组翻页,每组独立「显示更多」
分组本身就是天然的分页(今天 / 昨天 / 更早),不需要再跨组翻。
- 每组默认显示 10 条,超出时给「显示更多(还有 N 项)」
- 点一次加 10 条,只影响本组
- 切换搜索词 / 筛选条件时,所有组的显示条数重置
v1.3.0 — 内置重启 + 回滚记录独立存放
本次更新
重启能力已内置,不再需要额外安装任何插件。
发布前的最后一个外部依赖被消除了 —— 装一个插件就完整可用。
同时:回滚前快照改为独立存放(restore-points/),并明确说明是哪次回滚的现场。
v1.3.0(2026-10-20)
重启能力已内置 —— 不再需要额外安装任何插件
发布前的最后一个外部依赖被消除了。
之前的做法是让用户再装一个 dsh-fk-restart-button,否则「立即重启」按钮用不了。
这对发布场景不可接受:装一个插件就该完整可用。
现在把重启逻辑搬进了 lib/restart.mjs + lib/relaunch-helper.cjs:
- 零第三方依赖(只用
node:child_process/fs/os/path/url/crypto) - 不需要额外的 ctx 服务(和本插件一样只要
webServer) - Windows 桌面版可真正自动重启;其他环境明确提示手动重启
实现要点(都是实测踩出来的)
- 用 WMI
Win32_Process.Create创建助手进程 —— 普通 spawn 会被
taskkill /T一起杀掉,WMI 创建的进程父级是WmiPrvSE.exe,不在被杀的那棵树里 - 必须传
ProcessStartupInformation { ShowWindow: 0 },否则会弹出可见终端窗口 - 系统程序一律走绝对路径(有的机器 PATH 里没有 System32)
- 端口从请求头动态发现,不能写死 19387(某些构建绑动态端口)
端点变化
GET /restart-helper→ 改为探测内置能力,返回builtin: true与不可用原因POST /restart→ 直接执行内置重启,不再转发到外部插件
顺带清理
- 去掉了转发逻辑里的超时/重试复杂度(内置实现本身是毫秒级返回)
- 按钮 tooltip 现在显示真实的不可用原因
回滚前快照改为独立存放,并说明是哪次回滚
用户要求:「回滚后会生成一个回滚前的快照,我建议把这一栏单独存放,
并且说明是某某时间段的回滚」
- 新增
restore-points/目录 —— 回滚前快照从checkpoints/独立出来 - 独立配额:保留最近 10 份,不占用手动快照的 50 个名额
- 快照名明确写出时间:
回滚前 2026-10-20 15:29 meta/ 索引新增restoreInfo字段:{ "at": 1792491043994, "targetId": "...", "targetName": "装插件前", "reason": "用户指定" }- 面板新增「回滚记录(每次回滚前的现场)」分组,默认折叠,排在列表最前
- 每行副标题显示
· 回滚到「装插件前」前 - CLI 列表同步显示
↳ 回滚到「xxx」之前的现场
旧数据(v1.3.0 之前产生的回滚前快照)仍在 checkpoints/ 且没有 restoreInfo,
但 type 仍是 before-restore,所以照样归入「回滚记录」分组 —— 不迁移也能正常显示。
v1.2.0(2026-10-20)
修复:「立即重启 DSH」按钮永远是灰的,点不了
用户反馈:回滚完成后的结果页有「稍后重启 / 现在重启」,但「现在重启」是灰色的。
根因(两处):
-
探测写错了 ——
/restart-helper只在cordis.patch.yml文本里 grep 插件名,
但dsh-fk-restart-button是通过 profile 的bundles注册的,patch 里
根本没有它的名字 → 探测永远返回false→ 按钮永远渲染成禁用态。
改为以bundles/dependencies为准,patch 只作兜底。 -
没有转发端点 —— 原来的前端直接调重启插件的地址,插件没装时静默失败。
新增POST /restart:由 Host 端转发到重启插件(新旧两条路由都试),
统一给出可读错误。前端改调自己的端点。
顺带修掉一个会卡死界面的问题
转发请求原本没有超时。对端不响应时 fetch 会一直挂着,
按钮永远显示「重启中…」,用户只能强杀 DSH。
现在整个重启流程共享 8 秒总预算(不是每步各算),超时立刻中断并给出提示。
实测:最坏耗时从 20.6 秒降到 8.0 秒。
UI 改进
- 按钮不再因探测失败而变灰 —— 永远可点,由 Host 端返回真实结果
- 点击后显示「重启中…」,失败时明确告知「可手动关闭 DSH 再打开」
/restart-helper返回evidence字段,说明探测依据(bundle / dependency / patch)
v1.1.0(2026-10-20)
新增:固化副本(.bat 的独立数据源)
.bat 是「DSH 完全起不来」时的最后手段,不能依赖会被自动清理的快照池。
- 新增
fixed/bat-default/固化区 —— 不参与快照池的任何自动清理 - 每次 DSH 启动自动把当天 daily 快照固化过去(
fixedBy: auto-daily) .bat只读固化副本;找不到就明确报错,绝不偷偷回退到快照池- 面板可在任意快照上点「设为 .bat」,手动指定固化对象(
fixedBy: user,不会被自动覆盖) - 新增命令:
fix <ID>/fix --show/fix --clear/paths - 面板底部显示:
快照目录与脚本目录
新增:快照来源标记
- 区分
自动(钩子)/AI(会话) /手动(用户) - 判据:
DSH_SESSION_ID环境变量存在 → AI;否则 → 用户;钩子显式传auto - 面板标签 + 筛选器 + CLI 列均支持
修复
apply()被 Fiber 重复调用导致路由重复注册(每次启动写 15 条duplicate route错误)→ 用WeakSet幂等保护- 事件被重复订阅 3 次 → 同上
pickLastGood选点偏差:原按「健康等级+最新」,会选中before-restore而非当天 daily → 改为 当天 daily 优先,health 为 broken 的排除- 时区:
toISOString()在东八区 0–8 点会误判「今天」→ 改用本地localDateKey() - 自动固化被 health 过滤挡住(体检 fatal 时 daily 也不固化)→ 固化不按 health 过滤
- 卡片展开后文字被按钮挤压成一字一行 → 卡片改纵向,按钮独立成行