dsh-essential:给 DeepSeek Harness 补上可恢复的对话删除

前言

在 DSH 里跑智能体,对话记录会一条条积累。DSH 目前的 Session 持久化没有提供删除方法,想清理只能手工处理 JSONL 目录;而直接移动一个可能还有 Agent 在写的日志并不安全——运行中的进程不应该在它不知情的情况下失去自己的日志文件。

dsh-essential 解决的就是这个问题:把删除的「意图」和「执行」分开。运行中的进程只记录删除请求并立即隐藏对应 Session;真正的日志移动推迟到下一次冷启动、在构建索引之前完成,并且全程可恢复。下面介绍它的功能、安装和用法。

这是什么

dsh-essential 是一个 DeepSeek Harness 插件,包名 @deepseek-ai/dsh-essential,版本 0.0.1,MIT 许可证,GitHub 仓库位于 omdsh-dev/dsh-essential。一句话定位:为 DeepSeek Harness 提供可恢复的对话删除能力——在每个 Session 行菜单注入 Delete conversation 操作,并注册 /delete-conversation 人机命令。

它面向 Web profile。装好后,删除不再需要碰文件:界面上点菜单、页内卡片确认,或者命令行里一条斜杠命令,归档和恢复由插件按固定流程处理。

核心功能

Session 行菜单注入

打开任意 Session 行的 菜单,会多出一个 Delete conversation 操作。点击后不再弹原生浏览器对话框,而是打开页内确认卡片 Delete this conversation?,提供 Cancel / Delete conversation 两个动作。

实现上,插件通过一个稳定的 document 级控制器,以 React portal 把操作挂进菜单 DOM,因此 Host 菜单自动关闭时确认卡片不会跟着消失。没有活跃 Agent 的历史 Session 也支持删除;身份不明的行保持不动,以免误删。

/delete-conversation 命令

插件注册人机命令 /delete-conversation。命令层直接处理,不发送给模型:零请求 token,无模型调用。CONFIRM 字面量是强制要求。

立即隐藏,重启归档

显式确认后,插件立即通过 Workspace 的持久归档投影隐藏该 Session,且不移动、不删除任何活跃日志。下次 DSH 冷启动时,在构建索引之前把该 Session 的 JSONL 目录原子移动到:

<stateDir>/trash/<session-lifecycle-key>/

这样设计的原因:HMR 期间目标 Session 仍存活则保留请求,只有冷启动才能移动日志;运行进程从不移动目标日志,以保留 Agent 所有权与持久化协调。

安全设计

  • 删除请求绑定 sessionIdcreatedAtcwd,防止复用 id 误删更新的生命周期。
  • 移动前复查持久化清单、后端位置与完整检查身份。
  • 删除实现为重命名 Session 目录,从不 unlink 日志;重命名后若崩溃,可通过确定性回收站目标恢复。
  • 校验或移动失败时保留请求,源目录不动。

安装与启用

先做安装,再做重启。官方安装命令如下,把插件加进 Web profile(/path/to/DSH/path/to/dsh-essential 替换为实际路径):

node /path/to/DSH/apps/cli/lib/bin.js plugin --profile web add /path/to/dsh-essential

安装后重启 DSH。这个包是自包含 DSH bundle(带 cordis.patch.yml),不修补、不重建 DeepSeek Harness 源码树;安装后 Web Workspace 会等待删除恢复完成,再索引持久化 Session。运行环境要求 Node.js ^22.19.0 || >=24.0.0

如果不走安装命令,也可以在 cordis.yml 里直接组合:

- id: essential-conversation-delete
  name: '@deepseek-ai/dsh-essential'
  config:
    stateDir: /absolute/path/to/conversation-trash

stateDir 必填、必须为绝对路径,且位于 Session 工件目录之外。commandName 可选,默认 delete-conversation(不带 /),用于给命令起别名;无论怎么配,菜单始终使用稳定的 /delete-conversation

典型用法

菜单删除

1、打开 Session 行的 菜单,选择 Delete conversation。
2、在页内卡片 Delete this conversation? 里确认或取消,取消不发送任何请求。

删除进行中时,卡片保持打开、两个按钮禁用、主按钮变为 Deleting… 并显示进度;失败以及「已排队但尚未隐藏」的部分结果都会在卡片内呈现。

命令删除

删除当前对话:

/delete-conversation CONFIRM

按 Session id 删除其他对话:

/delete-conversation <session-id> CONFIRM

命令成功后重启 DSH,下次启动把日志移动到 <stateDir>/trash/<session-lifecycle-key>/

恢复对话

经过上面的步骤删除的对话都可以恢复:

1、停止 DSH;
2、移除回收站目录里的 deletion.json
3、把目录移回其中记录的 originalDirectory

适用场景与注意

适合谁:在 Web 界面管理较多对话、需要清理历史 Session,又不愿手工操作 JSONL 目录、也不希望数据被永久擦除的 DSH 用户和团队。

使用前有几条限制要知道:

  • 仅支持每 Session JSONL 的持久化;SQLite 没有独立工件位置,插件会显式拒绝。
  • 日志移动在重启后生效:行会立即隐藏,但运行进程从不移动目标日志。
  • 非永久擦除:日志保留在恢复回收站,直到管理员应用保留策略。
  • 无 sidecar 级联:消息反馈等独立存储可能残留孤儿行,因为 DSH 没有跨域的 Session 删除事务。
  • DOM 兼容边界:在 Harness 提供公开 Session 菜单槽位之前,菜单操作依赖语义 Session 行/菜单 DOM 与独立的 React-owner 查找;未来 Host 变更两者时插件失败关闭,斜杠命令仍可用。

另外提醒:插件以当前 dsh 进程的权限运行,安装任何第三方插件前都应先检查其源码与许可证(本项目为 MIT)。

想参与开发的话,仓库固定使用 pnpm@11.7.0,验证流程是:

pnpm install
pnpm run verify:self-contained
pnpm run typecheck
pnpm test
pnpm run build
pnpm run prepare

结尾

dsh-essential 的价值在于:在 DSH 没有公开删除能力的前提下,给出一条意图与执行分离、重启门控、全程可恢复的删除路径——菜单和命令各留一个入口,误删也有回收站兜底。

插件目录页:https://www.skillhub.cn/plugins/omdsh-dev/dsh-essential
GitHub 仓库:https://github.com/omdsh-dev/dsh-essential

需要说明的是,skillhub.cn 是独立的社区插件目录,与 DeepSeek、幻方没有官方从属关系。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