dsh-rewind-plugin 0.9.0-alpha.2 → 0.10.0-alpha.1
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 +2 -2
- package/README.md +2 -2
- package/docs/architecture.md +12 -8
- package/docs/format.md +3 -4
- package/docs/harness-reference.md +1 -4
- package/docs/rewind-fix.md +5 -5
- package/docs/rewind-fix.zh.md +6 -6
- package/lib/client.js +12 -6
- package/lib/index.js +13 -628
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/locales.d.ts +0 -20
- package/lib/types/snapshot-cleanup.d.ts +12 -48
- package/package.json +44 -44
- package/lib/types/rewind-fix.d.ts +0 -111
- package/lib/types/rewind-marker-repair.d.ts +0 -110
- package/lib/types/session-log-io.d.ts +0 -57
package/README.en.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# dsh-rewind
|
|
2
2
|
|
|
3
3
|
> [!WARNING]
|
|
4
|
-
> **Planning to use DSH `0.1.3`?
|
|
4
|
+
> **Planning to use DSH `0.1.3`? Install a `v0.9.x` release as soon as possible and run `/dsh-rewind-fix` to update old rewind markers** ([update guide](docs/rewind-fix.md)).
|
|
5
5
|
|
|
6
6
|
Conversation rewind for DeepSeek Harness: **rewind the conversation to any earlier user message in one click, in the same window** — no new branch, no window switch, with optional workspace-file restore (full Claude Code `/rewind` semantics).
|
|
7
7
|
|
|
@@ -106,7 +106,7 @@ The whole design rests on two principles, simple but deliberate: **the conversat
|
|
|
106
106
|
|
|
107
107
|
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:
|
|
108
108
|
|
|
109
|
-
- **Before-write backup**: tracks only the write-class tools (`write`, `edit
|
|
109
|
+
- **Before-write backup**: tracks only the write-class tools (`write`, `edit`) — 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.
|
|
110
110
|
- **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".
|
|
111
111
|
- **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.
|
|
112
112
|
- **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".
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# dsh-rewind
|
|
2
2
|
|
|
3
3
|
> [!WARNING]
|
|
4
|
-
> **计划使用 DSH `0.1.3`
|
|
4
|
+
> **计划使用 DSH `0.1.3` 的用户:请尽早安装 `v0.9.x` 版本,并运行 `/dsh-rewind-fix` 更新旧回退标记**([更新指南](docs/rewind-fix.zh.md))。
|
|
5
5
|
|
|
6
6
|
DeepSeek Harness 插件:**一键就地回退对话到任意更早的用户消息**——同窗口内完成,不新建分支、不换窗口,可一并还原工作区文件(完整 Claude Code `/rewind` 语义)。
|
|
7
7
|
|
|
@@ -96,7 +96,7 @@ dsh plugin --profile web add dsh-rewind-plugin
|
|
|
96
96
|
|
|
97
97
|
文件部分对齐 Claude Code 的检查点语义——**局部追踪、写前备份 + 每条消息重扫已跟踪文件**,而不是整树快照。这项取舍既省空间,又更完整:
|
|
98
98
|
|
|
99
|
-
- **写前备份**:只追踪写类工具(`write`、`edit
|
|
99
|
+
- **写前备份**:只追踪写类工具(`write`、`edit`),写前**备份原内容**,并**记录、追踪**被处理的文件——从不备份整个工作区,因此轻量。
|
|
100
100
|
- **外部变更也追**:每条用户消息边界,插件重新检查所有已跟踪文件——命令执行、手动修改等外部变更同样被记录,回退时一并还原。这让「轻量」却不「残缺」。
|
|
101
101
|
- **不变不存、同内容存链接**:记录只在有变化时发生——消息边界重扫时无变更的不备份(不留记录);写前备份时若与前一条记录一致,只存**指向它的链接**(`ref`)而非复制内容。重复写入几乎不占空间,链接也先落地、绝不悬空。
|
|
102
102
|
- **还原时对照真实磁盘**:先取每条路径的**最早**记录,再实时读取文件当前内容与之比对——**只操作真正不一致的文件**:改过的写回最早期内容、目标之后新建的删除、已经一致的跳过。重复回退因此**零副作用、幂等**,不会出现「幽灵影响」。
|
package/docs/architecture.md
CHANGED
|
@@ -17,12 +17,9 @@ credentials access.
|
|
|
17
17
|
|
|
18
18
|
```
|
|
19
19
|
src/
|
|
20
|
-
├── index.ts host plugin: /rewind, /undo, /snapshot-auto-cleanup
|
|
21
|
-
│
|
|
20
|
+
├── index.ts host plugin: /rewind, /undo, /snapshot-auto-cleanup
|
|
21
|
+
│ commands + checkpoint pipeline
|
|
22
22
|
├── rewind.ts pure planning: target parsing, surface-range plan, candidate listing
|
|
23
|
-
├── rewind-fix.ts /dsh-rewind-fix orchestration (repair pipeline, locks, rollback)
|
|
24
|
-
├── rewind-marker-repair.ts pure legacy-marker transform (A/B → C)
|
|
25
|
-
├── session-log-io.ts session-log zstd codec + lossless re-encoder (rewind-fix write-back)
|
|
26
23
|
├── snapshot.ts checkpoint store: disk before-backups, journaled restore,
|
|
27
24
|
│ reconcile / continue / rollback, bounded prune
|
|
28
25
|
├── snapshot-cleanup.ts cleanup policy + dsh-settings persistence + auto-sweep throttle
|
|
@@ -33,6 +30,11 @@ src/
|
|
|
33
30
|
pending interaction, locales, styles
|
|
34
31
|
```
|
|
35
32
|
|
|
33
|
+
The old marker-update repair line (`/dsh-rewind-fix` and its `rewind-fix.ts` /
|
|
34
|
+
`rewind-marker-repair.ts` / `session-log-io.ts` modules) was a **temporary
|
|
35
|
+
migration tool** for the DSH `0.1.2-rc.1` → `0.1.3` transition: it shipped
|
|
36
|
+
through the `0.9.x` line and is **removed in the `0.10.x` line**.
|
|
37
|
+
|
|
36
38
|
Two dependency rules keep the design testable:
|
|
37
39
|
|
|
38
40
|
1. **`rewind.ts` is pure** — no I/O, no `Session` dependency; everything
|
|
@@ -89,13 +91,15 @@ plugin versions wrote shapes a newer harness no longer accepts:
|
|
|
89
91
|
inside a closed turn.
|
|
90
92
|
|
|
91
93
|
A/B became unreadable once v2 reserved surface `replace` to a node that cites
|
|
92
|
-
`sourceEventSeqs` (`assistant/message` can no longer carry them).
|
|
93
|
-
|
|
94
|
+
`sourceEventSeqs` (`assistant/message` can no longer carry them). The
|
|
95
|
+
`/dsh-rewind-fix` command rewrote form A/B in closed sessions to form C so a
|
|
96
|
+
newer harness accepts the log — it was a **temporary migration tool** (kept on
|
|
97
|
+
the `0.9.x` line) and is **removed in the `0.10.x` line**.
|
|
94
98
|
|
|
95
99
|
## Checkpoint pipeline (Claude Code before-backup model)
|
|
96
100
|
|
|
97
101
|
```
|
|
98
|
-
tools/execute captureBefore: for write / edit
|
|
102
|
+
tools/execute captureBefore: for write / edit
|
|
99
103
|
(mutating commands only), read the file's BEFORE state;
|
|
100
104
|
subagent edits are NOT tracked (Claude Code alignment).
|
|
101
105
|
tools/post-execute commitEntry: anchor = latest user/message seq; skip
|
package/docs/format.md
CHANGED
|
@@ -158,8 +158,7 @@ Old-format data is never silently re-interpreted.
|
|
|
158
158
|
The snapshot auto-cleanup policy (the `enabled` switch and the `maxAgeDays`
|
|
159
159
|
idle cutoff) is no longer a file: it lives in the **dsh-settings document** under
|
|
160
160
|
the `dsh-rewind-snapshot-cleanup` namespace (validated by a schemastery schema;
|
|
161
|
-
defaults are the `base` layer).
|
|
162
|
-
`<dsh home>/snapshot-cleanup.json`
|
|
163
|
-
|
|
164
|
-
default and is dropped). The last-sweep clock stays in its own
|
|
161
|
+
defaults are the `base` layer). The policy was previously persisted in a legacy
|
|
162
|
+
`<dsh home>/snapshot-cleanup.json` file; that file store and its one-time
|
|
163
|
+
startup migration have been removed. The last-sweep clock stays in its own
|
|
165
164
|
`<dsh home>/snapshot-cleanup-last-sweep.json` state file, which is unchanged.
|
|
@@ -49,12 +49,9 @@ the canonical source; this block only adds the finer-grained client-side files
|
|
|
49
49
|
and packaging entries.
|
|
50
50
|
|
|
51
51
|
```
|
|
52
|
-
src/index.ts host plugin: /rewind|/undo|/snapshot-auto-cleanup
|
|
52
|
+
src/index.ts host plugin: /rewind|/undo|/snapshot-auto-cleanup
|
|
53
53
|
+ checkpoint pipeline (tools/execute|post-execute)
|
|
54
54
|
src/rewind.ts pure planning: target resolution, surface range, candidate listing
|
|
55
|
-
src/rewind-fix.ts /dsh-rewind-fix orchestration (repair pipeline, locks, rollback)
|
|
56
|
-
src/rewind-marker-repair.ts pure legacy-marker transform (A/B → C)
|
|
57
|
-
src/session-log-io.ts session-log zstd codec + lossless re-encoder (rewind-fix write-back)
|
|
58
55
|
src/snapshot.ts checkpoint store (disk before-backups, restore/preview, bounded prune)
|
|
59
56
|
src/snapshot-cleanup.ts cleanup policy + dsh-settings persistence + auto-sweep throttle
|
|
60
57
|
src/session-cwd.ts session-cwd resolution (fs-tools rule)
|
package/docs/rewind-fix.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## Applies to
|
|
6
6
|
|
|
7
7
|
- **DSH**: `0.1.2-rc.1`
|
|
8
|
-
- **dsh-rewind**: `0.9.0-alpha.1`
|
|
8
|
+
- **dsh-rewind**: `0.9.0-alpha.1`, `0.9.0-alpha.2`, `0.9.0`
|
|
9
9
|
|
|
10
10
|
## Background
|
|
11
11
|
|
|
@@ -40,7 +40,7 @@ The command rewrites session files and clears some snapshots, so a backup is a g
|
|
|
40
40
|
cp -r ~/.dsh/sessions ~/.dsh/sessions.backup
|
|
41
41
|
cp -r ~/.dsh/rewind-snapshots ~/.dsh/rewind-snapshots.backup
|
|
42
42
|
```
|
|
43
|
-
Or copy them anywhere convenient.
|
|
43
|
+
Or copy them anywhere convenient. You can also let the AI run the backup for you.
|
|
44
44
|
|
|
45
45
|
### Step 3 · Start a new session, or pick one that was never rewound
|
|
46
46
|
|
|
@@ -50,11 +50,11 @@ The command only handles **closed** sessions, and it can't run on itself. So:
|
|
|
50
50
|
|
|
51
51
|
Then run the command **in this new session**, and it will update the old sessions that need it.
|
|
52
52
|
|
|
53
|
-
>
|
|
53
|
+
> Don't run it in a session that itself needs updating and is currently open — the command skips this session, and any other currently-open/in-use session.
|
|
54
54
|
|
|
55
55
|
### Step 4 · Preview the update scope
|
|
56
56
|
|
|
57
|
-
Type `/dsh-rewind-fix` in the composer and send it. It only scans, doesn't write
|
|
57
|
+
Type `/dsh-rewind-fix` in the composer and send it. It only scans, doesn't write. The editor locks while it runs, which is normal. **Don't switch session windows midway.** When it finishes, it reports how many sessions were scanned, how many will be updated, how many skipped, and how many failed. Confirm those are what you expect before moving on.
|
|
58
58
|
```
|
|
59
59
|
/dsh-rewind-fix
|
|
60
60
|
```
|
|
@@ -67,7 +67,7 @@ Once you're sure, re-enter the command with `--apply` to actually run it:
|
|
|
67
67
|
```
|
|
68
68
|
This really rewrites the session logs and updates the old markers, and **may take a few minutes**. Please let it finish — **don't switch to another session window or close DSH** while it runs: a session you switch to is **safely skipped** (no corruption, but it won't be updated this pass and you'll need to re-run). A session that fails stays as it was, unharmed, and can be updated again later. Sessions that are updated also get their matching **snapshot backups cleared**, so file restore to earlier messages is no longer available for them.
|
|
69
69
|
|
|
70
|
-
### Step 6 · Restart DSH and preview again
|
|
70
|
+
### Step 6 · Restart DSH and preview again
|
|
71
71
|
|
|
72
72
|
After the run, restart DSH, then **preview once more**:
|
|
73
73
|
```
|
package/docs/rewind-fix.zh.md
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
## 适配
|
|
6
6
|
|
|
7
|
-
- **DSH
|
|
8
|
-
- **dsh-rewind
|
|
7
|
+
- **DSH**: `0.1.2-rc.1`
|
|
8
|
+
- **dsh-rewind**: `0.9.0-alpha.1`, `0.9.0-alpha.2`, `0.9.0`
|
|
9
9
|
|
|
10
10
|
## 背景
|
|
11
11
|
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
cp -r ~/.dsh/sessions ~/.dsh/sessions.backup
|
|
41
41
|
cp -r ~/.dsh/rewind-snapshots ~/.dsh/rewind-snapshots.backup
|
|
42
42
|
```
|
|
43
|
-
|
|
43
|
+
或者复制到任意合适的位置。你也可以直接让 AI 帮你完成数据的备份。
|
|
44
44
|
|
|
45
45
|
### 第三步 · 新建会话,或选一个从未回退过的会话
|
|
46
46
|
|
|
@@ -50,11 +50,11 @@ cp -r ~/.dsh/rewind-snapshots ~/.dsh/rewind-snapshots.backup
|
|
|
50
50
|
|
|
51
51
|
然后在**这个新会话窗口里**运行命令,去更新那些需要处理的旧会话。
|
|
52
52
|
|
|
53
|
-
>
|
|
53
|
+
> 别在「本身就需要更新、且正开着」的会话里运行——命令会跳过本会话,以及任何正被打开/使用的会话。
|
|
54
54
|
|
|
55
55
|
### 第四步 · 预览更新范围
|
|
56
56
|
|
|
57
|
-
在编辑区域输入 `/dsh-rewind-fix`
|
|
57
|
+
在编辑区域输入 `/dsh-rewind-fix` 并发送。它只扫描、不写盘。执行时编辑区会正常锁定。**不要中途切换会话窗口。**完成后会告诉你:扫描了几个会话、其中几个将被更新、几个跳过、几个失败。确认是你预期的那几项,再进下一步。
|
|
58
58
|
```
|
|
59
59
|
/dsh-rewind-fix
|
|
60
60
|
```
|
|
@@ -67,7 +67,7 @@ cp -r ~/.dsh/rewind-snapshots ~/.dsh/rewind-snapshots.backup
|
|
|
67
67
|
```
|
|
68
68
|
这一步会真的改动会话日志、把旧标记更新成新格式,**可能需要几分钟**。请耐心等它跑完,**不要中途切换会话窗口**或关闭 DSH——被切到的会话会被**安全地跳过**(不损坏,但这次不会更新,需重新执行)。更新失败的会话保持原状态不变、无破坏,可重新进行更新。被更新的会话会同时**清掉对应的文件快照备份**,更早消息回退时文件还原不可用。
|
|
69
69
|
|
|
70
|
-
### 第六步 · 重启 DSH
|
|
70
|
+
### 第六步 · 重启 DSH,再预览确认
|
|
71
71
|
|
|
72
72
|
执行完后重启一下 DSH,然后**再跑一次预览**:
|
|
73
73
|
```
|
package/lib/client.js
CHANGED
|
@@ -446,7 +446,12 @@ var STYLE = `
|
|
|
446
446
|
line-height: 1.5;
|
|
447
447
|
color: var(--dsw-alias-label-error);
|
|
448
448
|
}
|
|
449
|
-
/* Switch row: label left, role=switch button right, hint below (Subagent module).
|
|
449
|
+
/* Switch row: label left, role=switch button right, hint below (Subagent module).
|
|
450
|
+
* The track mirrors the harness ui-primitives Switch (0.1.3-alpha.2 line): the
|
|
451
|
+
* on/off appearance keys off aria-checked rather than a parallel class, so the
|
|
452
|
+
* visual state cannot disagree with the state assistive technology reads, and
|
|
453
|
+
* corner-shape: round opts the capsule track out of the global superellipse
|
|
454
|
+
* (which would square the capsule ends off against the round thumb inside). */
|
|
450
455
|
.dsh-rewind-cleanup-toggle-row {
|
|
451
456
|
display: flex;
|
|
452
457
|
align-items: flex-start;
|
|
@@ -469,10 +474,11 @@ var STYLE = `
|
|
|
469
474
|
padding: 2px;
|
|
470
475
|
border: 0;
|
|
471
476
|
border-radius: 10px;
|
|
477
|
+
corner-shape: round;
|
|
472
478
|
background: var(--dsw-alias-border-l3);
|
|
473
479
|
cursor: pointer;
|
|
474
480
|
}
|
|
475
|
-
.dsh-rewind-cleanup-switch-
|
|
481
|
+
.dsh-rewind-cleanup-switch[aria-checked='true'] {
|
|
476
482
|
background: var(--dsw-alias-brand-primary);
|
|
477
483
|
}
|
|
478
484
|
.dsh-rewind-cleanup-switch:disabled {
|
|
@@ -492,7 +498,7 @@ var STYLE = `
|
|
|
492
498
|
background: var(--dsw-alias-label-primary-foreground);
|
|
493
499
|
transition: transform 120ms ease;
|
|
494
500
|
}
|
|
495
|
-
.dsh-rewind-cleanup-switch-
|
|
501
|
+
.dsh-rewind-cleanup-switch[aria-checked='true'] .dsh-rewind-cleanup-thumb {
|
|
496
502
|
transform: translateX(16px);
|
|
497
503
|
}
|
|
498
504
|
.dsh-rewind-cleanup-input {
|
|
@@ -1333,8 +1339,8 @@ function createRewindBridge(deps) {
|
|
|
1333
1339
|
}
|
|
1334
1340
|
|
|
1335
1341
|
// src/client/build-info.ts
|
|
1336
|
-
var PLUGIN_VERSION = true ? "0.
|
|
1337
|
-
var BUILD_HASH = true ? "
|
|
1342
|
+
var PLUGIN_VERSION = true ? "0.10.0-alpha.1" : "dev";
|
|
1343
|
+
var BUILD_HASH = true ? "7022eaa4" : "dev";
|
|
1338
1344
|
|
|
1339
1345
|
// src/client/locales.ts
|
|
1340
1346
|
var zh = {
|
|
@@ -1531,7 +1537,7 @@ function SettingsCleanupCard({ api, t }) {
|
|
|
1531
1537
|
{
|
|
1532
1538
|
type: "button",
|
|
1533
1539
|
role: "switch",
|
|
1534
|
-
className:
|
|
1540
|
+
className: "dsh-rewind-cleanup-switch",
|
|
1535
1541
|
"aria-checked": draft.enabled,
|
|
1536
1542
|
"aria-labelledby": "dsh-rewind-cleanup-enabled-label",
|
|
1537
1543
|
disabled,
|