dsh-archived-chats 1.1.2 → 1.3.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.md +20 -18
- package/README.zh-CN.md +20 -18
- package/assets/screenshots/preview-01.png +0 -0
- package/assets/screenshots/preview-02.png +0 -0
- package/assets/screenshots/preview-03.png +0 -0
- package/assets/screenshots/preview-04.png +0 -0
- package/assets/screenshots/preview-05.png +0 -0
- package/assets/screenshots/preview-06.png +0 -0
- package/assets/screenshots/preview-07.png +0 -0
- package/assets/screenshots/preview-08.png +0 -0
- package/docs/ARCHITECTURE.en.md +24 -21
- package/docs/ARCHITECTURE.md +28 -21
- package/lib/auto-retention.js +135 -0
- package/lib/client.js +594 -967
- package/lib/history-restore.js +6 -3
- package/lib/index.js +56 -29
- package/lib/legacy-recycle.js +411 -0
- package/lib/recycle.js +3 -2
- package/lib/retention-service.js +4 -6
- package/lib/retention.js +19 -59
- package/lib/types/client/index.d.ts +13 -8
- package/lib/types/index.d.ts +38 -1
- package/lib/workspace-bulk-archive.js +3 -10
- package/package.json +4 -5
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
</div>
|
|
29
29
|
|
|
30
|
-
Session Archive gives DeepSeek Harness a first-class home for chats that disappear from the sidebar after archive. Browse every archived conversation by workspace, search its full content,
|
|
30
|
+
Session Archive gives DeepSeek Harness a first-class home for chats that disappear from the sidebar after archive. Browse every archived conversation by workspace, search its full content, recover deleted chats from the Recycle Bin, and manage them through explicit, reversible workflows.
|
|
31
31
|
|
|
32
32
|
> Formerly **Archived Chats**, now **Session Archive / 会话档案**. The package name, repository, install command, and local data location are unchanged; existing users need no data migration.
|
|
33
33
|
|
|
@@ -46,7 +46,7 @@ dsh plugin --profile web update dsh-archived-chats
|
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
<p align="center">
|
|
49
|
-
<a href="assets/screenshots/preview-03.png"><img src="assets/screenshots/preview-03.png" width="49%" alt="Native read-only
|
|
49
|
+
<a href="assets/screenshots/preview-03.png"><img src="assets/screenshots/preview-03.png" width="49%" alt="Native read-only legacy-data preview with snapshot time and a synthetic stored image"></a>
|
|
50
50
|
<a href="assets/screenshots/preview-07.png"><img src="assets/screenshots/preview-07.png" width="49%" alt="Storage and Retention with session directories, protection snapshots, and policy controls"></a>
|
|
51
51
|
</p>
|
|
52
52
|
|
|
@@ -57,18 +57,20 @@ dsh plugin --profile web update dsh-archived-chats
|
|
|
57
57
|
| **Browse and search** | Workspace-grouped archive browsing, full-text search across messages and tool results, filters, sorting, tags, and notes. |
|
|
58
58
|
| **Archive a workspace** | From **Settings → Session Archive**, choose a workspace and open one confirmation for every eligible chat in it. Empty new-session windows are excluded; the workspace and its directory stay unchanged. |
|
|
59
59
|
| **Read-only preview** | Native conversation layout for Markdown, reasoning, tool activity, JSON, code, and available stored images, with responsive turn navigation. |
|
|
60
|
-
| **
|
|
60
|
+
| **Existing data** | Prior snapshots appear directly in the **Recycle Bin** for read-only preview, recovery as a new archived copy, or confirmed permanent deletion. Archiving no longer creates versions. |
|
|
61
61
|
| **Backup and restore** | JSON + Markdown ZIP export with preview-first, conflict-safe import. Existing session IDs are never overwritten. |
|
|
62
62
|
| **Recoverable deletion** | Snapshot-protected Recycle Bin with immediate Undo, two-level restore, separately confirmed permanent deletion, and an optional direct permanent-delete action for users who do not need recovery. |
|
|
63
|
-
| **Storage and relationships** | Separate storage accounting,
|
|
63
|
+
| **Storage and relationships** | Separate storage accounting, optional automatic Recycle Bin cleanup, and read-only Origins & Branches for forks and subagent trees. |
|
|
64
|
+
|
|
65
|
+
The four main views are **Archived**, **Recycle Bin**, **Storage & Retention**, and **Origins & Branches**. Existing snapshots are preserved during upgrades and folded into the Recycle Bin; the separate History entry and archive-time capture have been retired.
|
|
64
66
|
|
|
65
67
|
## Safety by design
|
|
66
68
|
|
|
67
69
|
- **Local only:** plugin metadata, recycle records, policies, and validated snapshots stay under `$DSH_HOME/plugin-data/archived-chats/`. Nothing is uploaded or cloud-synced.
|
|
68
|
-
- **No silent overwrite:** imports and
|
|
70
|
+
- **No silent overwrite:** imports and legacy-snapshot recovery create or select non-conflicting IDs; they never replace an existing session.
|
|
69
71
|
- **Deletion stays explicit:** ordinary removal enters the Recycle Bin after snapshot protection. Physical removal is available only through confirmed permanent-purge actions.
|
|
70
|
-
- **
|
|
71
|
-
- **Confirmed workspace archive:** the plugin prepares
|
|
72
|
+
- **Optional automatic cleanup:** off by default. After confirming a retention period, expired Recycle Bin chats are permanently deleted while DSH runs, with catch-up on startup. Enabling or shortening the period shows affected chats for confirmation; older saved policies stay disabled.
|
|
73
|
+
- **Confirmed workspace archive:** the chooser lists only workspaces with eligible chats and supports single, multiple, or toggleable Select all selection through a bottom-right Confirm button. The plugin prepares each exact set in the background, skips workspaces that became empty, then shows one aggregate confirmation. Only sessions whose inspected log contains a real `turn/start` are eligible; empty new-session windows and sessions whose content cannot be confirmed are skipped. Each workspace keeps its own five-minute, single-use credential, which excludes chats added later; a running chat is skipped, never stopped or moved.
|
|
72
74
|
- **Backup scope is visible:** ZIP exports preserve complete session JSON and readable Markdown, but do not include attachment bytes or descendant sessions.
|
|
73
75
|
|
|
74
76
|
## Compatibility
|
|
@@ -77,14 +79,14 @@ Features activate from the public capabilities exposed by the DeepSeek Harness H
|
|
|
77
79
|
|
|
78
80
|
| Host capability | Plugin behavior |
|
|
79
81
|
| --- | --- |
|
|
80
|
-
| Archive and session reads | Browsing, search, preview,
|
|
81
|
-
| `settings.section` + public `archiveSession` | The plugin-owned settings page provides
|
|
82
|
+
| Archive and session reads | Browsing, search, preview, legacy-snapshot inventory in the Recycle Bin, storage accounting, and lineage. |
|
|
83
|
+
| `settings.section` + public `archiveSession` | The plugin-owned settings page provides an eligible-only multi-workspace chooser and one aggregate confirmation without requiring a workspace-menu extension slot. Without archive capability, preparation returns `workspace-archive-unsupported` and makes no change. |
|
|
82
84
|
| Attachment reads | Stored images appear in conversation and snapshot previews; without it, text remains readable. |
|
|
83
85
|
| Session-scoped log location | Recycle Bin permanent deletion uses the persistence provider's public `locate(meta)` capability. Providers without a session-scoped location remain unsupported; failed operations retain their rows and display the reason. |
|
|
84
|
-
| Public session writer | ZIP import,
|
|
86
|
+
| Public session writer | ZIP import, legacy-snapshot recovery, and snapshot fallback when an original is missing all write through the Host's public `create` / `append` / `locate` capability, or a dedicated restore entry point where one exists. |
|
|
85
87
|
| Missing write capability | The operation returns `restore-unsupported` without writing or overwriting data. |
|
|
86
88
|
|
|
87
|
-
Back up `$DSH_HOME/plugin-data/archived-chats/` before downgrading to a release that does not
|
|
89
|
+
Back up `$DSH_HOME/plugin-data/archived-chats/` before downgrading to a release that does not understand the unified Recycle Bin or newer snapshot state.
|
|
88
90
|
|
|
89
91
|
## Demo preview
|
|
90
92
|
|
|
@@ -95,16 +97,16 @@ The eight fixed screenshots below come from an isolated Simplified Chinese light
|
|
|
95
97
|
<br>
|
|
96
98
|
<table>
|
|
97
99
|
<tr>
|
|
98
|
-
<td><img src="assets/screenshots/preview-01.png" alt="Session Archive overview with
|
|
100
|
+
<td><img src="assets/screenshots/preview-01.png" alt="Session Archive overview with four management views"><br><sub>Archive overview</sub></td>
|
|
99
101
|
<td><img src="assets/screenshots/preview-02.png" alt="Full-text search, filters, tags, and readable hit excerpts"><br><sub>Full-text search</sub></td>
|
|
100
102
|
</tr>
|
|
101
103
|
<tr>
|
|
102
|
-
<td><img src="assets/screenshots/preview-03.png" alt="Native read-only
|
|
103
|
-
<td><img src="assets/screenshots/preview-04.png" alt="
|
|
104
|
+
<td><img src="assets/screenshots/preview-03.png" alt="Native read-only snapshot preview with a stored image"><br><sub>Read-only preview</sub></td>
|
|
105
|
+
<td><img src="assets/screenshots/preview-04.png" alt="Existing snapshots unified into the Recycle Bin"><br><sub>Unified Recycle Bin</sub></td>
|
|
104
106
|
</tr>
|
|
105
107
|
<tr>
|
|
106
|
-
<td><img src="assets/screenshots/preview-05.png" alt="Irreversible confirmation before
|
|
107
|
-
<td><img src="assets/screenshots/preview-06.png" alt="Recycle Bin
|
|
108
|
+
<td><img src="assets/screenshots/preview-05.png" alt="Irreversible confirmation before emptying the Recycle Bin"><br><sub>Empty Recycle Bin confirmation</sub></td>
|
|
109
|
+
<td><img src="assets/screenshots/preview-06.png" alt="Recycle Bin row and workspace restore and permanent-delete actions"><br><sub>Recycle Bin actions</sub></td>
|
|
108
110
|
</tr>
|
|
109
111
|
<tr>
|
|
110
112
|
<td><img src="assets/screenshots/preview-07.png" alt="Storage accounting and retention policy controls"><br><sub>Storage and retention</sub></td>
|
|
@@ -133,7 +135,7 @@ Session Archive is actively maintained. The latest stable npm release receives f
|
|
|
133
135
|
npm test
|
|
134
136
|
```
|
|
135
137
|
|
|
136
|
-
The suite covers Host and browser behavior, export/import,
|
|
138
|
+
The suite covers Host and browser behavior, export/import, older-snapshot recovery, Recycle Bin, retention, search, responsive layout, public types, package contents, and repository hygiene. It uses isolated temporary data and never reads real sessions.
|
|
137
139
|
|
|
138
140
|
## Uninstall
|
|
139
141
|
|
|
@@ -141,7 +143,7 @@ The suite covers Host and browser behavior, export/import, History, Recycle Bin,
|
|
|
141
143
|
dsh plugin --profile web remove dsh-archived-chats
|
|
142
144
|
```
|
|
143
145
|
|
|
144
|
-
Uninstalling removes only the plugin package. It does not delete local data under `$DSH_HOME/plugin-data/archived-chats/` or trigger Recycle Bin permanent purge. Retained data includes `metadata.json`, `trash.json`, `retention.json`, the `snapshots/` directory, and any legacy `pending-deletions.json` that has not yet been migrated. A later reinstall can use this data. Before permanently removing the directory, restore and back up anything you need, then delete it manually only after confirming that none of its data is still required.
|
|
146
|
+
Uninstalling removes only the plugin package. It does not delete local data under `$DSH_HOME/plugin-data/archived-chats/` or trigger Recycle Bin permanent purge. Retained data includes `metadata.json`, `trash.json`, `legacy-recycle.json`, `retention.json`, the `snapshots/` directory, and any legacy `pending-deletions.json` that has not yet been migrated. A later reinstall can use this data. Before permanently removing the directory, restore and back up anything you need, then delete it manually only after confirming that none of its data is still required.
|
|
145
147
|
|
|
146
148
|
## License
|
|
147
149
|
|
package/README.zh-CN.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
|
-
会话档案为 DeepSeek Harness
|
|
29
|
+
会话档案为 DeepSeek Harness 中归档后从侧边栏消失的聊天提供统一入口。你可以按工作区浏览全部归档聊天、全文搜索对话、从回收站恢复已删除的聊天,并通过明确且可恢复的流程恢复或删除它们。
|
|
30
30
|
|
|
31
31
|
> 原「已归档的聊天」现已更名为「会话档案 / Session Archive」。包名、仓库、安装命令和本地数据位置均未改变,现有用户无需迁移数据。
|
|
32
32
|
|
|
@@ -45,7 +45,7 @@ dsh plugin --profile web update dsh-archived-chats
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
<p align="center">
|
|
48
|
-
<a href="assets/screenshots/preview-03.png"><img src="assets/screenshots/preview-03.png" width="49%" alt="
|
|
48
|
+
<a href="assets/screenshots/preview-03.png"><img src="assets/screenshots/preview-03.png" width="49%" alt="带旧版快照时间和合成图片的原生只读预览"></a>
|
|
49
49
|
<a href="assets/screenshots/preview-07.png"><img src="assets/screenshots/preview-07.png" width="49%" alt="空间与策略中的会话目录、保护快照和保留策略"></a>
|
|
50
50
|
</p>
|
|
51
51
|
|
|
@@ -56,18 +56,20 @@ dsh plugin --profile web update dsh-archived-chats
|
|
|
56
56
|
| **浏览与搜索** | 按工作区浏览归档聊天,全文搜索消息和工具结果,并支持筛选、排序、标签与备注。 |
|
|
57
57
|
| **归档整个工作区** | 从 **设置 → 会话档案** 打开工作区选择器,再用一次确认归档其中全部符合条件的聊天;空白的新会话窗口不会计入,工作区及其目录保持不变。 |
|
|
58
58
|
| **原生只读预览** | 以原生对话布局展示 Markdown、思考过程、工具活动、JSON、代码和可用的已存储图片,并提供响应式轮次导航。 |
|
|
59
|
-
|
|
|
59
|
+
| **已有快照** | 已有快照直接显示在 **回收站**,支持只读预览、恢复为新的归档副本或确认永久删除;归档不再生成版本。 |
|
|
60
60
|
| **备份与恢复** | 导出 JSON + Markdown ZIP,并通过预览优先、冲突安全的流程导入;已有会话 ID 永不覆盖。 |
|
|
61
61
|
| **可恢复删除** | 带保护快照的回收站支持立即撤销、两级恢复,以及单独确认的永久删除。 |
|
|
62
|
-
| **空间与关系** |
|
|
62
|
+
| **空间与关系** | 空间分账、可选的回收站自动清理,以及用于分叉和子代理树的只读「来源与分支」。 |
|
|
63
|
+
|
|
64
|
+
四个主视图为 **已归档**、**回收站**、**空间与策略** 和 **来源与分支**。升级会保留已有快照并统一放入回收站;独立历史版本入口与归档时自动抓取已取消。
|
|
63
65
|
|
|
64
66
|
## 安全设计
|
|
65
67
|
|
|
66
68
|
- **数据只在本机:** 插件元数据、回收记录、策略和已验证快照均保存在 `$DSH_HOME/plugin-data/archived-chats/`,不会上传或云同步。
|
|
67
|
-
- **不静默覆盖:**
|
|
69
|
+
- **不静默覆盖:** 导入和旧快照恢复只创建或选择无冲突 ID,绝不覆盖已有会话。
|
|
68
70
|
- **删除必须明确:** 普通移除会在快照保护后进入回收站;只有经过确认的永久删除操作才会物理清除。
|
|
69
|
-
-
|
|
70
|
-
- **确认工作区归档:**
|
|
71
|
+
- **可选自动清理:** 默认关闭,确认保留期限后,DSH 运行时自动永久删除到期的回收聊天,启动后补清理。开启或缩短期限会先列出受影响聊天供确认;旧版设置不会自动开启。
|
|
72
|
+
- **确认工作区归档:** 选择器只显示有可归档会话的工作区,支持单选、多选和可再次点击取消的“全选”,并统一从右下角“确定”继续。插件在后台分别准备精确集合,跳过准备期间变为空的工作区,再显示一次汇总确认。只有检查到真实 `turn/start` 的会话才符合条件;空白的新会话窗口及无法确认内容的会话都会跳过。每个工作区保留独立的 5 分钟单次凭据,不会纳入之后新建的聊天;运行中的聊天只会跳过,绝不停止或移动。
|
|
71
73
|
- **备份范围清楚:** ZIP 保留完整会话 JSON 和可读 Markdown,但不包含附件二进制或后代会话。
|
|
72
74
|
|
|
73
75
|
## 兼容性
|
|
@@ -76,14 +78,14 @@ dsh plugin --profile web update dsh-archived-chats
|
|
|
76
78
|
|
|
77
79
|
| Host 能力 | 插件行为 |
|
|
78
80
|
| --- | --- |
|
|
79
|
-
| 归档与会话读取 |
|
|
80
|
-
| `settings.section` + 公开 `archiveSession` |
|
|
81
|
+
| 归档与会话读取 | 浏览、搜索、预览、回收站中的旧快照清单、空间分账和会话血缘。 |
|
|
82
|
+
| `settings.section` + 公开 `archiveSession` | 插件自己的设置页提供仅展示可归档项的多工作区选择器和一次汇总确认,不依赖工作区菜单扩展 slot;缺少归档能力时,准备请求返回 `workspace-archive-unsupported`,且不作任何修改。 |
|
|
81
83
|
| 附件读取 | 对话和快照预览可显示已存储图片;缺少时文本内容仍可阅读。 |
|
|
82
84
|
| 会话独立日志位置 | 回收站永久删除使用持久化后端公开的 `locate(meta)` 能力。后端不提供会话独立位置时不支持永久删除;失败的条目保留在列表中并显示具体原因。 |
|
|
83
|
-
| 公开会话 writer | ZIP
|
|
85
|
+
| 公开会话 writer | ZIP 导入、旧快照恢复和原件丢失时的快照回退,都通过 Host 公开的 `create` / `append` / `locate` 能力写入;Host 提供专用恢复入口时优先使用。 |
|
|
84
86
|
| 缺少写入能力 | 操作返回 `restore-unsupported`,不会写入或覆盖数据。 |
|
|
85
87
|
|
|
86
|
-
|
|
88
|
+
降级到不识别统一回收站或新版快照状态的版本前,请备份 `$DSH_HOME/plugin-data/archived-chats/`。
|
|
87
89
|
|
|
88
90
|
## 演示预览
|
|
89
91
|
|
|
@@ -94,16 +96,16 @@ dsh plugin --profile web update dsh-archived-chats
|
|
|
94
96
|
<br>
|
|
95
97
|
<table>
|
|
96
98
|
<tr>
|
|
97
|
-
<td><img src="assets/screenshots/preview-01.png" alt="
|
|
99
|
+
<td><img src="assets/screenshots/preview-01.png" alt="会话档案总览和四个管理视图"><br><sub>归档总览</sub></td>
|
|
98
100
|
<td><img src="assets/screenshots/preview-02.png" alt="全文搜索、筛选、标签与命中摘要"><br><sub>全文搜索</sub></td>
|
|
99
101
|
</tr>
|
|
100
102
|
<tr>
|
|
101
|
-
<td><img src="assets/screenshots/preview-03.png" alt="
|
|
102
|
-
<td><img src="assets/screenshots/preview-04.png" alt="
|
|
103
|
+
<td><img src="assets/screenshots/preview-03.png" alt="带已存储图片的原生只读快照预览"><br><sub>原生只读预览</sub></td>
|
|
104
|
+
<td><img src="assets/screenshots/preview-04.png" alt="已有快照统一进入回收站"><br><sub>统一回收站</sub></td>
|
|
103
105
|
</tr>
|
|
104
106
|
<tr>
|
|
105
|
-
<td><img src="assets/screenshots/preview-05.png" alt="
|
|
106
|
-
<td><img src="assets/screenshots/preview-06.png" alt="
|
|
107
|
+
<td><img src="assets/screenshots/preview-05.png" alt="清空回收站前的不可恢复确认"><br><sub>清空回收站确认</sub></td>
|
|
108
|
+
<td><img src="assets/screenshots/preview-06.png" alt="回收站单条与工作区恢复和永久删除操作"><br><sub>回收站操作</sub></td>
|
|
107
109
|
</tr>
|
|
108
110
|
<tr>
|
|
109
111
|
<td><img src="assets/screenshots/preview-07.png" alt="空间分账和保留策略控件"><br><sub>空间与策略</sub></td>
|
|
@@ -132,7 +134,7 @@ Session Archive 目前处于积极维护状态。最新 npm 稳定版会接收
|
|
|
132
134
|
npm test
|
|
133
135
|
```
|
|
134
136
|
|
|
135
|
-
测试覆盖 Host
|
|
137
|
+
测试覆盖 Host 与浏览器行为、导出导入、旧快照恢复、回收站、保留策略、全文搜索、响应式布局、公开类型、包内容和仓库卫生。测试只使用隔离临时数据,不读取真实会话。
|
|
136
138
|
|
|
137
139
|
## 卸载
|
|
138
140
|
|
|
@@ -140,7 +142,7 @@ npm test
|
|
|
140
142
|
dsh plugin --profile web remove dsh-archived-chats
|
|
141
143
|
```
|
|
142
144
|
|
|
143
|
-
卸载只移除插件包,不会删除 `$DSH_HOME/plugin-data/archived-chats/` 中的本地数据,也不会触发回收站永久删除。保留的数据包括 `metadata.json`、`trash.json`、`retention.json`、`snapshots/` 目录,以及尚未迁移时可能存在的旧版 `pending-deletions.json`。之后重新安装仍可继续使用这些数据。准备彻底删除该目录前,请先恢复并备份需要的内容;只有确认其中的数据都不再需要时,才手动删除整个目录。
|
|
145
|
+
卸载只移除插件包,不会删除 `$DSH_HOME/plugin-data/archived-chats/` 中的本地数据,也不会触发回收站永久删除。保留的数据包括 `metadata.json`、`trash.json`、`legacy-recycle.json`、`retention.json`、`snapshots/` 目录,以及尚未迁移时可能存在的旧版 `pending-deletions.json`。之后重新安装仍可继续使用这些数据。准备彻底删除该目录前,请先恢复并备份需要的内容;只有确认其中的数据都不再需要时,才手动删除整个目录。
|
|
144
146
|
|
|
145
147
|
## 许可证
|
|
146
148
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/ARCHITECTURE.en.md
CHANGED
|
@@ -10,7 +10,7 @@ The plugin has a Host service half and a browser client half:
|
|
|
10
10
|
|
|
11
11
|
- The Host service in lib/index.js runs inside the DSH Web host, reads the workspace registry and session persistence, and exposes local HTTP routes.
|
|
12
12
|
- The browser client in lib/client.js registers the Session Archive settings.section and renders state and actions.
|
|
13
|
-
- Pure domain logic lives in lib/export.js, lib/import.js, lib/restore.js, lib/metadata.js, lib/search.js, lib/stats.js, lib/insights.js, lib/retention.js, lib/retention-service.js, lib/lineage.js, and lib/workspace-bulk-archive.js. lib/persistence-compat.js narrows the current Host's handle-based reads to a private read-only view; lib/history.js owns
|
|
13
|
+
- Pure domain logic lives in lib/export.js, lib/import.js, lib/restore.js, lib/metadata.js, lib/search.js, lib/stats.js, lib/insights.js, lib/retention.js, lib/retention-service.js, lib/auto-retention.js, lib/lineage.js, and lib/workspace-bulk-archive.js. lib/persistence-compat.js narrows the current Host's handle-based reads to a private read-only view; lib/history.js owns legacy-snapshot inventory and preview authorization; lib/history-restore.js owns single-use restore-as-copy transactions; and lib/legacy-recycle.js projects old snapshots into the unified Recycle Bin and persists migration state. lib/trash.js owns the regular recycle catalog, lib/snapshot.js owns verified snapshots, and lib/recycle.js composes the ordinary recycle lifecycle.
|
|
14
14
|
|
|
15
15
|
The browser never reads session files directly. All reads and writes go through Host routes.
|
|
16
16
|
|
|
@@ -26,6 +26,7 @@ GET /plugins/dsh-archived-chats/workspace-archive/workspaces
|
|
|
26
26
|
POST /plugins/dsh-archived-chats/workspace-archive/preview
|
|
27
27
|
POST /plugins/dsh-archived-chats/workspace-archive/apply
|
|
28
28
|
POST /plugins/dsh-archived-chats/retention/policy
|
|
29
|
+
POST /plugins/dsh-archived-chats/retention/policy/preview
|
|
29
30
|
POST /plugins/dsh-archived-chats/retention/preview
|
|
30
31
|
POST /plugins/dsh-archived-chats/retention/apply
|
|
31
32
|
GET /plugins/dsh-archived-chats/lineage
|
|
@@ -54,9 +55,9 @@ POST /plugins/dsh-archived-chats/delete
|
|
|
54
55
|
POST /plugins/dsh-archived-chats/delete-all
|
|
55
56
|
~~~
|
|
56
57
|
|
|
57
|
-
Every mutating route, plus preview, preview/image, search, history/preview, and history/preview/image, requires the `x-dsh-archived-chats: 1` header. `GET /history` returns only bounded safe inventory.
|
|
58
|
+
Every mutating route, plus preview, preview/image, search, history/preview, and history/preview/image, requires the `x-dsh-archived-chats: 1` header. `GET /history` returns only bounded safe inventory. Compatibility snapshot images require both the snapshot identity and the complete projected descriptor to match. History routes remain a migration and read-compatibility layer; the browser no longer exposes a standalone History view.
|
|
58
59
|
|
|
59
|
-
Workspace archive lists only safe workspace summaries. Preview accepts exactly one workspace ID and creates a five-minute, single-use token/nonce for at most 2,000 ordered eligible IDs. Apply accepts
|
|
60
|
+
Workspace archive lists only safe workspace summaries with at least one eligible chat. The browser may select one or more workspaces, but it still calls Preview separately for each workspace. Preview accepts exactly one workspace ID and creates a five-minute, single-use token/nonce for at most 2,000 ordered eligible IDs. The aggregate confirmation retains only nonempty previews; if every workspace became empty, the refreshed chooser returns without an empty-result confirmation. Apply accepts one workspace token and nonce at a time, never caller-selected IDs; the browser consumes those credentials in selection order and combines their safe results. Eligibility requires unarchived membership in the existing workspace, no non-idle Host agent, and an inspected live or persisted event log containing `turn/start`; an empty new-session window is classified as `session-empty`, while an inspection failure is `session-unavailable`, and both fail closed. On Hosts without agent status, a loaded session is conservatively considered live. Candidate inspection is bounded to eight concurrent reads. Each item revalidates membership, archive state, agent status, and conversation content inside the shared lifecycle queue, then invokes the public `workspaceRegistry.archiveSession()` receiver-bound to the registry. New chats after preview are excluded; an item that became live, empty, unavailable, archived, or detached is reported and skipped. Successful archives do not capture snapshots. This feature changes neither workspace membership nor a workspace path or directory, and never moves a chat across workspaces. A Host without public `archiveSession` returns `workspace-archive-unsupported` without mutation.
|
|
60
61
|
|
|
61
62
|
## State and local data
|
|
62
63
|
|
|
@@ -65,15 +66,16 @@ The state route joins archived sessions, workspace, tags, notes, and metadataUpd
|
|
|
65
66
|
~~~text
|
|
66
67
|
$DSH_HOME/plugin-data/archived-chats/metadata.json
|
|
67
68
|
$DSH_HOME/plugin-data/archived-chats/trash.json
|
|
69
|
+
$DSH_HOME/plugin-data/archived-chats/legacy-recycle.json
|
|
68
70
|
$DSH_HOME/plugin-data/archived-chats/retention.json
|
|
69
71
|
$DSH_HOME/plugin-data/archived-chats/snapshots/
|
|
70
72
|
~~~
|
|
71
73
|
|
|
72
|
-
Metadata
|
|
74
|
+
Metadata, recycle catalogs, and the legacy-snapshot migration catalog are versioned. Writes serialize and atomically replace their documents through temporary files. An unreadable or unsupported `trash.json` is preserved byte-for-byte, hides no archived sessions, and disables recycle mutations. An unreadable `legacy-recycle.json` blocks legacy-snapshot migration operations rather than guessing state.
|
|
73
75
|
|
|
74
76
|
The stats route measures session directories with concurrency four, skips symbolic links, and caches results for 30 seconds. A measurement failure marks only that row unavailable; list and mutation actions continue. Delete invalidates the affected cache row.
|
|
75
77
|
|
|
76
|
-
Insights joins session measurement with a stream-verified snapshot inventory and counts repeated snapshot attachments only from validated SHA-256 descriptors. The browser keeps totals in summary cards and presents session/snapshot inventories only in bounded searchable dialogs. retention.json uses an
|
|
78
|
+
Insights joins session measurement with a stream-verified snapshot inventory and counts repeated snapshot attachments only from validated SHA-256 descriptors. The browser keeps totals in summary cards and presents session/snapshot inventories only in bounded searchable dialogs. retention.json uses schema version 2 with an explicit recycleAutoDelete flag. Version-one documents remain readable, force that flag to false, and are not silently rewritten. Only Recycle Bin age contributes cleanup candidates; legacy snapshot-count, age, and quota fields do not schedule snapshot deletion. Policy preview issues a five-minute single-use token/nonce for enabling or shortening, bound to the current policy, proposed policy, and expired candidates. Policy save accepts { policy, confirmation: { token, nonce } } and revalidates under the lifecycle lock; the save request does not perform deletion itself. Automatic checks begin after startup recovery and repeat once a minute without overlap. Each candidate delegates to unified recycle purge, revalidating the setting and record inside its lifecycle lock before writing purge-pending intent. Plugin disposal stops new jobs; already-committed permanent deletions are retried. Legacy retention/preview and retention/apply manual APIs remain compatible, but the UI no longer has an extra manual cleanup-preview step. Lineage uses only durable parentSession edges, never rewrites headers, and resolves titles for at most 100 untitled active source nodes already included in the focused tree. Its 5,000-node cap bounds the PROJECTED graph, not the Host's store: `focusIds` narrows the output to archived and recycled chats plus their explaining context, so a store of 100,000 sessions with 25 archived projects 25 nodes. Header fields are coerced per node rather than validated whole-graph — an unanticipated `origin` value, an absent `createdAt`, a changed numeric type each degrade that node to a value the public LineageNode already allows, and only an unusable identity drops a row. A projection that rejected the whole graph for one unrecognized header let a Host-side change disable the panel with no plugin change at all; malformed workspace and recycle entries are skipped for the same reason.
|
|
77
79
|
|
|
78
80
|
## Preview and full-text search
|
|
79
81
|
|
|
@@ -83,15 +85,15 @@ The preview/image authorization sequence is fixed: first require POST and `x-dsh
|
|
|
83
85
|
|
|
84
86
|
Cross-session persistence inspection is limited to four concurrent reads, stops scheduling batches once the hit limit is satisfied, and aborts an older browser request when a newer search starts. A broken session is reported in `skipped` while other hits still succeed. Canonical projection limits each segment to 256 Ki code points, each message to 1 Mi code points and 1,000 segments, and each session to 10,000 projected messages; unknown structured values are bounded by depth, node, and character budgets before stringify. A 30-second TTL, 64-session LRU, and per-session cache cap keep bounded projections resident. Unarchive, delete, and restore invalidate affected cache entries.
|
|
85
87
|
|
|
86
|
-
##
|
|
88
|
+
## Legacy-snapshot compatibility and unified recycling
|
|
87
89
|
|
|
88
|
-
`history/capture
|
|
90
|
+
Archiving no longer calls `history/capture`; that compatibility route refuses new History captures. Upgrades preserve existing snapshots. `legacy-recycle.js` projects snapshots not referenced by regular recycle records as `legacy:<snapshotId>` Recycle Bin items, so the browser displays them in the unified Recycle Bin. Existing History inventory, preview, restore, and delete routes remain for migration and compatible callers. Recycle Bin operations still capture protection snapshots required for recovery.
|
|
89
91
|
|
|
90
92
|
`history.js` groups published snapshots as `archived`, `recycled`, or `history-only`, inspects no more than 5,000 snapshot directories, shares one in-flight request, and caches completed inventory for 30 seconds. Inventory contains only safe title/workspace title, timestamps, sizes, attachment counts, and protection state; degraded entries expose only snapshot ID and a stable code. Paginated preview and image reads revalidate snapshot identity, digests, and complete descriptors without returning paths or raw records.
|
|
91
93
|
|
|
92
|
-
`history-restore.js` fully validates the snapshot, asks the Host for a new session ID, and issues a five-minute single-use token/nonce. Confirmation consumes the credential before writes and rechecks the manifest, then creates persistence, rewrites session/attachment identities, appends events, restores workspace and metadata, and commits archive registry state last. Failures reverse plugin-controlled steps. The source session and snapshot
|
|
94
|
+
`history-restore.js` fully validates the snapshot, asks the Host for a new session ID, and issues a five-minute single-use token/nonce. Confirmation consumes the credential before writes and rechecks the manifest, then creates persistence, rewrites session/attachment identities, appends events, restores workspace and metadata, and commits archive registry state last. After commit, unified recycling marks the migration state `restore-complete`, then removes the restored snapshot and migration entry; a cleanup failure retains cleanup state without undoing the successfully created archived copy. Failures before commit reverse plugin-controlled steps. The source session and snapshot do not change before commit, and the plugin makes no claim that Host-global attachment objects were deleted.
|
|
93
95
|
|
|
94
|
-
|
|
96
|
+
Legacy-snapshot permanent deletion and Empty Recycle Bin both enter the shared lifecycle queue and bypass the ordinary 30-second cache/in-flight list so current snapshot and regular recycle-protection state is recomputed. A snapshot referenced by a regular recycle record is not also projected as a legacy item. A degraded snapshot cannot be previewed or restored, but it can be permanently deleted through the unified Recycle Bin so its bytes remain reclaimable. Deletion physically removes the plugin snapshot and its attachment copies while leaving the source chat and other snapshots unchanged.
|
|
95
97
|
|
|
96
98
|
## Export flow
|
|
97
99
|
|
|
@@ -118,19 +120,19 @@ import/inspect accepts only version-one ZIPs produced by this plugin. The Host s
|
|
|
118
120
|
5. restore.js uses a feature-detected adapter to write sessions, metadata, and archive state.
|
|
119
121
|
6. Any failure rolls back staged data and never overwrites an existing session.
|
|
120
122
|
|
|
121
|
-
The confirmation token expires quickly, can be used once, and is bounded to eight retained plans and 128 MiB total per process. Confirmation-time conflict revalidation, staging, and commit all run inside the shared lifecycle queue. Import resolves a session writer by capability: a dedicated Host restore entry point when one exists, otherwise the ordinary `create` / `append` / `locate` surface — the same capability
|
|
123
|
+
The confirmation token expires quickly, can be used once, and is bounded to eight retained plans and 128 MiB total per process. Confirmation-time conflict revalidation, staging, and commit all run inside the shared lifecycle queue. Import resolves a session writer by capability: a dedicated Host restore entry point when one exists, otherwise the ordinary `create` / `append` / `locate` surface — the same capability legacy-snapshot recovery writes through, so import works wherever that works. The append writer carries its own session-scoped rollback (it confirms the located directory is the session's own before creating anything), so a separate removal capability is required only for a dedicated restore entry point. Archive and metadata write capabilities are still required. The staged id does not exist yet, so a session reader that fails closed on unknown ids is the expected answer to the capability probe and never aborts the restore. Workspace attach is used only with a matching detach, otherwise the item restores ungrouped with a warning. A boundary that throws after changing state is compensated in reverse order; failed compensation is reported explicitly rather than returning false success.
|
|
122
124
|
|
|
123
125
|
## Recycle and protection-snapshot lifecycle
|
|
124
126
|
|
|
125
127
|
`trash.json` permits only `trashed`, `purge-pending`, and `degraded`. Legal transitions are `missing -> trashed`, `trashed/degraded -> purge-pending`, and removal of an existing state after a committed transaction. A `purge-pending` record cannot restore.
|
|
126
128
|
|
|
127
|
-
Protection manifests use `dsh-archived-chats/snapshot` v1 and session payloads use `dsh-archived-chats/snapshot-session` v1. Each recycle record names one active snapshot
|
|
129
|
+
Protection manifests use `dsh-archived-chats/snapshot` v1 and session payloads use `dsh-archived-chats/snapshot-session` v1. Each regular recycle record names one active snapshot. A valid snapshot left without a regular recycle reference after restore or another recycle cycle automatically appears as a legacy-snapshot item in the unified Recycle Bin until it is restored as a copy or permanently deleted. Exact limits are 4 MiB manifest, 64 MiB session JSON, 1,000 attachments, 32 MiB each, and 512 MiB total. Restore validation streams attachment digests first and rereads one attachment at a time immediately before Host writes, never retaining all attachment bytes together. Snapshot publication/deletion and state-file renames sync file and parent-directory durability, with a safe fallback on Windows filesystems that do not expose directory fsync. Windows cannot atomically replace a file or remove a directory entry while another handle is open on it — an indexer or antivirus scan is enough — so replaces and recursive removals retry the transient `EPERM` / `EACCES` / `EBUSY` codes there, bounded, and only there: on POSIX the same codes are permanent conditions and retrying would only delay the same failure. Snapshot publication also treats a rename refused onto an existing directory as a conflict after probing the destination, because Windows reports that as `EPERM` rather than `EEXIST`. Path containment is tested with the platform separator and rejects an absolute answer, so a Windows `..\` escape or a different drive letter cannot read as inside the root.
|
|
128
130
|
|
|
129
131
|
Move ordering is: validate archive ownership → dispose or park a live session → capture and verify snapshot → recheck ownership → atomically commit `trashed` → invalidate caches. Ordinary move never removes the persistence artifact.
|
|
130
132
|
|
|
131
133
|
Archived sessions also expose an explicit direct permanent-delete action. It uses the same session-scoped physical-delete checks and crash-recovery bracket as Recycle Bin purge, but intentionally skips snapshot creation and recycle storage after a separate irreversible confirmation. Ordinary delete remains recoverable by default.
|
|
132
134
|
|
|
133
|
-
Restore first rejects an existing-ID conflict. With an intact original it restores archive visibility and removes only the recycle record
|
|
135
|
+
Restore first rejects an existing-ID conflict. With an intact original it restores archive visibility and removes only the regular recycle record without rewriting persistence; the protection snapshot then appears as a legacy-snapshot item in the unified Recycle Bin. With a missing original it completes validation and attachment-identity republishing before writing through public `create` / `append` / `saveImage` capabilities. A failure rolls back the new artifact and retains trash.
|
|
134
136
|
|
|
135
137
|
Permanent purge persists `purge-pending` before physical writes, then removes every snapshot for that source, then the original session, and finally the recycle record. The session delete is deliberately last: a failure before it leaves the original intact and the record completable, rather than a `purge-pending` record whose session is already gone and which can therefore neither restore nor complete. The snapshot sweep attributes each published snapshot by manifest identity so a snapshot that fails validation is still removed when it belongs to this session, and an unrelated unverifiable snapshot is skipped instead of aborting the sweep — corruption elsewhere in the store must never make a purge impossible. The recycle record also names its own snapshot id, covering one damaged past attribution. Workspace, metadata, snapshot, or physical-delete failures retain `purge-pending`; snapshot deletion is rescanned before success can be returned. Physical deletion additionally requires the located artifact to sit in a directory named for the session itself, so a backend layout that shares one parent between sessions can never have that parent removed. Startup recovery retries only `purge-pending`, never plain `trashed`. Legacy `pending-deletions.json` is strict read-only migration input: each still-archived ID becomes recoverable trash and is never boot-deleted merely because of the old marker.
|
|
136
138
|
|
|
@@ -138,13 +140,14 @@ Permanent purge persists `purge-pending` before physical writes, then removes ev
|
|
|
138
140
|
|
|
139
141
|
client.js registers an order-30 `settings.section` plus a `shell.overlay`, and uses public Host archive services and design tokens. Workspace archive UI state stays inside the plugin-owned settings section and requires no workspace-action slot or shared client store. The page state includes:
|
|
140
142
|
|
|
141
|
-
- A frame-wide archive success notice in `shell.overlay`: during its effect lifetime the plugin wraps public `workspaces.archiveSession` and
|
|
142
|
-
- An **Archive workspace chats** action in **Settings → Session Archive**:
|
|
143
|
+
- A frame-wide archive success notice in `shell.overlay`: during its effect lifetime the plugin wraps public `workspaces.archiveSession` and reports success only after the original succeeds. View and Undo remain available, with a three-second dismissal. No history capture is requested.
|
|
144
|
+
- An **Archive workspace chats** action in **Settings → Session Archive**: the chooser lists only workspaces with eligible chats and supports single selection, multiple selection, and Select all that toggles off on a second click. The bottom-right Confirm button is the only continuation. The client prepares each selection, drops workspaces that concurrently became empty, and shows one aggregate confirmation with the exact total eligible count, Archived destination, and only a nonzero live-skip count, with no visible session preview. Full success refreshes consumers and closes; any skipped or failed outcome retains the per-item result until dismissed.
|
|
143
145
|
- Archived sessions and workspace groups.
|
|
144
146
|
- Search, type/project/tag filters, and sorting.
|
|
145
147
|
- Tag and note editor.
|
|
146
|
-
-
|
|
147
|
-
- Archived
|
|
148
|
+
- Row actions handle one chat in this order: preview, edit tags and note, permanent delete, and Unarchive; there is no single-chat export. Archive workspace menus provide Export all, Unarchive all, Delete all permanently, and Move all to Recycle Bin in that order. Recycle Bin workspace menus provide Restore all and Delete all permanently. Neither view has multi-select state, row checkboxes, or a batch toolbar.
|
|
149
|
+
- Archived and Recycle Bin title rows provide cross-workspace Delete all and Empty Recycle Bin actions respectively; the latter covers every recycled chat and protection snapshot. Recycle Bin row restore and permanent delete are named, tooltip-backed icon buttons.
|
|
150
|
+
- Four tabs: Archived, Recycle Bin, Storage & Retention, and Origins & Branches. Existing snapshots expose preview, recovery as a new archived copy, and confirmed deletion in the Recycle Bin. Restore confirmation focuses Cancel first and never places token/nonce in the render tree. Storage and relationship views retain bounded dialogs and read-only relationship projection.
|
|
148
151
|
- Import preview, disabled conflicts, and restore results.
|
|
149
152
|
- Responsive settings-page markers and sidebar refresh injection.
|
|
150
153
|
|
|
@@ -159,7 +162,7 @@ The browser never mutates files directly. After an operation, the Host response
|
|
|
159
162
|
## Security and failure policy
|
|
160
163
|
|
|
161
164
|
- All state-changing routes require POST and the guard header.
|
|
162
|
-
- History responses exclude workspace/snapshot/attachment paths, raw events, notes, and confirmation tokens; logs contain only IDs and stable codes.
|
|
165
|
+
- Compatibility History responses and legacy-snapshot Recycle Bin items exclude workspace/snapshot/attachment paths, raw events, notes, and confirmation tokens; logs contain only IDs and stable codes.
|
|
163
166
|
- Workspace archive responses expose only safe workspace IDs/titles, eligible counts, session IDs/titles/timestamps in a confirmed preview, and stable per-item outcomes; workspace paths, event bodies, notes, attachment paths, and confirmation credentials stay out of logs and rendered results.
|
|
164
167
|
- Import limits ZIP size, entries, paths, versions, and JSON structure, rejecting traversal, duplicates, and prototype-pollution keys.
|
|
165
168
|
- Ordinary delete never invokes physical purge; only a committed recycle record can enter purge.
|
|
@@ -171,9 +174,9 @@ The browser never mutates files directly. After an operation, the Host response
|
|
|
171
174
|
|
|
172
175
|
The plugin adapts through Host capability detection: archive reads, attachment reads, persistence writes, physical location, and live-session lifecycle support are evaluated independently, and missing capabilities must degrade safely or return explicit errors. A legacy persistence object with native `inspect` is retained unchanged. The current Host's `list()` snapshots and `open(id, 'read')` handles are adapted into a private `list` / `listSnapshots` / `inspect` read view; every inspection reads from offset 0 and closes its handle after success or failure. The view does not invent `create`, `append`, or `locate`. Ordinary sessions remain browsable, exportable, and snapshot-capable, while session-directory accounting, restore writes, and permanent purge are unavailable through this read-only view. Without physical location, purge returns `purge-unsupported` before changing recycle state, snapshots, pending markers, or live sessions.
|
|
173
176
|
|
|
174
|
-
Snapshot and ZIP schema v1 cannot preserve `inheritedEventCount`. When a current read handle reports an inherited prefix greater than zero, the adapter returns `session-inspection-unsupported` before reading events and still closes the handle, avoiding a silently flattened branch history. Workspace archive
|
|
177
|
+
Snapshot and ZIP schema v1 cannot preserve `inheritedEventCount`. When a current read handle reports an inherited prefix greater than zero, the adapter returns `session-inspection-unsupported` before reading events and still closes the handle, avoiding a silently flattened branch history. Workspace archive no longer depends on snapshot capture. Recycle protection and ZIP export continue to reject unsupported inherited event data. This UI change does not widen the snapshot or restore protocol.
|
|
175
178
|
|
|
176
|
-
On Hosts with the compatible legacy writer surface, Import,
|
|
179
|
+
On Hosts with the compatible legacy writer surface, Import, legacy-snapshot recovery, and snapshot fallback when the original is missing still write through the public `create` / `append` / `locate` capability, or a dedicated restore entry point where the Host offers one; only a Host exposing neither returns `restore-unsupported` without mutation. A capability set that no shipped Host satisfies is not an acceptable guard — it makes the feature permanently dead rather than gracefully degraded. Back up the complete plugin-data directory before downgrading to a release that does not understand the unified Recycle Bin or newer snapshot state.
|
|
177
180
|
|
|
178
181
|
Coverage includes:
|
|
179
182
|
|
|
@@ -184,8 +187,8 @@ Coverage includes:
|
|
|
184
187
|
- stats.js symlink handling, caching, and concurrency limits.
|
|
185
188
|
- search.js message projection, Unicode search, pagination, partial failures, and TTL/LRU caching.
|
|
186
189
|
- trash.js, snapshot.js, and recycle.js format validation, concurrency, recovery, rollback, crash intent, and legacy migration.
|
|
187
|
-
- insights.js, retention.js, retention-service.js, and lineage.js trusted accounting, policy bounds, short-lived authority, revalidation, and bounded graph projection.
|
|
188
|
-
- history.js
|
|
190
|
+
- insights.js, retention.js, retention-service.js, auto-retention.js, and lineage.js trusted accounting, policy bounds, short-lived authority, revalidation, scheduler lifecycle, and bounded graph projection.
|
|
191
|
+
- history.js, history-restore.js, and legacy-recycle.js legacy-snapshot preservation, unified recycle projection, cache invalidation, snapshot authorization, single-use confirmation, transaction rollback, and source immutability.
|
|
189
192
|
- Host routes and browser settings smoke/responsive behavior.
|
|
190
193
|
|
|
191
194
|
Run:
|