@xrn1997/dsh-session-delete 0.5.0 → 0.6.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.
Files changed (47) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +165 -141
  3. package/cordis.patch.yml +7 -3
  4. package/icon.svg +18 -18
  5. package/lib/client.js +749 -430
  6. package/lib/index.js +850 -484
  7. package/lib/types/api/attachment-orphans.d.ts +9 -3
  8. package/lib/types/api/attachment.d.ts +17 -7
  9. package/lib/types/api/connection-route.d.ts +23 -0
  10. package/lib/types/api/dispatch.d.ts +24 -17
  11. package/lib/types/api/route-table.d.ts +25 -9
  12. package/lib/types/client/api-base.d.ts +19 -0
  13. package/lib/types/client/batch-bar.d.ts +1 -1
  14. package/lib/types/client/batch-pick.d.ts +19 -0
  15. package/lib/types/client/batch-select.d.ts +7 -5
  16. package/lib/types/client/context-menu-actions.d.ts +47 -0
  17. package/lib/types/client/copy.d.ts +8 -0
  18. package/lib/types/client/delete-confirm.d.ts +2 -2
  19. package/lib/types/client/host-rows.d.ts +27 -32
  20. package/lib/types/client/index.d.ts +2 -0
  21. package/lib/types/client/main-view.d.ts +2 -1
  22. package/lib/types/client/maintenance-settings.d.ts +3 -1
  23. package/lib/types/client/pending-open.d.ts +17 -0
  24. package/lib/types/client/remote.d.ts +22 -19
  25. package/lib/types/client/store.d.ts +1 -7
  26. package/lib/types/client/trash-nav.d.ts +5 -1
  27. package/lib/types/client/trash-view.d.ts +3 -0
  28. package/lib/types/client/ui/MenuItemButton.d.ts +1 -1
  29. package/lib/types/client/ui/Toast.d.ts +4 -1
  30. package/lib/types/client/use-trash-panel-controller.d.ts +1 -1
  31. package/lib/types/config.d.ts +45 -0
  32. package/lib/types/deps.d.ts +8 -3
  33. package/lib/types/domain/closure.d.ts +3 -0
  34. package/lib/types/index.d.ts +18 -16
  35. package/lib/types/ports/attachments-port.d.ts +40 -0
  36. package/lib/types/ports/fs-port.d.ts +10 -0
  37. package/lib/types/ports/host-port.d.ts +4 -2
  38. package/lib/types/shared/wire.d.ts +18 -5
  39. package/lib/types/trash/attachments.d.ts +17 -2
  40. package/lib/types/verbs/errors.d.ts +3 -1
  41. package/lib/types/verbs/orphan-subagents.d.ts +3 -2
  42. package/lib/types/verbs/permanent-removal.d.ts +10 -5
  43. package/locale/en.json +6 -6
  44. package/locale/zh.json +6 -6
  45. package/package.json +122 -117
  46. package/lib/types/api/request-trust.d.ts +0 -45
  47. package/lib/types/ports/connection-port.d.ts +0 -33
