dsh-recall-plugin 1.7.1 → 2.1.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/CHANGELOG.md +55 -12
- package/README.en.md +23 -19
- package/README.md +30 -20
- package/lib/client.js +1459 -1266
- package/lib/config.js +43 -2
- package/lib/diagnostics.js +59 -0
- package/lib/errors.js +73 -0
- package/lib/index.js +426 -1000
- package/lib/maintenance.js +263 -145
- package/lib/routes-core.js +162 -0
- package/lib/routes-manage.js +541 -0
- package/lib/scripts.posix.js +165 -27
- package/lib/scripts.pwsh.js +148 -33
- package/lib/session-info.js +71 -0
- package/lib/snapshots.js +305 -78
- package/lib/store.js +157 -19
- package/package.json +65 -54
package/CHANGELOG.md
CHANGED
|
@@ -2,24 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
本文件格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循语义化版本。
|
|
4
4
|
|
|
5
|
+
## [2.1.0] - 2026-08-29
|
|
6
|
+
|
|
7
|
+
改进专项与审查修复、环境诊断批次(错误治理 / POSIX home 三档 / 并发治理)、双平台实弹冒烟(Windows + WSL2 Ubuntu 26.04)后发版。单测 224 项、官方 API 探针、`verify:host`、`check:dsh` 全绿。
|
|
8
|
+
|
|
9
|
+
### 新增
|
|
10
|
+
|
|
11
|
+
- **回退失败救援闭环**(H1):rollback 未输出 ROLLBACK_OK(工作区可能半回退)时,用 execute 预先打下的安全快照(`snap-pre-rollback-<ts>`)自动 reset 回「回退前」状态,提示含「已自动恢复」;救援也失败时给出可直接复制执行的手动命令(空格路径已实弹验证)。
|
|
12
|
+
- **索引原子写与损坏隔离**(H2):index.json/lineage.json 走 tmp+rename 原子写;内容损坏或形状非法时 fail-loud——坏文件改名 `.corrupt-<ts>` 保留现场并告警,孤儿从 tag 重建(时间从 tag creatordate 恢复),不再静默当空。
|
|
13
|
+
- **错误码单一事实源**(H3):`lib/errors.js` 收敛 18 个错误码;无快照撤回 / STALE / AGENT_BUSY 三场景的 client 文案与按钮行为对齐。
|
|
14
|
+
- **client 多文件化**(R1):`src/client/` 源码 + esbuild 打包(产物 `lib/client.js` 随源码提交),CI 钉产物新鲜度(F-G6)。
|
|
15
|
+
- **Host 路由域拆分**(R2):routes-core / routes-manage / session-info 三域,全部 API 可直调。
|
|
16
|
+
- **fork lineage 持久化**(F1):lineage.json 记录撤回链(childId↔parentId),快照管理按链分组展示。
|
|
17
|
+
- **verify-host 装配门禁**(E1):复刻生产装配做结构断言(兄弟提供者桩 + agents 行为),装配回归发版前即可拦截。
|
|
18
|
+
- **环境错误分类与可行动提示**(M1):快照失败按 git 缺失 / 磁盘满 / 无权限 / 锁冲突 / mkdir 冲突分类,toast 与设置页「最近错误」共用同一套可行动中文文案(≤140 字符、不含原始路径);同一错误相邻重复合并 ×N 计数。
|
|
19
|
+
- **POSIX home 三档回退与旧容器迁移**(M2):bash `$DSH_HOME` → Node `DSH_HOME` → `~/.dsh`(第三档补齐 `.dsh` 层,修复快照误落 `~/dsh-recall-snapshots` 的 I24 漂移);旧根级容器首次启动整容器自动迁移(MIGRATE_OK / OLD_ABSENT / BOTH_PRESENT / MIGRATE_FAIL 四态,数据不丢永远优先于路径规范)。
|
|
20
|
+
- **并发治理**(M3):store 心跳文件(宿主 PID + epoch 秒,随每次快照/建库刷新);失败清扫三级让路——另一活实例使用中让路(`CLEANUP_OTHER_INSTANCE`,win32 `Get-Process` / POSIX `kill -0` 探活)→ 5 分钟内新锁让路(`CLEANUP_SKIPPED_FRESH_LOCK`)→ 照常清扫(`CLEANUP_DONE`),根治 issue #11 双实例互踩死循环。
|
|
21
|
+
|
|
22
|
+
### 修复
|
|
23
|
+
|
|
24
|
+
- **PS 5.1 降级环境读编码**:index.json/lineage.json 读取显式 `-Encoding UTF8`——pwsh-local 解析链降级到 PS 5.1 时按 ANSI 活动代码页解码无 BOM UTF-8,中文 root 乱码 → 好索引被误判 corrupt 隔离(双平台实弹复现)。
|
|
25
|
+
- **双实例并发写索引的 tmp-rename 竞态**:并发 saveIndex 时一方 rename 把 `.tmp` 消费掉,另一方报「No such file」刷错误——写侧完整成功后 rename 阶段的 ENOENT 视同成功(同伴已原子落盘),不再进用户错误列表(WSL2 双实例实弹复现)。
|
|
26
|
+
- **冷启动首消息快照丢失**(ensureGit init 竞态):首条消息与启动预热并发时两个 `git init` 同跑,输家 `fatal: cannot mkdir: File exists`——POSIX 版改为 HEAD 复查放行同伴、真失败带诊断退出(WSL2 实弹复现)。
|
|
27
|
+
- **孤儿重建条目 time=0**:重建快照时间从 tag creatordate 恢复——此前重建后管理列表时间前缀缺失、retention/条数上限按「最旧」误清真实快照。
|
|
28
|
+
- **救援链路前缀契约**(F-S1,严重):rescue tag 忘拼 `snap-` 前缀导致 reset 目标必然 unknown revision、救援 100% 走失败分支——修复后救援首次真正生效(实弹验证含空格路径)。
|
|
29
|
+
- 其余审查修复:rebuildOrphans 过滤安全 tag(F-G1)、POSIX rollback 删除侧 rm 失败响亮退出(F-G2)、loadIndex 读截断与损坏区分(F-G3)、errors 测试门禁补强(F-G4)、verify-host 复刻生产装配(F-G5)、产物新鲜度 CI 门禁(F-G6)及 A1-A8 改进项。
|
|
30
|
+
|
|
31
|
+
## [2.0.0] - 2026-08-26
|
|
32
|
+
|
|
33
|
+
P0 防线(撤回防护/时效校验)、P1 工程化(单测/探针/CI)、设置页体验改造与新增四项配置、转向指令消息撤回修复。发版前活体冒烟(浏览器自动化 + 真实 dsh web)通过。
|
|
34
|
+
|
|
35
|
+
### 新增
|
|
36
|
+
|
|
37
|
+
- **运行中撤回防护**(P0-1):目标工作区 agent 正在运行时拒绝发起撤回(preview/execute 均拦截,同会话优先、快照存在时叠加跨会话同工作区检查)——避免用户确认时文件被 agent 改动,预览清单与实际回退内容脱节。拦截依赖 `inject` 声明 `agents` 服务(cordis 4 门禁,冒烟实证:漏声明时静默 fail-open,防护等于没有)。
|
|
38
|
+
- **回退时效校验**(P0-3):preview 之后、execute 之前若该消息又出现了新快照(`previewTotal` 与当前 `recall.total` 不一致),强制重新预览并提示,防止按旧清单回退。
|
|
39
|
+
- **工程化基建**(P1):vitest 单元测试(104 例)+ 官方 API 字段探针(`npm run test:probe`,dsh 升级后本地必跑)+ GitHub Actions CI;快照失败反馈持久化(设置页可回溯最近错误);per-workspace 快照条数硬上限(超出先清最旧)。
|
|
40
|
+
- **新增配置项**:快照总开关 `snapshotEnabled`(关闭只冻结新建、存量快照仍可撤回)、撤回后归档开关 `archiveOriginal`(关闭时原会话保留在侧栏)、按时间保留 `retentionDays`(0 关闭;超期快照自动清理,与条数上限独立触发)。
|
|
41
|
+
- **配置一键恢复默认**:设置页「恢复默认」走官方 `settings.replace` reset 通道(`section: {}` 重置为组合默认并清 user 覆盖层),老版本服务无该 RPC 时降级写默认值。
|
|
42
|
+
- **设置页体验改造**:文件大小上限改 MB 单位输入;快照树「加载更多」与计数修复(缓存全量数组、按 limit 切片);存储健康状态行;快照搜索框;危险操作分级(全删/清空折叠 + 二次确认);操作成功即时反馈;空态引导;「最近错误」可一键清空。
|
|
43
|
+
|
|
44
|
+
### 修复
|
|
45
|
+
|
|
46
|
+
- **转向指令消息缺撤回按钮**:agent 运行中插入的用户输入在 UI 投影层为 `kind=steering`(存储层 `role` 恒 user、无差异),不命中 keyed `user` 渲染器而落到官方默认气泡——keyed 注册扩展为 `['user','steering']`(冒烟实测复现并验证)。
|
|
47
|
+
|
|
5
48
|
## [1.7.1] - 2026-08-25
|
|
6
49
|
|
|
7
50
|
### 修复
|
|
8
51
|
|
|
9
52
|
- 历史会话中用户消息图片从未渲染([#9](https://github.com/limbo947/dsh-recall-plugin/issues/9)):插件渲染器读取的 `props.loadImage` 在官方 `conversation.chat.node` slot 契约中**从不存在**(实际入口是 `props.renderMessageImages`),自研加载链在守卫处直接 return——v1.6.2 的重试链、v1.7.0 的失败按钮全部从未执行,图片永久无声空白(v1.6.2/#8 的修复因此「修了却无效」)。用户消息图片改走官方 `renderMessageImages` 管线(自带鉴权、缓存、失败重试与灯箱预览),布局对齐官方(图片在上、气泡在下);自研 `ImageBox`/`useImageSrc` 及对应 CSS 作为死代码移除。
|
|
10
53
|
|
|
11
|
-
## [1.7.0] - 2026-08-25
|
|
12
|
-
|
|
13
|
-
### 新增
|
|
14
|
-
|
|
15
|
-
- 快照失败/跳过可见性([#7](https://github.com/limbo947/dsh-recall-plugin/issues/7) 加固项 1):快照失败或熔断时客户端 toast 提示(同一故障文本 10 分钟节流,避免持续故障期间刷屏),轮询到失败即终止、不再空等 20 次;熔断期间的新消息会收到「已暂停,N 分钟后自动重试」提示而非沉默。「按钮为什么消失了」的排障成本由此消掉。
|
|
16
|
-
- `git add --ignore-errors` fail-open 兜底([#7](https://github.com/limbo947/dsh-recall-plugin/issues/7) 加固项 3):无法索引的路径(无提交的嵌入式仓库、不可读文件等)以退出码 1 结束但索引照常落盘——快照缺个别路径可接受,好过整条快照 fatal。被跳过的路径以 SNAP_SKIP 行回传,客户端提示「快照已跳过未纳入的路径」(这些路径撤回时既不恢复也不会被删,与排除表语义一致)。
|
|
17
|
-
- 失败后孤儿进程清扫 + stale 锁清理([#7](https://github.com/limbo947/dsh-recall-plugin/issues/7) 加固项 4):runShell 失败路径按 `--git-dir=<本仓库>` 命令行标记定位漏网孤儿进程并终止(win: `taskkill /T /F`,POSIX: `pgrep`+`kill`),随后清理 index.lock 等残留锁——DSH subprocess 服务的树级终止有竞态窗口,且 git 被硬杀不做锁回收,残留的 index.lock 会让后续每条快照持续 fatal。
|
|
18
|
-
|
|
19
|
-
### 修复
|
|
20
|
-
|
|
21
|
-
- `git add` fatal 时脚本假成功(空树快照):pwsh 对原生命令非零退出不抛错(ErrorActionPreference 不作用于 native),此前 add fatal 后脚本会带着未更新的旧索引继续走完 write-tree/commit/tag,产出空树 tag 且退出码 0——快照「成功」却什么都回退不了。现显式检查退出码(≥2 抛错终止),diff/rollback 的同款 add 一并修复。
|
|
22
|
-
|
|
54
|
+
## [1.7.0] - 2026-08-25
|
|
55
|
+
|
|
56
|
+
### 新增
|
|
57
|
+
|
|
58
|
+
- 快照失败/跳过可见性([#7](https://github.com/limbo947/dsh-recall-plugin/issues/7) 加固项 1):快照失败或熔断时客户端 toast 提示(同一故障文本 10 分钟节流,避免持续故障期间刷屏),轮询到失败即终止、不再空等 20 次;熔断期间的新消息会收到「已暂停,N 分钟后自动重试」提示而非沉默。「按钮为什么消失了」的排障成本由此消掉。
|
|
59
|
+
- `git add --ignore-errors` fail-open 兜底([#7](https://github.com/limbo947/dsh-recall-plugin/issues/7) 加固项 3):无法索引的路径(无提交的嵌入式仓库、不可读文件等)以退出码 1 结束但索引照常落盘——快照缺个别路径可接受,好过整条快照 fatal。被跳过的路径以 SNAP_SKIP 行回传,客户端提示「快照已跳过未纳入的路径」(这些路径撤回时既不恢复也不会被删,与排除表语义一致)。
|
|
60
|
+
- 失败后孤儿进程清扫 + stale 锁清理([#7](https://github.com/limbo947/dsh-recall-plugin/issues/7) 加固项 4):runShell 失败路径按 `--git-dir=<本仓库>` 命令行标记定位漏网孤儿进程并终止(win: `taskkill /T /F`,POSIX: `pgrep`+`kill`),随后清理 index.lock 等残留锁——DSH subprocess 服务的树级终止有竞态窗口,且 git 被硬杀不做锁回收,残留的 index.lock 会让后续每条快照持续 fatal。
|
|
61
|
+
|
|
62
|
+
### 修复
|
|
63
|
+
|
|
64
|
+
- `git add` fatal 时脚本假成功(空树快照):pwsh 对原生命令非零退出不抛错(ErrorActionPreference 不作用于 native),此前 add fatal 后脚本会带着未更新的旧索引继续走完 write-tree/commit/tag,产出空树 tag 且退出码 0——快照「成功」却什么都回退不了。现显式检查退出码(≥2 抛错终止),diff/rollback 的同款 add 一并修复。
|
|
65
|
+
|
|
23
66
|
## [1.6.2] - 2026-08-25
|
|
24
67
|
|
|
25
68
|
### 修复
|
package/README.en.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|

|
|
9
9
|

|
|
10
10
|

|
|
11
|
-

|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
**Under any message you've sent**, **click "↶ Recall"**, **and both your workspace files and the conversation history roll back to the moment right before that message was sent**.
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|

|
|
20
20
|
|
|
21
21
|
---
|
|
22
|
-
| Confirmation panel · file change list | |
|
|
22
|
+
| Confirmation panel · file change list | Confirmation panel · rollback scope |
|
|
23
23
|
| --- | --- |
|
|
24
|
-
|  |  |
|
|
24
|
+
|  |  |
|
|
25
25
|
|
|
26
|
-
- After a recall, the message text is auto-refilled into the input box for quick editing and resending (can be disabled in the settings card)
|
|
26
|
+
- After a recall, the message text is auto-refilled into the input box for quick editing and resending (can be disabled in the settings card)
|
|
27
27
|
- Settings · plugin config card (thresholds / exclusions / snapshot manager, saved changes apply live)
|
|
28
28
|
|
|
29
29
|
| Settings | Settings |
|
|
@@ -41,8 +41,11 @@
|
|
|
41
41
|
- **Keeps your project directory clean**: snapshots always live under `$DSH_HOME`, nothing is ever dropped into your project — regardless of the session's sandbox permission (workspace-write / read-only sessions snapshot and recall as usual). Only when home itself is unwritable (e.g. pointed at a read-only drive) does it fall back to an in-project `.dsh-recall-snapshots` directory (the page shows a notice when degraded); once home is writable again, data migrates back and the fallback directory is cleaned up.
|
|
42
42
|
- **Change your mind as many times as you like**: as long as the session still exists (including archived ones), snapshots are fully retained and never pruned. After one recall you can recall again to an even earlier point; files overwritten during a recall always remain recoverable. Once a session is permanently deleted, its snapshots are cleaned up accordingly (see below).
|
|
43
43
|
- **See the list before you act**: clicking recall first shows the list of files that will change (modified / restored / deleted); nothing is overwritten until you confirm.
|
|
44
|
-
- **Disk-friendly**: snapshots use git delta compression — incremental, not full-directory copies. Files larger than 100MB are skipped automatically.
|
|
45
|
-
- **Automatic housekeeping**: periodic `git gc` packs loose objects (lossless — not a single snapshot is lost); snapshots of deleted sessions are cleaned up automatically; build artifacts can be excluded globally via `exclude.txt` (see below).
|
|
44
|
+
- **Disk-friendly**: snapshots use git delta compression — incremental, not full-directory copies. Files larger than 100MB are skipped automatically (the threshold is configurable in the settings card).
|
|
45
|
+
- **Automatic housekeeping**: periodic `git gc` packs loose objects (lossless — not a single snapshot is lost); snapshots of deleted sessions are cleaned up automatically; build artifacts can be excluded globally via `exclude.txt` (see below).
|
|
46
|
+
- **Failures speak up** (1.7.0+): snapshot failures, skipped paths, and circuit-breaker pauses all surface as a toast at the top of the page (the same fault only bothers you once per 10 minutes) — nothing fails silently; the failure reason lands in the "Recent errors" section of the settings card.
|
|
47
|
+
- **Self-healing on failure** (1.7.0+): after a snapshot fails, leftover objects are pruned automatically; 3 consecutive failures trigger an exponential-backoff circuit breaker (auto-retry after the cooldown); the failure path also sweeps stray git processes and stale locks — the disk never bloats from failed retries, and a single hiccup can't wedge the pipeline.
|
|
48
|
+
- **Unindexable paths are skipped, not fatal** (1.7.0+): embedded git repositories, unreadable files, and other paths that can't be indexed no longer fail the whole snapshot — the snapshot is still taken, and skipped paths are reported via toast (on recall they are neither restored nor deleted, same semantics as exclusions).
|
|
46
49
|
- **Tree-view snapshot manager**: the "Snapshot Manager" on the settings page shows a **workspace → session → snapshot** three-level tree with expand/collapse support; each level has a delete button on its right, so you can clear all snapshots of a workspace or a session at once. Leaves show a summary of the message content the snapshot corresponds to, making it easy to locate "what this message changed back then".
|
|
47
50
|
|
|
48
51
|
## Known Limitations
|
|
@@ -50,8 +53,9 @@
|
|
|
50
53
|
- Snapshots are created **when a message is sent**; messages from before the plugin was enabled have no snapshot and show no recall button.
|
|
51
54
|
- The first user message of a session cannot roll back the conversation (files only), because fork requires an earlier turn boundary.
|
|
52
55
|
- Supports Windows (PowerShell 5.1/7 + git CLI) and Linux/macOS (bash + git CLI). Windows is thoroughly verified on real machines; Linux has been fully tested on WSL2 (Ubuntu 26.04, bash 5.3 + git 2.53), including Chinese paths, home fallback, session cleanup, and gc; the macOS side is written to be bash 3.2 compatible but has not been tested on real hardware yet.
|
|
53
|
-
- Nested git repositories inside the workspace (subdirectories with their own `.git`)
|
|
56
|
+
- Nested git repositories inside the workspace (subdirectories with their own `.git`) cannot be indexed: the snapshot proceeds for everything else (fail-open, with a toast listing the skipped paths), but their contents do not participate in recalls.
|
|
54
57
|
- Extreme cases like filenames containing newlines/TAB are beyond the diff list's parsing capability (negligible probability).
|
|
58
|
+
- **Interplay with dsh-routing-suite (progressive tool-disclosure router)**: if you also run the router-standard preset, a recall forks a new session via `sessions.fork`, which resets the router's stage to its default (the tool surface temporarily narrows). Symptoms, root cause and the fix are documented in [docs/routing-interplay.md](docs/routing-interplay.md) (Chinese).
|
|
55
59
|
|
|
56
60
|
## Installation
|
|
57
61
|
|
|
@@ -61,7 +65,7 @@ Prerequisites: git CLI (without it the recall button won't appear and a notice s
|
|
|
61
65
|
```powershell
|
|
62
66
|
dsh plugin --profile web add dsh-recall-plugin
|
|
63
67
|
```
|
|
64
|
-
- Or install directly from git
|
|
68
|
+
- Or install directly from git:
|
|
65
69
|
```powershell
|
|
66
70
|
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
|
|
67
71
|
```
|
|
@@ -96,7 +100,7 @@ Snapshots are fully retained as long as "the session might still be recoverable"
|
|
|
96
100
|
*.log
|
|
97
101
|
```
|
|
98
102
|
|
|
99
|
-
This applies to all projects (when home is unwritable and a workspace falls back to in-project storage, it gets its own independent exclusion config, listed as a separate card in the settings tab). New exclusions only affect future snapshots; **when recalling to an earlier snapshot, files that weren't excluded at that time are still restored** (returning to the state as it was — that's exactly what recall means). To fully purge a directory that already made it into snapshots, manually delete the corresponding hash directory under `dsh-recall-snapshots/` in home. The settings card requires DSH's built-in settings page (all 0.1.0-rc.x releases have it); on very old versions without the tab, editing the file directly is equivalent.
|
|
103
|
+
This applies to all projects (when home is unwritable and a workspace falls back to in-project storage, it gets its own independent exclusion config, listed as a separate card in the settings tab). New exclusions only affect future snapshots; **when recalling to an earlier snapshot, files that weren't excluded at that time are still restored** (returning to the state as it was — that's exactly what recall means). To fully purge a directory that already made it into snapshots, manually delete the corresponding hash directory under `dsh-recall-snapshots/` in home. The settings card requires DSH's built-in settings page (all 0.1.0-rc.x releases have it); on very old versions without the tab, editing the file directly is equivalent.
|
|
100
104
|
- **Tree-view snapshot manager**: open "**Settings → Plugins → Recall Plugin → Snapshot Manager**" to see the tree list — first level workspace (folder name), second level session (session title), third level snapshot (time + message content summary, hover to see the full content). Workspace and session nodes support expand/collapse; every level has a delete button on its right, with an inline confirmation before deletion. Deleting a workspace = clearing all snapshots of that workspace; deleting a session = clearing all snapshots of that session within that workspace; deleting a leaf = removing just that single snapshot.
|
|
101
105
|
|
|
102
106
|
## How It Works
|
|
@@ -111,21 +115,21 @@ When each user message is sent (before the agent touches any files), the workspa
|
|
|
111
115
|
git --git-dir="<store>\git\.git" ls-tree -r --name-only snap-<messageID>
|
|
112
116
|
```
|
|
113
117
|
|
|
114
|
-
|
|
115
|
-
|
|
116
118
|
## Local Development (without publishing)
|
|
117
119
|
|
|
120
|
+
Point the profile's dependency for this package at your clone via `link:`, and changes take effect after restarting DSH (the workspace `lib/` IS the running code — no copying or publishing needed):
|
|
121
|
+
|
|
118
122
|
```powershell
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
#
|
|
126
|
-
# then restart DSH and hard-refresh the page
|
|
123
|
+
# 1. Edit $env:USERPROFILE\.dsh\profiles\web\package.json:
|
|
124
|
+
# in "dependencies", set "dsh-recall-plugin": "link:<path-to-your-clone>\dsh-recall-plugin"
|
|
125
|
+
# "dsh.profile.bundles" should already contain "dsh-recall-plugin" (run the official install command once)
|
|
126
|
+
# 2. Install in the profile directory and restart
|
|
127
|
+
cd $env:USERPROFILE\.dsh\profiles\web
|
|
128
|
+
pnpm install
|
|
129
|
+
# 3. Restart DSH and hard-refresh the page (Ctrl+Shift+R)
|
|
127
130
|
```
|
|
128
131
|
|
|
132
|
+
|
|
129
133
|
## License
|
|
130
134
|
|
|
131
135
|
MIT
|
package/README.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# dsh-recall-plugin
|
|
2
2
|
|
|
3
|
-
> 撤回一条消息,项目文件也一起回去。
|
|
4
|
-
|
|
5
3
|
简体中文 | [English](README.en.md)
|
|
6
4
|
|
|
7
5
|

|
|
8
6
|

|
|
9
7
|

|
|
10
|
-

|
|
8
|
+

|
|
12
9
|
|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
13
|
---
|
|
14
|
-
**在任意一条你发过的消息下方**,**点「↶ 撤回」**,**工作区文件和对话历史一起回到那条消息发出之前的状态**。
|
|
14
|
+
**在任意一条你发过的消息下方**,**点「↶ 撤回」**,**工作区文件和对话历史一起回到那条消息发出之前的状态**。(dsh-0.1.1-rc.2)
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
[更新日志](CHANGELOG.md)
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|

|
|
23
23
|
|
|
24
24
|
---
|
|
25
|
-
| 确认面板 ·
|
|
25
|
+
| 确认面板 · 变更文件清单 | 确认面板 · 回退范围说明 |
|
|
26
26
|
| --- | --- |
|
|
27
|
-
|  |  |
|
|
27
|
+
|  |  |
|
|
28
28
|
|
|
29
29
|
- 撤回后自动把消息文本回填到输入框,方便修改后重发(可在设置卡片关闭)
|
|
30
30
|
- 设置页 · 插件配置卡片(阈值 / 排除表 / 快照管理,保存即热生效)
|
|
@@ -39,8 +39,11 @@
|
|
|
39
39
|
- **项目目录保持干净**:快照始终存在 `$DSH_HOME` 下,不会往项目里塞任何东西;与会话的沙箱权限无关(workspace-write / read-only 会话照常快照与回退),仅当 home 本身不可写(如指到只读盘)才降级到项目内 `.dsh-recall-snapshots`(降级时页面会提示),home 恢复后自动迁走、清理干净。
|
|
40
40
|
- **可以反复后悔**:只要会话还在(含归档),快照全量保留、不修剪。撤回一次后还能再撤到更早;撤回时被覆盖的文件也一直找得回来。会话被彻底删除后,其快照随之清理(见下)。
|
|
41
41
|
- **先看清单再动手**:点撤回先弹出将变更的文件清单(修改 / 恢复 / 删除),确认后才执行,不会稀里糊涂覆盖。
|
|
42
|
-
- **磁盘友好**:快照走 git delta 压缩,是增量不是整目录拷贝;超过 100MB
|
|
42
|
+
- **磁盘友好**:快照走 git delta 压缩,是增量不是整目录拷贝;超过 100MB 的大文件自动跳过(阈值可在设置卡片改)。
|
|
43
43
|
- **自动瘦身**:定期 `git gc` 把 loose 对象压 pack(无损,快照一个不丢);会话删除后其快照自动清理;构建产物可经 `exclude.txt` 全局排除(见下)。
|
|
44
|
+
- **失败了会说话**(1.7.0+):快照失败、跳过路径、连续失败熔断都会在页面顶部 toast 提示(同类故障 10 分钟只打扰一次),不会无声失效;失败原因进设置卡片「最近错误」。
|
|
45
|
+
- **故障自愈**(1.7.0+):快照失败后自动清理残骸对象、连续 3 次失败起指数退避熔断(冷却后自动重试),失败路径还会清扫漏网的 git 进程与残留锁——磁盘不会被失败重试撑爆,也不会被一次异常卡死。
|
|
46
|
+
- **个别路径进不去就跳过**(1.7.0+):嵌入式 git 仓库、无读权限等无法索引的路径不再让整条快照失败——快照照常落盘,被跳过的路径 toast 告知(撤回时既不恢复也不删它们,与排除表语义一致)。
|
|
44
47
|
- **树形快照管理**:设置页「快照管理」按 **工作区 → 会话 → 快照** 三级树形展示,支持展开/折叠;每级右侧都有删除按钮,可一次清掉整个工作区或某个会话的全部快照,叶子显示该快照对应的消息内容摘要,方便定位“这条消息当时改了什么”。
|
|
45
48
|
|
|
46
49
|
## 已知限制
|
|
@@ -48,8 +51,9 @@
|
|
|
48
51
|
- 快照在**消息发送时**创建,插件启用前的历史消息没有快照,不显示撤回按钮。
|
|
49
52
|
- 会话第一条用户消息无法回退对话(仅文件回退),因为 fork 需要更早的 turn 边界。
|
|
50
53
|
- 支持 Windows(PowerShell 5.1/7 + git CLI)与 Linux/macOS(bash + git CLI)。Windows 真机验证充分;Linux 已在 WSL2(Ubuntu 26.04,bash 5.3 + git 2.53)实测全流程(含中文路径、home 降级、会话清理、gc);macOS 侧脚本按 bash 3.2 兼容编写,尚未真机实测。
|
|
51
|
-
- 工作区内嵌套的其他 git 仓库(子目录自带 `.git
|
|
54
|
+
- 工作区内嵌套的其他 git 仓库(子目录自带 `.git`)无法索引:快照对其余部分照常(fail-open,页面会提示跳过了哪些路径),但其内容不参与回退。
|
|
52
55
|
- 文件名含换行/TAB 的极端情形不在 diff 清单的解析能力内(概率可忽略)。
|
|
56
|
+
- **与 dsh-routing-suite(渐进式工具披露路由)的交互**:若同时启用 dsh-routing-suite 的 router-standard 预设,撤回会经 `sessions.fork` 出新会话,导致路由阶段重置为默认(工具面临时收窄)。现象、成因与解决方案见 [docs/routing-interplay.md](docs/routing-interplay.md)。
|
|
53
57
|
|
|
54
58
|
## 安装
|
|
55
59
|
|
|
@@ -60,7 +64,7 @@
|
|
|
60
64
|
```powershell
|
|
61
65
|
dsh plugin --profile web add dsh-recall-plugin
|
|
62
66
|
```
|
|
63
|
-
- 也可从 git
|
|
67
|
+
- 也可从 git 直接安装:
|
|
64
68
|
```powershell
|
|
65
69
|
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
|
|
66
70
|
```
|
|
@@ -110,21 +114,27 @@ pm2 restart <你的dsh进程名> # 若用 pm2 托管
|
|
|
110
114
|
git --git-dir="<store>\git\.git" ls-tree -r --name-only snap-<消息ID>
|
|
111
115
|
```
|
|
112
116
|
|
|
113
|
-
|
|
114
|
-
|
|
115
117
|
## 本地开发(无需发布)
|
|
116
118
|
|
|
119
|
+
把 profile 对本包的依赖改成 `link:` 指向克隆目录,改完代码重启 DSH 即生效(工作区 `lib/` 即运行代码,无需复制或发布):
|
|
120
|
+
|
|
117
121
|
```powershell
|
|
118
|
-
#
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
#
|
|
125
|
-
# 然后重启 DSH 并硬刷新页面
|
|
122
|
+
# 1. 编辑 $env:USERPROFILE\.dsh\profiles\web\package.json:
|
|
123
|
+
# "dependencies" 里 "dsh-recall-plugin": "link:<你的克隆路径>\dsh-recall-plugin"
|
|
124
|
+
# "dsh.profile.bundles" 已含 "dsh-recall-plugin"(官方命令装过一次即可)
|
|
125
|
+
# 2. 在 profile 目录安装并重启
|
|
126
|
+
cd $env:USERPROFILE\.dsh\profiles\web
|
|
127
|
+
pnpm install
|
|
128
|
+
# 3. 重启 DSH + 硬刷新页面(Ctrl+Shift+R)
|
|
126
129
|
```
|
|
127
130
|
|
|
131
|
+
|
|
132
|
+
### 测试
|
|
133
|
+
|
|
134
|
+
- `npm test`:纯逻辑单测(vitest,无 DSH 依赖,CI 与本地同跑)——配置解析、快照解析器、脚本模板同名导出契约、客户端纯函数、发布包内容布局、快照索引持久化、存储总量上限;
|
|
135
|
+
- `npm run test:probe`:官方 API 字段探针(依赖本机 dsh 安装;dsh 升级后本地必跑)——钉住 `renderMessageImages`/`node`/`cwd`、`sessions.fork` 的 `atSeq`/`increaseTitle`、`listSessions` 记录结构、`AgentRegistry` 等字段,违反即红(合规清单 #8 的机器化)。
|
|
136
|
+
- CI(GitHub Actions)跑 `npm ci --legacy-peer-deps` + `npm test`(探针只在有 dsh 的机器跑)。
|
|
137
|
+
|
|
128
138
|
## License
|
|
129
139
|
|
|
130
140
|
MIT
|