dsh-rewind-plugin 0.6.3 → 0.7.0
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/README.en.md +14 -10
- package/README.md +10 -7
- package/assets/screenshots/cleanup-setting.png +0 -0
- package/docs/compat/audit.md +5 -0
- package/docs/format.md +11 -0
- package/docs/snapshot-auto-cleanup.md +4 -12
- package/docs/snapshot-auto-cleanup.zh.md +4 -8
- package/lib/client.js +513 -2
- package/lib/index.js +70 -32
- package/lib/types/client/locales.d.ts +34 -0
- package/lib/types/client/portals.d.ts +7 -6
- package/lib/types/client/settings-card.d.ts +76 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/locales.d.ts +0 -2
- package/lib/types/snapshot-cleanup.d.ts +67 -7
- package/package.json +12 -2
package/README.en.md
CHANGED
|
@@ -66,10 +66,13 @@ clears the file backups (chat rewinds are unaffected) and the plugin rebuilds th
|
|
|
66
66
|
automatically.
|
|
67
67
|
|
|
68
68
|
A **global auto-cleanup** (off by default) removes the snapshot directories of
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
long-inactive sessions, leaving the active session and chat log untouched. Configure
|
|
70
|
+
and review it in the **Settings > Plugins > Plugin configuration > Snapshot
|
|
71
|
+
cleanup** panel (the auto-cleanup switch and the idle-day cutoff), or use the
|
|
72
|
+
`/snapshot-auto-cleanup` command to **view, configure, and run** it. See:
|
|
73
|
+
[Snapshot cleanup](docs/snapshot-auto-cleanup.md).
|
|
74
|
+
|
|
75
|
+
<img src="assets/screenshots/cleanup-setting.png" alt="Snapshot cleanup settings: auto-cleanup and idle days" width="600">
|
|
73
76
|
|
|
74
77
|
## Why it stands out
|
|
75
78
|
|
|
@@ -98,14 +101,15 @@ The whole design rests on two principles, simple but deliberate: **the conversat
|
|
|
98
101
|
|
|
99
102
|
### 2. File restore: lightweight checkpointing, "back up before the change"
|
|
100
103
|
|
|
101
|
-
The file half follows Claude Code's checkpoint semantics — **
|
|
104
|
+
The file half follows Claude Code's checkpoint semantics — **partial tracking + before-write backup, plus a re-scan of tracked files at each message**, not a whole-tree snapshot. This trade-off saves space, and it's actually more complete:
|
|
102
105
|
|
|
103
|
-
- **Before-backup**: tracks the write-class tools (`write`, `edit`, `str_replace_editor`)
|
|
104
|
-
- **External changes count too**: at every user-message boundary the plugin re-checks all tracked files —
|
|
105
|
-
- **
|
|
106
|
+
- **Before-write backup**: tracks only the write-class tools (`write`, `edit`, `str_replace_editor`) — backs up the original content before a write and records/tracks the files it touches; it never backs up the whole workspace, so it's lightweight.
|
|
107
|
+
- **External changes count too**: at every user-message boundary the plugin re-checks all tracked files — external changes such as a command run or a manual edit are recorded as well and restored by a later rewind. "Lightweight" but not "incomplete".
|
|
108
|
+
- **Unchanged-not-recorded, identical-content-as-link**: an entry is written only when something changed — at the message-boundary re-check, an unchanged file is never backed up (no record); at before-write time, when the new content matches the path's prior record, only a **link to it** (`ref`) is stored instead of a copy. Repeated writes cost almost nothing, and a link is materialized before its group is evicted — never left dangling.
|
|
109
|
+
- **Reconcile against the real disk before restoring**: restore takes each path's **earliest** record, then reads the live file and compares — **only files that actually differ are touched**: modified files are written back to the earliest backup, files created after the target are deleted, already-matching files are skipped. Repeated rewinds are therefore **idempotent with zero side effects** and never produce "ghost impact".
|
|
106
110
|
- **Safety boundary**: symlinks / hard links are skipped so one restore can't clobber another name of the same file; paths are sanitized so nothing ever escapes the backup root; a per-file failure never aborts the pass.
|
|
107
111
|
|
|
108
|
-
> **Design highlight**:
|
|
112
|
+
> **Design highlight**: this checkpoint's light footprint comes from **recording only what was actually touched and really changed** — before-write backup makes it restorable, unchanged-not-recorded and content-as-link drop the repetition; which files to touch is decided against the real disk at restore time.
|
|
109
113
|
|
|
110
114
|
### Design highlights
|
|
111
115
|
|
|
@@ -132,7 +136,7 @@ This plugin deliberately stays lightweight and focused on one thing — "convers
|
|
|
132
136
|
## Compatibility
|
|
133
137
|
|
|
134
138
|
- Node.js `^22.19.0 || >=24.0.0`.
|
|
135
|
-
-
|
|
139
|
+
- Compatibility definition, verification method, and version alignment: see [docs/compat/audit.md](docs/compat/audit.md); supported DSH versions are declared by `package.json` `peerDependencies`.
|
|
136
140
|
|
|
137
141
|
> [!WARNING]
|
|
138
142
|
> This project and DeepSeek Harness are both in developer preview. Pin exact
|
package/README.md
CHANGED
|
@@ -60,7 +60,9 @@ dsh plugin --profile web add dsh-rewind-plugin
|
|
|
60
60
|
|
|
61
61
|
快照(写前备份)存储于 `<dsh home>/rewind-snapshots/`(未设 `$DSH_HOME` 时即 `~/.dsh/rewind-snapshots/`)。插件对**同一会话**的快照做内容去重(内容未变则存为链接)并保留最近 100 组锚点;**手动删除该目录**仅清除文件备份(对话回退不受影响),插件会自动重建。
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
另提供**全局自动清理**(默认关闭):把长期不活跃的会话快照整目录移除,不影响活动会话与对话日志。可在 `设置→插件→插件配置→快照清理` 面板查看与配置(自动清理开关、失活天数),也可用 `/snapshot-auto-cleanup` 命令查看、设置和运行。详见:[快照自动清理](docs/snapshot-auto-cleanup.zh.md)。
|
|
64
|
+
|
|
65
|
+
<img src="assets/screenshots/cleanup-setting.png" alt="快照清理设置:自动清理与失活天数" width="600">
|
|
64
66
|
|
|
65
67
|
## 本插件的优势
|
|
66
68
|
|
|
@@ -89,14 +91,15 @@ dsh plugin --profile web add dsh-rewind-plugin
|
|
|
89
91
|
|
|
90
92
|
### 2. 文件还原:轻量检查点,「改前备份」
|
|
91
93
|
|
|
92
|
-
文件部分对齐 Claude Code
|
|
94
|
+
文件部分对齐 Claude Code 的检查点语义——**局部追踪、写前备份 + 每条消息重扫已跟踪文件**,而不是整树快照。这项取舍既省空间,又更完整:
|
|
93
95
|
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
96
|
+
- **写前备份**:只追踪写类工具(`write`、`edit`、`str_replace_editor`),写前**备份原内容**,并**记录、追踪**被处理的文件——从不备份整个工作区,因此轻量。
|
|
97
|
+
- **外部变更也追**:每条用户消息边界,插件重新检查所有已跟踪文件——命令执行、手动修改等外部变更同样被记录,回退时一并还原。这让「轻量」却不「残缺」。
|
|
98
|
+
- **不变不存、同内容存链接**:记录只在有变化时发生——消息边界重扫时无变更的不备份(不留记录);写前备份时若与前一条记录一致,只存**指向它的链接**(`ref`)而非复制内容。重复写入几乎不占空间,链接也先落地、绝不悬空。
|
|
99
|
+
- **还原时对照真实磁盘**:先取每条路径的**最早**记录,再实时读取文件当前内容与之比对——**只操作真正不一致的文件**:改过的写回最早期内容、目标之后新建的删除、已经一致的跳过。重复回退因此**零副作用、幂等**,不会出现「幽灵影响」。
|
|
97
100
|
- **安全边界**:符号/硬链接跳过,避免透过一个还原误伤另一个名字;路径经安全化处理,**绝不越出备份根目录**;单个文件失败绝不中止整轮还原。
|
|
98
101
|
|
|
99
|
-
>
|
|
102
|
+
> **设计点睛**:这套检查点的「轻」,来自**只记录被工具动过、且确实变化的文件**——写前备份保证可还原,不变不存与存链接压掉重复;还原时再对照真实磁盘,只动不一致的文件。
|
|
100
103
|
|
|
101
104
|
### 设计亮点一览
|
|
102
105
|
|
|
@@ -123,7 +126,7 @@ dsh plugin --profile web add dsh-rewind-plugin
|
|
|
123
126
|
## 兼容性
|
|
124
127
|
|
|
125
128
|
- Node.js `^22.19.0 || >=24.0.0`。
|
|
126
|
-
-
|
|
129
|
+
- 兼容性定义、验证方法与版本对齐详见 [docs/compat/audit.md](docs/compat/audit.md);支持的 DSH 版本由 `package.json` 的 `peerDependencies` 声明。
|
|
127
130
|
|
|
128
131
|
> [!WARNING]
|
|
129
132
|
> 本项目与 DeepSeek Harness 均处于开发者预览阶段。可复现环境请 pin 精确版本,
|
|
Binary file
|
package/docs/compat/audit.md
CHANGED
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
> `-alpha` prerelease published under another tag, e.g. `0.1.2-alpha.2` under
|
|
21
21
|
> `alpha`, is a manual pre-release check).
|
|
22
22
|
>
|
|
23
|
+
> `0.1.2-alpha.1` was never published to npm, so the peer OR-union is declared only from `0.1.2-alpha.2`; the plugin code still supports the `alpha.1`+ client.
|
|
24
|
+
>
|
|
25
|
+
> `0.1.2-alpha.3` verified-compatible (`v0.6.3` runs without issues); `rc.2` (`latest`) remains the primary baseline.
|
|
26
|
+
>
|
|
23
27
|
> Client channel (harness `0.1.2-alpha.x`; `0.1.2-alpha.2` is published to npm
|
|
24
28
|
> under the `alpha` dist-tag while `latest` stays `0.1.1-rc.2`): the plugin reads
|
|
25
29
|
> the session chat through `uiConversation` whenever the DSH client exposes it.
|
|
@@ -67,6 +71,7 @@
|
|
|
67
71
|
- **rewind across a compact checkpoint**: `RewindError('not-on-surface')` refuses cleanly, no crash.
|
|
68
72
|
- **plan-mode**: a marker reuses the last started turn (no phantom turn); a rewind never touches the log-only `plan/mode` state (plan mode stays active; the user leaves it with `/plan off`) and the log stays replayable (`compat-invariants` I1/I3 marker + `plan/mode` probe, `verify-host`).
|
|
69
73
|
- **agent-loop cancellation**: `finally` guarantees step/turn closure; the rewind force-stop path leaves no dangling frame.
|
|
74
|
+
- **settings-card cross-version reach**: the Snapshot cleanup card must be registered through a **nested** `ctx.inject(['settingsScope'], …)` — naming `settingsScope` in the module-level inject unmounts the whole client plugin on rc.2 (card and rewind button disappear). It uses only the rc.2↔alpha-common scope subset (`getSnapshot().value` + `set`), never the alpha-only `mutate`.
|
|
70
75
|
|
|
71
76
|
## Known behavior boundaries (deterministic differences, non-crash, documented)
|
|
72
77
|
|
package/docs/format.md
CHANGED
|
@@ -149,3 +149,14 @@ version field. A future incompatible format must either bump the journal
|
|
|
149
149
|
`version` (readers reject unknown values — there is no best-effort fallback or
|
|
150
150
|
legacy coercion) or move the state root (e.g. `rewind-snapshots/v2`) and ship
|
|
151
151
|
an explicit migration tool. Old-format data is never silently re-interpreted.
|
|
152
|
+
|
|
153
|
+
## Cleanup policy persistence
|
|
154
|
+
|
|
155
|
+
The snapshot auto-cleanup policy (the `enabled` switch and the `maxAgeDays`
|
|
156
|
+
idle cutoff) is no longer a file: it lives in the **dsh-settings document** under
|
|
157
|
+
the `dsh-rewind-snapshot-cleanup` namespace (validated by a schemastery schema;
|
|
158
|
+
defaults are the `base` layer). On first run after this change, a legacy
|
|
159
|
+
`<dsh home>/snapshot-cleanup.json` is imported into the document **once** and
|
|
160
|
+
then deleted (an absent file is a no-op; an invalid file imports the safe
|
|
161
|
+
default and is dropped). The last-sweep clock stays in its own
|
|
162
|
+
`<dsh home>/snapshot-cleanup-last-sweep.json` state file, which is unchanged.
|
|
@@ -15,7 +15,7 @@ you've stopped using, and now and then remove their snapshots to keep disk usage
|
|
|
15
15
|
down. It never touches your active session, and it never touches your
|
|
16
16
|
conversation.
|
|
17
17
|
|
|
18
|
-
**Manual
|
|
18
|
+
**Manual**: even with automatic cleanup off, you can run the cleanup yourself:
|
|
19
19
|
|
|
20
20
|
- `/snapshot-auto-cleanup run [--apply]` — preview, then actually remove the
|
|
21
21
|
snapshots of sessions you haven't used for a while.
|
|
@@ -41,20 +41,12 @@ whether or not automatic cleanup is on.
|
|
|
41
41
|
|
|
42
42
|
## Settings
|
|
43
43
|
|
|
44
|
-
The
|
|
44
|
+
The auto-cleanup switch and the idle-day cutoff live in the **dsh-settings configuration document**. View and edit them in the **Settings > Plugins > Plugin configuration > Snapshot cleanup** panel (the auto-cleanup switch and the idle days), or view and set them with the `/snapshot-auto-cleanup` command:
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
{ "enabled": false, "maxAgeDays": 30 }
|
|
48
|
-
```
|
|
46
|
+
<img src="../assets/screenshots/cleanup-setting.png" alt="Snapshot cleanup settings: auto-cleanup and idle days" width="600">
|
|
49
47
|
|
|
50
48
|
- `enabled` — whether automatic cleanup runs (default `false`).
|
|
51
|
-
- `maxAgeDays` — how many idle days before a session's snapshots are removed
|
|
52
|
-
(default `30`). Only positive numbers are accepted, so a broken setting can
|
|
53
|
-
never delete everything.
|
|
54
|
-
|
|
55
|
-
You can point the plugin at a different file with the `DSH_SNAPSHOT_CLEANUP_CONFIG`
|
|
56
|
-
environment variable. The file is changed only when you turn cleanup on/off or
|
|
57
|
-
set `max-age`; a missing file reads as the safe default (off).
|
|
49
|
+
- `maxAgeDays` — how many idle days before a session's snapshots are removed (default `30`). Only positive integers are accepted, so a broken setting can never delete everything.
|
|
58
50
|
|
|
59
51
|
## When automatic cleanup runs
|
|
60
52
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**自动清理**(默认关闭):插件会记住哪些会话你已不再使用,并定期移除它们的快照以节省磁盘。它**绝不**触碰你当前活跃的会话,也**绝不**触碰你的对话。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**手动**:即使自动清理是关闭的,你也可以自己执行清理:
|
|
12
12
|
|
|
13
13
|
- `/snapshot-auto-cleanup run [--apply]` — 先预演,再真正移除你已有一阵子没用的会话的快照。
|
|
14
14
|
- `/snapshot-auto-cleanup run --current [--apply]` — 先预演,再真正清空**当前**会话的快照。这会让它从"现在"重新开始记录回退历史(你的对话不受影响)。若此刻有正在进行中的回合,插件会先暂停它,再清空。
|
|
@@ -29,16 +29,12 @@
|
|
|
29
29
|
|
|
30
30
|
## 设置
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
自动清理开关与失活天数保存在 **dsh-settings 配置文档**。可在 **设置→插件→插件配置→快照清理** 面板查看与修改(自动清理开关、失活天数),也可用 `/snapshot-auto-cleanup` 命令查看和设置:
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
{ "enabled": false, "maxAgeDays": 30 }
|
|
36
|
-
```
|
|
34
|
+
<img src="../assets/screenshots/cleanup-setting.png" alt="快照清理设置:自动清理与失活天数" width="600">
|
|
37
35
|
|
|
38
36
|
- `enabled` — 是否运行自动清理(默认 `false`)。
|
|
39
|
-
- `maxAgeDays` — 会话失活多少天后移除其快照(默认 `30
|
|
40
|
-
|
|
41
|
-
你可以用环境变量 `DSH_SNAPSHOT_CLEANUP_CONFIG` 指向别的文件。该文件只在运行 `/snapshot-auto-cleanup` 时写入;文件缺失按安全默认值(关闭)处理。
|
|
37
|
+
- `maxAgeDays` — 会话失活多少天后移除其快照(默认 `30`)。只接受正整数,因此一个损坏的设置永远不可能"删掉一切"。
|
|
42
38
|
|
|
43
39
|
## 自动清理何时运行
|
|
44
40
|
|