package/README.md CHANGED
@@ -1,141 +1,165 @@
1
- # @xrn1997/dsh-session-delete
2
-
3
- [![CI](https://github.com/xrn1997/dsh-session-delete/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/xrn1997/dsh-session-delete/actions/workflows/ci.yml)
4
- [![npm version](https://img.shields.io/npm/v/@xrn1997/dsh-session-delete.svg)](https://www.npmjs.com/package/@xrn1997/dsh-session-delete)
5
- [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
6
- [![Tested with DSH 0.2.0-rc.2 … 0.2.1-rc.5](https://img.shields.io/badge/DSH-0.2.0--rc.2%20%E2%80%A6%200.2.1--rc.5-brightgreen)](#安装)
7
-
8
- 给 DeepSeek Harness(DSH)加一个**删除会话**的能力。DSH 官方有归档、没有删除——归档只是把会话从列表里挪走,文件还在。本插件补上删除,并且让删除可恢复:删除 = 移入回收站,另有一个显式的「彻底删除」。
9
-
10
- ![回收站面板:左列是按项目分组的会话清单,右栏是选中那条的元信息与按块折叠的正文,页脚是整页唯一的实心红按钮「清空回收站…」](docs/screenshots/screenshot-01.png)
11
-
12
- - 安装:`dsh plugin --profile <profile> add @xrn1997/dsh-session-delete`
13
- - 许可:[Apache-2.0](LICENSE)
14
- - 数据:回收站本体留在本机 `$DSH_HOME/session-trash/`(默认 `~/.dsh/session-trash/`),不联网、不上传
15
-
16
- ## 目录
17
-
18
- - [功能特性](#功能特性)
19
- - [安装](#安装)
20
- - [用法](#用法)
21
- - [回收站与数据](#回收站与数据)
22
- - [界面语言](#界面语言)
23
- - [常见问题](#常见问题)
24
- - [开发](#开发)
25
- - [贡献](#贡献)
26
- - [许可](#许可)
27
-
28
- ## 功能特性
29
-
30
- - **删除 = 移入回收站**:会话行「⋯」→「删除」,可随时恢复;删完有一条停 6 秒的撤销提示。删的是当前正打开的会话时,对话会随删除关闭(不会停在「会话不可用」),点撤销会把它重新打开
31
- - **按整组删**:父会话在盘上的子会话与更深后代一起走;任一成员在跑 ⇒ 整组拒绝、零副作用
32
- - **批量删除**:宿主会话列表「⋯」→「多选」,一次确认、一次执行;失败的留在框里可重试,成功的整批撤销
33
- - **回收站面板**:左清单右详情,按项目分组、可折叠、可拖分栏;看得见正文再决定恢复不恢复
34
- - **详情看得到附件**:消息里的图片内联、可点开放大,普通文件给下载 chip;图片加载失败换成占位,不把破图留在屏上(文件下载失败没有页面内提示,浏览器可能把错误响应存成文件)
35
- - **恢复**:单条即点即回,批量带确认;回到各自的原项目目录(删除前你自己归档过的仍保持归档)
36
- - **显式彻底删除**:单条「彻底删除…」与页脚「清空回收站…」共用同一个二次确认;不自动过期
37
- - **手动清理残留**:插件设置页有一张「维护」卡,随时检查两类残留——父会话已不在的子会话,和 `.dsh` 里已没有任何引用的图片副本;看过数量与体积再由你决定清不清,不自动检查、不自动清理
38
- - **失败不吞**:宿主读不到时把原文上屏并给「重试」;不可用时不注册任何入口
39
- - **文案随宿主语言**:中文 / English 挂在宿主 locale 服务上
40
-
41
- ## 安装
42
-
43
- ```bash
44
- dsh plugin --profile <profile> add @xrn1997/dsh-session-delete
45
- dsh plugin --profile <profile> remove @xrn1997/dsh-session-delete
46
- ```
47
-
48
- 装完**重启宿主**(Node 半不走 HMR)。卸载只移除插件,`$DSH_HOME/session-trash/`(默认 `~/.dsh/session-trash/`)下已有的目录不会被自动清理。
49
-
50
- 装法:
51
-
52
- - **npm 安装**(推荐):使用预构建产物,秒装、无需构建授权。
53
- - **GitHub Release 装**(不依赖本包在 npm 上的发布,也不需要构建工具链):发版工作流在 `V*` tag 上产出预构建 tarball。装最新 Release:
54
- `dsh plugin --profile <profile> add https://github.com/xrn1997/dsh-session-delete/releases/latest/download/dsh-session-delete.tgz`
55
- 钉版本就换成 `https://github.com/xrn1997/dsh-session-delete/releases/download/V<版本>/xrn1997-dsh-session-delete-<版本>.tgz`;tarball 自带 `lib/`,装的是预构建产物,宿主能否挂载仍由兼容闸与真机验证决定。宿主不认 URL 形态的参数时,把 `.tgz` 下到本地再按下面离线分发那条装。Releases 页还没有对应版本时,用 npm 或离线分发。
56
- - **离线分发**:`pnpm pack` 出 tarball 后 `dsh plugin --profile <profile> add ./xrn1997-dsh-session-delete-<版本>.tgz`(scoped 包的文件名带作者段)。包里带预构建产物(`prepack` 会替你跑 `build`),这条路不需要为构建脚本授权。
57
-
58
- **兼容性分两层,别混**:
59
-
60
- - **装得上**由 `package.json` 的 `engines.dsh` 决定:宿主拿运行中的版本比这个区间,不满足即拒绝并回滚。窗口是 **`>=0.1.7-rc.2 <0.3.0-0`**(预发布版本参与匹配)。地板是**完整功能**的最低代次:`0.1.7-rc.2` 在 CLI 台架上验过四个槽位齐全、激活零错误;更低的 `0.1.7-rc.1` 缺行首勾选槽位,`0.1.5` 及以前连会话行入口都没有。
61
- - **真跑过**由 `dsh.compatibility.dshReleases` 记录,只列桌面真机实测过的宿主:**DSH Desktop 0.2.0-rc.2、0.2.1-rc.1、0.2.1-rc.2、0.2.1-rc.3、0.2.1-rc.5**(均 `compatible`)。窗口内的其他代次装得上但没在桌面真机上验过;窗口外的一律拒装。
62
-
63
- ## 用法
64
-
65
- **删一条**:会话行「⋯」→「删除」→ 确认框。确认框在点之前就说明**这一组**的规模(「含 N 个子会话,将一起移入回收站」,N>0 才出现),删完那条提示点「撤销」即恢复。
66
-
67
- ![会话行的「⋯」菜单:宿主原有动作之后,本插件加了「多选」与红色的「删除」两行](docs/screenshots/screenshot-02.png)
68
-
69
- 删除按**整组**走:父会话在盘上的子会话与更深后代一起移走(传递闭包,一层层取到底)——那些行宿主本来就不显示。任一成员在跑(**包括列表里看不见的子会话**)⇒ 整组拒绝、零副作用,报的是那个运行中的 id;本插件不替用户终止正在进行的活。
70
-
71
- **删一批**:会话行「⋯」→「多选」进入显式模式。模式内点整行勾选/取消且**不切换会话**,行首出勾选框,浮条常驻(0 条也给退出入口),同一位置在「全选 / 取消全选」之间切换。确认框逐条列出这批会话,执行是一次批量请求:部分失败不关框、原文落在失败那一行,按钮变成「重试这 N 条」,成功的 6 秒内可整批撤销。
72
-
73
- ![批量删除模式:两行已勾选,浮条显示「已选 2 条」与展开的已选清单,动作是「移入回收站 2 条」与「退出多选」](docs/screenshots/screenshot-03.png)
74
-
75
- **管回收站**:侧栏面板里的「回收站」一行(与「插件」同层)。左清单右详情(中央列更窄时改成下钻,「← 返回清单」回来),按项目分组、组头可折叠、两栏之间那根线可拖。详情按块展示这条会话的对话全量:你的提问、宿主注入的上下文、助手文字与思考、工具调用与结果、系统消息与压缩摘要。注入、思考、工具等默认折叠,可逐块或一键展开;长会话顶部有「加载更早」。助手文字与思考按 Markdown 排版,你的提问保持原话。跟着父会话一起进来的子会话不占清单行,入口在父详情的「子会话」段:点一条即切到那个孩子的详情(元信息、正文与分页同一套),头部「← 返回父会话」回到父。
76
-
77
- - **恢复**:单条不需要确认框,放回原项目目录(删除前你自己归档过的仍保持归档;旧版本留下的归档态条目会迁移式取消归档)。原工作区已被删掉也照常恢复(跳过账本挂接,归入「未分组」),清单行在点之前就说这句。
78
- - **批量恢复 / 批量彻底删除**:工具栏「多选」进入,页脚换成两颗动作按钮。组头那颗是**三态**勾选框,点它选上这个项目的全部会话(含折叠起来看不见的)。两者都先确认,逐条执行、失败不连坐,失败的原文留在它自己那行。
79
- - **彻底删除 / 清空**:共用同一个二次确认。单条那张卡片报的是**这一次会释放多少**(父 + 跟着进来的孩子 + 仍留在盘上的后代,与头部合计共用同一算式)。「清空回收站…」先把回收站目录与清单对账一遍再清,所以手工搬进 `session-trash/` 的**认得出**的目录也归它管;认不出的外人目录不动也不列。
80
- - **残留维护在插件设置页**:父会话已不在(既不在会话列表、也不在回收站清册)的子会话宿主客户端整排不显示,回收站里也不会有;`.dsh` 附件库里也可能留下没有任何引用的图片副本。插件详情页的「维护」卡分「孤儿会话」「孤儿附件」两段,都是**手动**:点「检查」只读,看过数量、体积与图片缩略图再确认清理,清完自动重查;永久删除、不搬进回收站、**绝不自动跑**。回收站面板不再扫描残留,顶上只保留彻底删除 / 清空之后的附件清理提示。
81
-
82
- ## 回收站与数据
83
-
84
- | 东西 | 位置 |
85
- | --- | --- |
86
- | 回收站本体 | `$DSH_HOME/session-trash/<时间戳>-<原目录名>/`(默认 `~/.dsh/session-trash/…`) |
87
- | 回收站清单 | 本插件自己的 storage domain(介质在 `$DSH_HOME/storages/`,默认 `~/.dsh/storages/`) |
88
-
89
- - 回收站与 `$DSH_HOME/sessions/`(默认 `~/.dsh/sessions/`)**同卷**:搬进搬出靠整目录 `rename`,原子、瞬时。
90
- - **一格目录 = 一个会话**:父会话与跟着它进来的子会话各占一格,面板上折成一行。手工翻回收站目录时看到比清单多的目录,那是子会话。
91
- - **清单丢了不致命**:会话文件自描述,解压后第一行即 header,含 `id` 与 `cwd`;读取回收站列表(以及清空、恢复、彻底删除与清理无主子会话前)会先与回收站目录对账。
92
- - **不自动过期**:不设天数上限,清空是显式动作;界面显示条数与共可释放量(与彻底删除确认同一口径)。
93
- - **附件**:宿主把对话里的图片/文件副本存在 `$DSH_HOME/attachments/v1`。彻底删除会话时,只清理**只被这些会话引用**的图片副本;共享副本保留,你磁盘上的原图不受影响。普通文件附件目前只渲染、不代删。设置页「维护」卡的「孤儿附件」段可以手动清掉 `.dsh` 里已经没有任何引用的图片副本,同样只动这些副本、源文件不受影响、共享引用保留。
94
- - **无主子会话不在回收站里**:它们的父会话已不存在;清理只清会话目录与会话独占的图片副本(宿主投影缓存不包含在内,共享图片保留,你磁盘上的原图不受影响)。检查与清理都在插件设置页的「维护」卡里手动发起。
95
- - 回收站本体留在本机、不联网、不上传。
96
-
97
- ## 界面语言
98
-
99
- 中文 / English 挂在宿主自己的 locale 服务上,跟随设置的界面语言;服务不可用时退回内置中文。
100
-
101
- ## 常见问题
102
-
103
- **装完侧栏没有「回收站」,会话菜单里也没有「删除」?**
104
-
105
- 先重启宿主。若仍没有,确认这一代宿主上本插件激活过——取数通道探测不过时,本插件一个入口都不注册:页面上看不出它的存在,但也不会因此把宿主拖死。这是有意用「入口不出现」表达不可用,不是禁用态。
106
-
107
- **删完之后侧栏那一行怎么还在?**
108
-
109
- 本插件只在**宿主确实不再列它**时才通告客户端把那一行去掉;拿不准时宁可沉默(那时说「已移除」是假话)。刚巧遇上就刷新页面,那一行会自己消失。本机运行期没打开过的**冷会话**走正常路径,删完即走。
110
-
111
- **正在运行的会话为什么删不掉?**
112
-
113
- 判据用的是宿主自己的活跃检查(与官方归档的准入同源)。一律拒绝,不替用户终止正在进行的活——先停下这个会话再删。**它正在跑的子会话也算**:报告的是那个子会话的 id,而那一行宿主的列表里不显示,所以别看列表就以为删得掉。
114
-
115
- **批量删除/恢复为什么只成功了一部分?**
116
-
117
- 执行是逐条的,失败不会连坐。批量删除的确认框不关,原文留在失败那一行,按钮变成「重试这 N 条」;批量恢复失败的条目留在清单自己那行,多选态保持,成功的已经消失。重试只处理失败名单。
118
-
119
- **把工作区删了,回收站里的会话还能恢复吗?**
120
-
121
- 能。宿主的「删除工作区」只删注册、保留目录和每个会话日志;恢复照常回盘,只是跳过账本挂接,会话落在「未分组」。清单行和批量恢复确认框都会在点之前说明。
122
-
123
- **我把会话目录从回收站手工搬回 `sessions/` 了,为什么列表里没有?**
124
-
125
- 回收站目录只负责文件;恢复还要挂回工作区账本(旧版本留下的归档态条目会迁移式取消归档)。手工搬回不是恢复,下一次读清单会把对应行对账掉。请在面板里点「恢复」。
126
-
127
- **把宿主绑到局域网地址后,操作报「需要宿主的 Web 身份」或「非受信来源」?**
128
-
129
- 本插件的取数门槛与宿主自己的 `/api` 同一套口径:本机与桌面壳照旧,局域网 / 反向代理客户端则要求你已经用 `dsh web` 打印的那一行 URL 打开过页面(宿主签发的 Web 身份)——缺的就是这枚身份时,原文写「需要宿主的 Web 身份」。原文写「非受信来源」说的是另一件事:这条请求的归属不成立,`Host` 不被认为是本次部署的地址,或 `Origin` / `Referer` 与它对不上。常见成因有三种:用自定义域名(含 hosts 文件)访问,却没把它写进宿主 `client-connection` 的 `trustedHosts`——宿主自己的页面同样要求这一条;反向代理改写了 `Host`,它必须保留客户端的原始 `Host`,改写成回环地址时浏览器请求会因 `Origin` / `Referer` 对不上被拒,而不带这两个头的工具请求会被当成本机请求(那一支不要求 Web 身份);或者当前宿主代次没有提供身份服务(`connection`),那时远程请求一律拒——升级宿主,或改从本机访问。绑定时另有一条前提:宿主只接受具体接口地址、拒绝 `0.0.0.0`,请绑到某个具体 IP(例如 `webserver.host: 192.168.50.199`)。
130
-
131
- ## 开发
132
-
133
- 构建、本地调试、门控、真机验证与发版见 [`docs/development.md`](docs/development.md);提交信息与 PR 约定见 [`CONTRIBUTING.md`](CONTRIBUTING.md);架构地图与主人清单见 [`docs/architecture.md`](docs/architecture.md);界面规格见 [`docs/ui-spec.md`](docs/ui-spec.md);文档分层与放置见 [`docs/AGENTS.md`](docs/AGENTS.md);裁决见 [`docs/adr/`](docs/adr/README.md);发布历史见 [`CHANGELOG.md`](CHANGELOG.md)。历史取舍在 git 历史里,README 不复述。
134
-
135
- ## 贡献
136
-
137
- 欢迎 Issue 与 PR。提交信息、PR 约定与发版边界见 [`CONTRIBUTING.md`](CONTRIBUTING.md);提交前按 [`docs/development.md`](docs/development.md) 的「复核门」跑 `pnpm test` 与 `pnpm typecheck`,并确认退出码;提交即表示你同意以 [Apache-2.0](LICENSE) 协议授权你的贡献。
138
-
139
- ## 许可
140
-
141
- [Apache-2.0](LICENSE)
1
+ # @xrn1997/dsh-session-delete
2
+
3
+ [![CI](https://github.com/xrn1997/dsh-session-delete/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/xrn1997/dsh-session-delete/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@xrn1997/dsh-session-delete.svg)](https://www.npmjs.com/package/@xrn1997/dsh-session-delete)
5
+ [![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
6
+ [![Tested with DSH 0.2.0-rc.2 … 0.2.2-rc.1](https://img.shields.io/badge/DSH-0.2.0--rc.2%20%E2%80%A6%200.2.2--rc.1-brightgreen)](#安装)
7
+
8
+ 给 DeepSeek Harness(DSH)加一个**删除会话**的能力。DSH 官方有归档、没有删除——归档只是把会话从列表里挪走,文件还在。本插件补上删除,并且让删除可恢复:删除 = 移入回收站,另有一个显式的「彻底删除」。
9
+
10
+ ![回收站面板:左列是按项目分组的会话清单,右栏是选中那条的元信息与按块折叠的正文,页脚是整页唯一的实心红按钮「清空回收站…」](docs/screenshots/screenshot-01.png)
11
+
12
+ - 安装:`dsh plugin --profile <profile> add @xrn1997/dsh-session-delete`
13
+ - 许可:[Apache-2.0](LICENSE)
14
+ - 数据:回收站本体留在本机 `$DSH_HOME/session-trash/`(默认 `~/.dsh/session-trash/`),不联网、不上传
15
+
16
+ ## 目录
17
+
18
+ - [功能特性](#功能特性)
19
+ - [安装](#安装)
20
+ - [用法](#用法)
21
+ - [回收站与数据](#回收站与数据)
22
+ - [可调项](#可调项)
23
+ - [界面语言](#界面语言)
24
+ - [常见问题](#常见问题)
25
+ - [开发](#开发)
26
+ - [贡献](#贡献)
27
+ - [许可](#许可)
28
+
29
+ ## 功能特性
30
+
31
+ - **删除 = 移入回收站**:会话行「⋯」→「删除」,可随时恢复;删完有一条停 6 秒的撤销提示。删的是当前正打开的会话时,对话会随删除关闭(不会停在「会话不可用」),点撤销会把它重新打开
32
+ - **按整组删**:父会话在盘上的子会话与更深后代一起走;任一成员在跑 ⇒ 整组拒绝、零副作用
33
+ - **批量删除**:宿主会话列表「⋯」→「多选」,一次确认、一次执行;失败的留在框里可重试,成功的整批撤销
34
+ - **回收站面板**:左清单右详情,按项目分组、可折叠、可拖分栏;看得见正文再决定恢复不恢复
35
+ - **详情看得到附件**:消息里的图片内联、可点开放大,普通文件给下载 chip;图片加载失败换成占位,不把破图留在屏上(文件下载失败没有页面内提示,浏览器可能把错误响应存成文件)
36
+ - **恢复**:单条即点即回,批量带确认;回到各自的原项目目录(删除前你自己归档过的仍保持归档)
37
+ - **显式彻底删除**:单条「彻底删除…」与页脚「清空回收站…」共用同一个二次确认;不自动过期
38
+ - **手动清理残留**:插件设置页有一张「维护」卡,随时检查两类残留——父会话已不在的子会话,和 `.dsh` 里已没有任何引用的图片副本;看过数量与体积再由你决定清不清,不自动检查、不自动清理
39
+ - **失败不吞**:宿主读不到时把原文上屏并给「重试」;不可用时不注册任何入口
40
+ - **文案随宿主语言**:中文 / English 挂在宿主 locale 服务上
41
+
42
+ ## 安装
43
+
44
+ ```bash
45
+ dsh plugin --profile <profile> add @xrn1997/dsh-session-delete
46
+ dsh plugin --profile <profile> remove @xrn1997/dsh-session-delete
47
+ ```
48
+
49
+ 装完**重启宿主**(Node 半不走 HMR)。卸载只移除插件,`$DSH_HOME/session-trash/`(默认 `~/.dsh/session-trash/`)下已有的目录不会被自动清理。
50
+
51
+ 装法:
52
+
53
+ - **npm 安装**(推荐):使用预构建产物,秒装、无需构建授权。
54
+ - **GitHub Release 装**(不依赖本包在 npm 上的发布,也不需要构建工具链):发版工作流在 `V*` tag 上产出预构建 tarball。装最新 Release:
55
+ `dsh plugin --profile <profile> add https://github.com/xrn1997/dsh-session-delete/releases/latest/download/dsh-session-delete.tgz`
56
+ 钉版本就换成 `https://github.com/xrn1997/dsh-session-delete/releases/download/V<版本>/xrn1997-dsh-session-delete-<版本>.tgz`;tarball 自带 `lib/`,装的是预构建产物,宿主能否挂载仍由兼容闸与真机验证决定。宿主不认 URL 形态的参数时,把 `.tgz` 下到本地再按下面离线分发那条装。Releases 页还没有对应版本时,用 npm 或离线分发。
57
+ - **离线分发**:`pnpm pack` 出 tarball 后 `dsh plugin --profile <profile> add ./xrn1997-dsh-session-delete-<版本>.tgz`(scoped 包的文件名带作者段)。包里带预构建产物(`prepack` 会替你跑 `build`),这条路不需要为构建脚本授权。
58
+
59
+ **兼容性分两层,别混**:
60
+
61
+ - **装得上**由 `package.json` 的 `engines.dsh` 决定:宿主拿运行中的版本比这个区间,不满足即拒绝并回滚。窗口是 **`>=0.1.7-rc.2 <0.3.0-0`**(预发布版本参与匹配)。地板由两件硬依赖定:`sidebar.session.row.leading`(0.1.7-rc.2 首现)与 `workspaceRegistry.unarchiveSession`;`0.1.7-rc.2` 是第一个同时具备全部所需槽位与服务方法的代次,CLI 台架验过四个槽位齐全、激活零错误。更低的 `0.1.7-rc.1` 缺行首勾选槽位;0.1.7-alpha、0.1.6、0.1.5 还缺会话行菜单/行尾槽位或 `unarchiveSession`,**不要装**。
62
+ - **真跑过**由 `dsh.compatibility.dshReleases` 记录,只列桌面真机实测过的宿主:**DSH Desktop 0.2.0-rc.2、0.2.1-rc.1、0.2.1-rc.2、0.2.1-rc.3、0.2.1-rc.5、0.2.2-rc.1**(均 `compatible`)。窗口内的其他代次装得上但没在桌面真机上验过,不作为推荐目标;窗口外的一律拒装。
63
+ - **部署注意**:exact Fetch 路由的 owner principal 校验(非 owner 回 403)自 `0.2.1-alpha.3` 起才有;更早的代次(含 `0.2.0-rc.2`)只有宿主 `/api` 的 trusted-host / 浏览器认证。单机 web / 桌面标准组合可用;要跑多 Peer 部署,优先名单里带这道校验的实测代次(`0.2.1-rc.1` 起)。
64
+
65
+ ## 用法
66
+
67
+ **删一条**:会话行「⋯」→「删除」→ 确认框。确认框在点之前就说明**这一组**的规模(「含 N 个子会话,将一起移入回收站」,N>0 才出现),删完那条提示点「撤销」即恢复。
68
+
69
+ ![会话行的「⋯」菜单:宿主原有动作之后,本插件加了「多选」与红色的「删除」两行](docs/screenshots/screenshot-02.png)
70
+
71
+ 删除按**整组**走:父会话在盘上的子会话与更深后代一起移走(传递闭包,一层层取到底)——那些行宿主本来就不显示。这里的子会话只指宿主 `origin:"subagent"` 的会话;用「在新对话中分支」产生的普通 fork 是独立会话,删父、恢复都不动它。任一成员在跑(**包括列表里看不见的子会话**)⇒ 整组拒绝、零副作用,报的是那个运行中的 id;本插件不替用户终止正在进行的活。
72
+
73
+ **删一批**:会话行「⋯」→「多选」进入显式模式。模式内点整行勾选/取消且**不切换会话**,行首出勾选框,浮条常驻(0 条也给退出入口),同一位置在「全选 / 取消全选」之间切换。确认框逐条列出这批会话,执行是一次批量请求:部分失败不关框、原文落在失败那一行,按钮变成「重试这 N 条」,成功的 6 秒内可整批撤销。
74
+
75
+ ![批量删除模式:两行已勾选,浮条显示「已选 2 条」与展开的已选清单,动作是「移入回收站 2 条」与「退出多选」](docs/screenshots/screenshot-03.png)
76
+
77
+ **管回收站**:侧栏面板里的「回收站」一行(与「插件」同层)。左清单右详情(中央列更窄时改成下钻,「← 返回清单」回来),按项目分组、组头可折叠、两栏之间那根线可拖。详情按块展示这条会话的对话全量:你的提问、宿主注入的上下文、助手文字与思考、工具调用与结果、系统消息与压缩摘要。注入、思考、工具等默认折叠,可逐块或一键展开;长会话顶部有「加载更早」。助手文字与思考按 Markdown 排版,你的提问保持原话。跟着父会话一起进来的子会话不占清单行,入口在父详情的「子会话」段:点一条即切到那个孩子的详情(元信息、正文与分页同一套),头部「← 返回父会话」回到父。
78
+
79
+ - **恢复**:单条不需要确认框,放回原项目目录(删除前你自己归档过的仍保持归档;旧版本留下的归档态条目会迁移式取消归档)。原工作区已被删掉也照常恢复(跳过账本挂接,归入「未分组」),清单行在点之前就说这句。
80
+ - **批量恢复 / 批量彻底删除**:工具栏「多选」进入,页脚换成两颗动作按钮。组头那颗是**三态**勾选框,点它选上这个项目的全部会话(含折叠起来看不见的)。两者都先确认,逐条执行、失败不连坐,失败的原文留在它自己那行。
81
+ - **彻底删除 / 清空**:共用同一个二次确认。单条那张卡片报的是**这一次会释放多少**(父 + 跟着进来的孩子 + 仍留在盘上的后代,与头部合计共用同一算式)。「清空回收站…」先把回收站目录与清单对账一遍再清,所以手工搬进 `session-trash/` 的**认得出**的目录也归它管;认不出的外人目录不动也不列。
82
+ - **残留维护在插件设置页**:父会话已不在(既不在会话列表、也不在回收站清册)的子会话宿主客户端整排不显示,回收站里也不会有;`.dsh` 附件库里也可能留下没有任何引用的图片副本。插件详情页的「维护」卡分「孤儿会话」「孤儿附件」两段,都是**手动**:点「检查」只读,看过数量、体积与图片缩略图再确认清理,清完自动重查;永久删除、不搬进回收站、**绝不自动跑**。回收站面板不再扫描残留,顶上只保留彻底删除 / 清空之后的附件清理提示。
83
+
84
+ ## 回收站与数据
85
+
86
+ | 东西 | 位置 |
87
+ | --- | --- |
88
+ | 回收站本体 | `$DSH_HOME/session-trash/<时间戳>-<原目录名>/`(默认 `~/.dsh/session-trash/…`) |
89
+ | 回收站清单 | 本插件自己的 storage domain(介质在 `$DSH_HOME/storages/`,默认 `~/.dsh/storages/`) |
90
+
91
+ - 回收站与 `$DSH_HOME/sessions/`(默认 `~/.dsh/sessions/`)**同卷**:搬进搬出靠整目录 `rename`,原子、瞬时。
92
+ - **一格目录 = 一个会话**:父会话与跟着它进来的子会话各占一格,面板上折成一行。手工翻回收站目录时看到比清单多的目录,那是子会话。
93
+ - **清单丢了不致命**:会话文件自描述,解压后第一行即 header,含 `id` 与 `cwd`;读取回收站列表(以及清空、恢复、彻底删除与清理无主子会话前)会先与回收站目录对账。
94
+ - **不自动过期**:不设天数上限,清空是显式动作;界面显示条数与共可释放量(与彻底删除确认同一口径)。
95
+ - **附件**:宿主把对话里的图片/文件副本存在 `$DSH_HOME/attachments/v1`。彻底删除会话时,只清理**只被这些会话引用**的图片副本;共享副本保留,你磁盘上的原图不受影响。普通文件附件目前只渲染、不代删。设置页「维护」卡的「孤儿附件」段可以手动清掉 `.dsh` 里已经没有任何引用的图片副本,同样只动这些副本、源文件不受影响、共享引用保留。
96
+ - **无主子会话不在回收站里**:它们的父会话已不存在;清理只清会话目录与会话独占的图片副本(宿主投影缓存不包含在内,共享图片保留,你磁盘上的原图不受影响)。检查与清理都在插件设置页的「维护」卡里手动发起。
97
+ - 回收站本体留在本机、不联网、不上传。
98
+
99
+ ## 可调项
100
+
101
+ 三只旋钮都有默认值,在宿主 profile 的 `cordis.patch.yml` 里改;不需要改代码:
102
+
103
+ | 键 | 默认值 | 作用 |
104
+ | --- | --- | --- |
105
+ | `orphanPreviewLimit` | `200` | 设置页「孤儿附件」预览清单的条数(数量与字节仍按全量报告) |
106
+ | `maxAttachmentBytes` | `20971520`(20 MiB) | `GET /attachment` 单次响应的字节上限 |
107
+ | `maxJsonRefBytes` | `10485760`(10 MiB) | 附件引用扫描里单个 JSON 引用源的字节上限 |
108
+
109
+ ```yaml
110
+ - insert:
111
+ - id: session-delete
112
+ name: '@xrn1997/dsh-session-delete'
113
+ config:
114
+ orphanPreviewLimit: 200
115
+ maxAttachmentBytes: 20971520
116
+ maxJsonRefBytes: 10485760
117
+ ```
118
+
119
+ 配置在插件激活时归一;未知键、非整数或越界会让这一条激活失败(不会用半套配置启动)。宿主的配置页不保证渲染这三个字段(本仓不引宿主 schema 库,ADR-0037),以 `cordis.patch.yml` 为准。
120
+
121
+ ## 界面语言
122
+
123
+ 中文 / English 挂在宿主自己的 locale 服务上,跟随设置的界面语言;服务不可用时退回内置中文。
124
+
125
+ ## 常见问题
126
+
127
+ **装完侧栏没有「回收站」,会话菜单里也没有「删除」?**
128
+
129
+ 先重启宿主。若仍没有,确认这一代宿主上本插件激活过——取数通道探测不过时,本插件一个入口都不注册:页面上看不出它的存在,但也不会因此把宿主拖死。这是有意用「入口不出现」表达不可用,不是禁用态。
130
+
131
+ **删完之后侧栏那一行怎么还在?**
132
+
133
+ 本插件只在**宿主确实不再列它**时才通告客户端把那一行去掉;拿不准时宁可沉默(那时说「已移除」是假话)。刚巧遇上就刷新页面,那一行会自己消失。本机运行期没打开过的**冷会话**走正常路径,删完即走。
134
+
135
+ **正在运行的会话为什么删不掉?**
136
+
137
+ 判据用的是宿主自己的活跃检查(与官方归档的准入同源)。一律拒绝,不替用户终止正在进行的活——先停下这个会话再删。**它正在跑的子会话也算**:报告的是那个子会话的 id,而那一行宿主的列表里不显示,所以别看列表就以为删得掉。
138
+
139
+ **批量删除/恢复为什么只成功了一部分?**
140
+
141
+ 执行是逐条的,失败不会连坐。批量删除的确认框不关,原文留在失败那一行,按钮变成「重试这 N 条」;批量恢复失败的条目留在清单自己那行,多选态保持,成功的已经消失。重试只处理失败名单。
142
+
143
+ **把工作区删了,回收站里的会话还能恢复吗?**
144
+
145
+ 能。宿主的「删除工作区」只删注册、保留目录和每个会话日志;恢复照常回盘,只是跳过账本挂接,会话落在「未分组」。清单行和批量恢复确认框都会在点之前说明。
146
+
147
+ **我把会话目录从回收站手工搬回 `sessions/` 了,为什么列表里没有?**
148
+
149
+ 回收站目录只负责文件;恢复还要挂回工作区账本(旧版本留下的归档态条目会迁移式取消归档)。手工搬回不是恢复,下一次读清单会把对应行对账掉。请在面板里点「恢复」。
150
+
151
+ **把宿主绑到局域网地址后,插件入口不出现,或操作报「需要宿主的 Web 身份」/「非受信来源」?**
152
+
153
+ 本插件把九段注册到宿主的 exact Fetch 路由(`/api/dsh-session-delete-api/...`),取数门槛就是宿主 `/api` 的那一套:浏览器、桌面壳的请求转发与本机 `curl` 都需要宿主签发的 Web 身份(`dsh web` 那次访问换来的 cookie),不再有回环免身份,也没有旧前缀 fallback。支持面是 web UI 与桌面端,二者都装 `client-connection`;入口探测回 401/403 时插件不注册任何入口(页面表现为插件不存在),不会摆出一个点下去必然失败的入口;操作中途身份失效,原文「需要宿主的 Web 身份」上屏。原文写「非受信来源」说的是另一件事:这条请求的归属不成立,`Host` 不被认为是本次部署的地址,或 `Origin` 与它对不上(宿主 `/api` 查 Host / `sec-fetch-site` / Origin;附件字节段另有插件的同源取数闸,同站/跨站页面与 authority 对不上的 `Origin` / `Referer` 都拒)。常见成因有两种:用自定义域名(含 hosts 文件)访问,却没把它写进宿主 `client-connection` 的 `trustedHosts`——宿主自己的页面同样要求这一条;或者反向代理改写了 `Host`,它必须保留客户端的原始 `Host`。绑定时另有一条前提:宿主只接受具体接口地址、拒绝 `0.0.0.0`,请绑到某个具体 IP(例如 `webserver.host: 192.168.50.199`)。
154
+
155
+ ## 开发
156
+
157
+ 构建、本地调试、门控、真机验证与发版见 [`docs/development.md`](docs/development.md);提交信息与 PR 约定见 [`CONTRIBUTING.md`](CONTRIBUTING.md);架构地图与主人清单见 [`docs/architecture.md`](docs/architecture.md);界面规格见 [`docs/ui-spec.md`](docs/ui-spec.md);文档分层与放置见 [`docs/AGENTS.md`](docs/AGENTS.md);裁决见 [`docs/adr/`](docs/adr/README.md);发布历史见 [`CHANGELOG.md`](CHANGELOG.md)。历史取舍在 git 历史里,README 不复述。
158
+
159
+ ## 贡献
160
+
161
+ 欢迎 Issue 与 PR。提交信息、PR 约定与发版边界见 [`CONTRIBUTING.md`](CONTRIBUTING.md);提交前按 [`docs/development.md`](docs/development.md) 的「复核门」跑 `pnpm test` 与 `pnpm typecheck`,并确认退出码;提交即表示你同意以 [Apache-2.0](LICENSE) 协议授权你的贡献。
162
+
163
+ ## 许可
164
+
165
+ [Apache-2.0](LICENSE)。
package/cordis.patch.yml CHANGED
@@ -1,3 +1,7 @@
1
- - insert:
2
- - id: session-delete
3
- name: '@xrn1997/dsh-session-delete'
1
+ - insert:
2
+ - id: session-delete
3
+ name: '@xrn1997/dsh-session-delete'
4
+ config:
5
+ orphanPreviewLimit: 200
6
+ maxAttachmentBytes: 20971520
7
+ maxJsonRefBytes: 10485760
package/icon.svg CHANGED
@@ -1,18 +1,18 @@
1
- <!--
2
- 插件卡片/组件行的图标(`package.json` 顶层 `icon`,宿主按**图片**读它、不内联 HTML)。
3
-
4
- 形状逐字取自 `@deepseek-ai/dsh-client-ui-primitives@0.2.0-rc.2` 的 `IconTrashOutlineRegular`
5
- (与插件界面里那枚垃圾桶图标同源)。
6
-
7
- 两处与组件版不同:
8
- 1. 颜色写死。图片形式的 SVG **不继承 `currentColor`**(它是一份独立文档),所以不能像组件里那样
9
- 吃宿主的字色 ⇒ 取一个浅色/深色底上都能读的中灰。
10
- 2. 不带 `aria-hidden`。这不是行内构件,可及名由承载它的宿主卡片提供。
11
- -->
12
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="#8a9099" stroke-width="1">
13
- <path d="M1.28149 3.88831H14.7187" />
14
- <path d="M5.41602 3.88833V2.47962C5.41602 2.29282 5.52492 2.11366 5.71876 1.98157C5.9126 1.84948 6.17551 1.77527 6.44964 1.77527H9.55053C9.82466 1.77527 10.0876 1.84948 10.2814 1.98157C10.4753 2.11366 10.5842 2.29282 10.5842 2.47962V3.88833" />
15
- <path d="M2.57349 3.88831L3.19366 13.2943C3.21937 13.5502 3.33952 13.7872 3.53065 13.9593C3.72178 14.1313 3.97016 14.2259 4.22729 14.2246H11.7728C12.0299 14.2259 12.2783 14.1313 12.4694 13.9593C12.6605 13.7872 12.7807 13.5502 12.8064 13.2943L13.4266 3.88831" />
16
- <path d="M6.44946 6.98926V11.1238" />
17
- <path d="M9.55054 6.98926V11.1238" />
18
- </svg>
1
+ <!--
2
+ 插件卡片/组件行的图标(`package.json` 顶层 `icon`,宿主按**图片**读它、不内联 HTML)。
3
+
4
+ 形状逐字取自 `@deepseek-ai/dsh-client-ui-primitives@0.2.0-rc.2` 的 `IconTrashOutlineRegular`
5
+ (与插件界面里那枚垃圾桶图标同源)。
6
+
7
+ 两处与组件版不同:
8
+ 1. 颜色写死。图片形式的 SVG **不继承 `currentColor`**(它是一份独立文档),所以不能像组件里那样
9
+ 吃宿主的字色 ⇒ 取一个浅色/深色底上都能读的中灰。
10
+ 2. 不带 `aria-hidden`。这不是行内构件,可及名由承载它的宿主卡片提供。
11
+ -->
12
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="#8a9099" stroke-width="1">
13
+ <path d="M1.28149 3.88831H14.7187" />
14
+ <path d="M5.41602 3.88833V2.47962C5.41602 2.29282 5.52492 2.11366 5.71876 1.98157C5.9126 1.84948 6.17551 1.77527 6.44964 1.77527H9.55053C9.82466 1.77527 10.0876 1.84948 10.2814 1.98157C10.4753 2.11366 10.5842 2.29282 10.5842 2.47962V3.88833" />
15
+ <path d="M2.57349 3.88831L3.19366 13.2943C3.21937 13.5502 3.33952 13.7872 3.53065 13.9593C3.72178 14.1313 3.97016 14.2259 4.22729 14.2246H11.7728C12.0299 14.2259 12.2783 14.1313 12.4694 13.9593C12.6605 13.7872 12.7807 13.5502 12.8064 13.2943L13.4266 3.88831" />
16
+ <path d="M6.44946 6.98926V11.1238" />
17
+ <path d="M9.55054 6.98926V11.1238" />
18
+ </svg>