dsh-dialogue-cleanup

English · 简体中文

npm version npm downloads GitHub release GitHub stars License: MIT DeepSeek Harness 0.2.0-rc.2

在运行中的 DeepSeek Harness Web 界面里删掉会话 —— 不用重启,也不用离开当前窗口。

会话行 ... 菜单里一项做单条删除,另有一页批量管理面板挂在设置页里。

设置页里的批量管理面板:搜索、筛选、逐行状态徽标与 16 行会话

安装 · 界面 · 实现 · 发布流程 · Releases

## 为什么会有它 **一句话定位:删会话就该真的删掉。** DeepSeek Harness 把一条会话同时放在四个地方 —— 内存 live 条目、工作区记录、注册表残留(pin / archive)、以及磁盘上的目录。只清掉其中一处, 留下的就是一行幽灵会话、一条过期的工作区记录,或者一个还在悄悄占磁盘的目录。 下面每一条,都是这个定位的具体落实: - **一个不可逆操作,只实现一次。** 删除逻辑在宿主(`lib/service.js` 的 `deleteSession`), 由两个薄适配层通向它 —— HTTP 契约与 slot UI —— 因此单条删除与批量删除**不可能各自漂移**。 - **运行中的会话是「拒绝」,不是「猜」。** `deletable` 由宿主判定,UI 不去猜;宿主会拒的,界面根本不给选。 - **已归档默认仍然显示。** 归档**不等于**删除:归档会话照样占磁盘,默认藏起来恰好会藏掉你想清理的那些。 (官方侧栏默认隐藏;这里是三选一 —— `隐藏已归档` / `全部对话` / `仅显示已归档`,且**默认显示已归档**。) - **子代理行明确标注。** 官方侧栏把 `origin: 'subagent'` 的行整个藏起来,所以一旦这些行出现 (kind = 子代理 / 全部),每一行都会显式打上徽标 —— 子代理会话绝不能看起来像普通对话。 - **它如实汇报做了什么。** 结果行给出 成功 / 失败 / 降级 / 删掉的目录数,每条失败原因**原样保留**。 摘不掉 live store 条目时,插件报 `detached: false`,而不是假装成功。 - **错误码是语义正确的。** 与上游包(永远回 `200`)不同,这里用真实状态码: 400 / 403 / 404 / 405 / 409 / 429 / 500。 ## 界面速览 **确认框:不可逆,并且明说。** 只有两条关闭路径 —— 显式「取消」按钮,或 `Esc`。 点击遮罩**故意不关闭**:一次误点不该让你损失一次确认机会。

删除确认框:永久删除警告、会话 id,以及「取消」/「永久删除」按钮

这个浮层是**原生 `` + `showModal()`** 驱动的,因此进入浏览器的 **top layer**, 能盖在打开它的设置面板之上(普通定位元素做不到)。同时白送真正的焦点陷阱与正确的 `Esc` 语义, 而且**不需要**把 DOM 挂到组件树之外。 **批量面板(挂在设置页)** —— 搜索、项目 / 状态 / 会话类型 / 归档四组筛选、排序、分页, 以及逐行状态徽标。上面截图里的徽标(`空闲` / `运行中` / `子代理` / `已归档`)来自真实渲染输出: `运行中` 的行不可勾选。 > 两张截图都由 `scripts/render-shot.mjs` 从**真实组件树 + 真实 CSS** 生成, > 再用无头 Edge 栅格化 —— 不是手画的示意图;但也**不是**在运行中的 GUI 里拍的照片, > 详见下面的[已知限制](#已知限制)。 ## 快速开始 ```sh dsh plugin --profile web add dsh-dialogue-cleanup ``` 1. **单条删除** —— 鼠标移到侧栏的会话行,打开 `...` 菜单选 **删除会话** (注册在 `order: 500`,紧跟官方 archive 项 = 400 之后)。确认框弹出后确认, 即清掉 live 条目、工作区记录、注册表残留与磁盘工件。 2. **批量删除** —— 打开 **设置 → 对话清理**。勾选若干行(或「全选本页可删除项」),一次请求删完。 3. 宿主半改动需要**重启** DSH 进程;客户端半不需要(见 [docs/RELEASING.md](docs/RELEASING.md) 的表)。 > 兼容 DSH **0.2.0-rc.2**。npm 包与 GitHub Release 一起发布; > 版本号规则与发布链路见 [docs/RELEASING.md](docs/RELEASING.md)。 ## 它怎么实现的 一个 npm 包同时装两半,按官方插件规范装进宿主: - **宿主半(仓库进程)** —— `lib/index.js` 是 Cordis 函数插件,只具名导出 `name` / `inject` / `apply`;它注册一条 `ctx.webServer` 前缀路由,删除实现全部留在 `lib/service.js`。磁盘删除与路径约束在 `lib/artifacts.js`,审计在 `lib/audit.js`。 - **客户端半(浏览器)** —— `client.js`,单文件 bundle,经 `window.__ModuleLoader__.load({ id, factory })` 注册,**除 `require("react")` 外零依赖**。 - **两个入口都是官方 slot,都不碰 DOM:** - `sidebar.workspaces.session.menu.item`,`order: 500` → 单条删除那一项。 - `settings.section`(`id: dialogue-cleanup`,`order: 25`,排在官方 `account(-10) / general(0) / models(10) / plugins(15) / agent-presets(20)` 之后) → 入口**和**面板。一个注册项 = 设置里的一页,内容渲染在设置面板的**内容列**里。 - **面板因此不需要 `layout` 服务**,也不往 `main` / `sidebar` 抢位置 —— 少一个可选依赖、少一处降级分支。 - **样式表跟着组件走。** 菜单项把 `