dsh-autorestart 0.8.4 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/README.md +43 -7
- package/client.js +581 -9
- package/docs/README.zh.md +12 -4
- package/index.js +727 -47
- package/lib/backup.js +219 -4
- package/lib/checkpoint.js +93 -3
- package/lib/restart-phase.js +5 -0
- package/locale/en.json +21 -1
- package/locale/zh.json +21 -1
- package/package.json +2 -2
package/docs/README.zh.md
CHANGED
|
@@ -148,7 +148,10 @@ session resume on boot, durable-goal re-arm, and an agent-callable idle-aware gr
|
|
|
148
148
|
- 拷回本身也有**时间上限**(`rollbackCopyTimeoutMs`,默认 120 秒/步):拷不完就放弃,并把原因写进报告。
|
|
149
149
|
- **托管模式(`restartMode: command`)也有同一张安全网**:重启命令通常会把插件自己所在的进程一起杀掉,所以看护脚本在命令**之前**就启动了,由它来确认新实例有没有起来。命令起不来或以非零码退出时,插件**如实报错**(带退出码和输出)并把快照拷回去,绝不静默当成功。
|
|
150
150
|
- 下次启动时 `continuum_status` 会报 `lastRollback`(时间、等了多久、是否回滚、**失败原因**、快照路径、崩溃日志名与尾部摘要)。
|
|
151
|
-
-
|
|
151
|
+
- **回滚目标是「最新的安全份」,不是「最新的一份」**(用户决定,2026-10-30):每份备份旁边有一张 `meta.json` 记着身份——`known-good`(安全份,已经有一次启动成功验证过)、`snapshot`(本次快照,重启前刚拍、还没验证)、`unknown`(身份层之前的旧备份)。**这次重启前拍的那份永远不是回滚目标**,因为它可能正是坏掉的那一份(「改坏了插件再点重启」就是这个场景)。第一次安装时会种子一份安全份;每次启动成功(健康检查通过)后,把那次重启前的快照提升为安全份。
|
|
152
|
+
- **没有安全份就一份都不还原**:找不到 latest known-good 时,回滚什么都不做,报告里写 `no-known-good: <原因>`,profile 保持失败重启后的原样,看门狗也**不挂**(没有可还原的目标,挂上去只会再把坏配置写一遍)。
|
|
153
|
+
- **可以手动回退到任意一份备份**(含更早、未验证的那份,用户决定 2026-10-30):设置页每行都有「回退到这一份」,点了先弹**二次确认**(写清还原哪一份、当前状态会被覆盖、还原后会自动重启),确认后才动,取消则什么都不发。服务端 `POST /__dsh_autorestart/rollback-to` 只收**备份目录名**(必须是本机列表里的那一份,路径 / 路径穿越直接拒绝),顺序是先存一份当前快照(`reason: before-manual-rollback`,所以这次回退本身还能再退回来)→ 再还原选中的那份 → 写 `last-manual-rollback.json` 回执 → 走既有重启流程请求重启(插件自己绝不 kill 进程);当前状态存不下来、或看门狗正持有回滚锁时直接拒绝(409),不会出现还原了一半。
|
|
154
|
+
- 开关:`backupOnRestart`(默认 `true`)、`backupIncludePlugins`(默认 `true`,关掉就只备配置文件)、`maxBackups`(默认 `3`:当前一份 + 之前两份;**最新的 known-good 永远不删**)、`rollbackTimeoutMs`(默认 `90000`)、`restartCommandTimeoutMs`(默认 `30000`)、`rollbackCopyTimeoutMs`(默认 `120000`)。
|
|
152
155
|
|
|
153
156
|
### 这台电脑不让建计划任务时(自动回滚就没了)
|
|
154
157
|
|
|
@@ -330,7 +333,7 @@ agent/status(running) ──► 写 checkpoint(<DSH_HOME>\storages\dsh-autores
|
|
|
330
333
|
|
|
331
334
|
## 安装
|
|
332
335
|
|
|
333
|
-
当前版本:**0.8.
|
|
336
|
+
当前版本:**0.8.5**。
|
|
334
337
|
|
|
335
338
|
```powershell
|
|
336
339
|
# 在 dsh 里(或对 Agent 说):把工作区里的这个包安装为 profile bundle
|
|
@@ -366,13 +369,16 @@ dsh plugin --profile desktop add C:\path\to\dsh-autorestart
|
|
|
366
369
|
|
|
367
370
|
设置页里关于「备份」「回执」和「启动方式」的几块,先说清楚它们看的是什么:
|
|
368
371
|
|
|
369
|
-
- **现在备份了什么**(在两个备份勾选的下面):宿主真的去读 `<DSH_HOME>/storages/dsh-autorestart/backups/`,所以份数、每份的**本地时间**、大小、有没有含已装插件、以及存放路径都是真的。只有目录元信息被读,备份里的内容**不遍历**(一份就可能 150 MB
|
|
372
|
+
- **现在备份了什么**(在两个备份勾选的下面):宿主真的去读 `<DSH_HOME>/storages/dsh-autorestart/backups/`,所以份数、每份的**本地时间**、大小、有没有含已装插件、以及存放路径都是真的。只有目录元信息被读,备份里的内容**不遍历**(一份就可能 150 MB)。没有备份时写的是「还没有备份;每次重启前会自动生成一份」。每份备份先写**身份**(它到底能不能用来回滚),再写两行带标签的数值:
|
|
370
373
|
|
|
371
374
|
```
|
|
375
|
+
身份 安全份 · 版本 0.8.5
|
|
372
376
|
备份时间 2026-10-29 22:08
|
|
373
377
|
备份大小 156 MB(含已装插件)
|
|
374
378
|
```
|
|
375
379
|
|
|
380
|
+
身份只有三种:**安全份**(已经有一次启动成功验证过,自动回滚只认它)、**本次快照**(每次重启前刚拍的,还没验证)、**旧备份(未验证)**(身份层之前的拷贝,或者没有身份文件)。列表上方还有一段说明,讲清两种身份、看门狗只回滚安全份、第一次安装会生成安全份、最多保留 3 份、旧备份不会被自动回滚、手动回退会先二次确认再重启。身份和版本由宿主给(`backups.items[].kind` / `backups.items[].version`)——浏览器读不到 `meta.json`。
|
|
381
|
+
|
|
376
382
|
时间就是拍快照那台机器的本地时间,**精确到分、不带时区偏移**(`+08:00` 只会添乱——看的人本来就看自己的钟)。大小自动选单位(`92 KB` / `156 MB`),只在有意义时保留一位小数(`117.7 MB`,永远不写 `156.0 MB`);「(含已装插件)」紧跟在大小后面,因为它正是这份备份为什么这么大。两份备份就是两组,组与组之间留空隙。
|
|
377
383
|
- **设置改动有回执**:每个开关/下拉都是改了就写,所以面板必须说清写没写进去——宿主回 `ok: true` 之后,**设置面板内部顶部**(面板自己的 `sticky` 条,往下滚动也一直可见)出现绿色**「已生效」** + 小字时间(`已生效 21:40:12`),3 秒后淡出;被拒绝时是红色**「没保存成功」** + 宿主给的原因,不自动消失,直到下一次改动成功或你自己点 × 关掉。**宿主没回话之前一律不显示**:首次渲染、轮询刷新、点控件都不会亮。
|
|
378
384
|
- **启动方式**(Web 托管端才有):默认只给**一行大白话**(例如「我记下的启动方式:由你的脚本拉起(重启交给它,我不插手)」)加两个小动作(重新检测 / 撤销);命令原文收在**「技术细节」**折叠里,默认收起,展开才出现。**桌面客户端这一整块不渲染** —— 它自己拉起自己,也不该写 `restartCommand`。宿主说不清是哪一端时,宁可整块不显示。
|
|
@@ -407,7 +413,7 @@ dsh plugin --profile desktop add C:\path\to\dsh-autorestart
|
|
|
407
413
|
| `continuationText` | `''` | 覆盖默认续接提示文本 |
|
|
408
414
|
| `backupOnRestart` | `true` | 每次重启前给 profile 拍快照;重启后起不来时能自动回退 |
|
|
409
415
|
| `backupIncludePlugins` | `true` | 快照里是否带上已安装插件目录(本机约 117 MB、多约 3 秒);关掉就只备配置文件 |
|
|
410
|
-
| `maxBackups` | `
|
|
416
|
+
| `maxBackups` | `3` | 保留几份快照(当前一份 + 之前两份);写新的时自动删旧的——但**最新的 known-good 一份永远不删** |
|
|
411
417
|
| `rollbackTimeoutMs` | `90000` | 看护脚本等新宿主多久(毫秒),超时就回退快照(**不会再拉起第二个宿主**) |
|
|
412
418
|
| `restartCommandTimeoutMs` | `30000` | 重启命令最多让插件等多久(毫秒)。前台跑着宿主的命令永远不返回——那会报「还在运行」,不算失败 |
|
|
413
419
|
| `rollbackCopyTimeoutMs` | `120000` | 拷回快照的**每一步**最多花多久(毫秒):拷不完就放弃,并把原因写进回退报告 |
|
|
@@ -552,6 +558,8 @@ restart gate: action=wait reason=agents-busy-within-soft-window busyCount=1 quie
|
|
|
552
558
|
`{ "sessionId": "…", "scope": "mine" }`):别的会话照样重启。面板里**没有**"全撤"——那种操作只留给
|
|
553
559
|
工具显式调用(`continuum_cancel_restart` 带 `scope: "all"`)。
|
|
554
560
|
|
|
561
|
+
**浮层不会悬停,也不说假话**:重启被新会话打断时,浮层立刻从「正在重启…」换成「**有新会话在跑,重启已暂缓**」,第二行小字「等它结束会自动继续 · 已等 N 个会话」——这时候说「正在重启」就是假话。宿主每 350ms 复查一次空闲门,那句假话最多只存在一个心跳;备份一结束、进入「正在重启」阶段之前也会当场复查一次,被挡就在同一次 tick 退回等待。阶段超过 15 秒无更新视为过期,不再显示,胶囊仍显示等待数。
|
|
562
|
+
|
|
555
563
|
## 收工关机(Graceful shutdown)
|
|
556
564
|
|
|
557
565
|
**它干什么。** 左侧栏最底部一个月亮按钮:点一下 → 等**所有**会话都收工 → 屏幕上倒数(一个巨大的数字 + 一只蓝色小鲸鱼,每秒换一句中文)→ **关掉整台电脑**。倒数期间随时可以取消:卡片上有按钮,月亮按钮本身在关机期间也变成了"再点一下 = 取消"。倒数期间要是有会话又开始干活,倒计时会退回"等待",**绝不关机**。
|