dsh-session-delete:在 DSH 里真正删除会话

前言

在 DeepSeek Harness(DSH)里结束一段对话后,侧栏里「删掉」会话,往往只是把 id 写进 workspace.json 的 archivedSessionIds,界面不再显示,磁盘上的日志、缓存和索引并不会少一个字节。官方文档对这一点写得很清楚:dsh-session-persistence 没有删除或保留 API;dsh-session-persistence-jsonl 不会删除会话文件;dsh-client-ui-workspace 也没有 Session 删除能力。

对自托管、在意本地数据残留或合规留痕的开发者来说,归档不等于清除。社区插件 dsh-session-delete(维护者 wangyueyueye,分类 admin-security)补的是「按落点枚举、确认后再删」这一条链路,并把删干净当成一等目标,而不是再包一层隐藏。

这是什么

dsh-session-delete 给 DSH 增加可审计的「删除会话」能力:先扫描会话在磁盘上的所有相关落点,在弹窗里列出大小与原因,用户选定删除范围、擦除方式并勾选确认后,才由宿主侧 API 执行删除。

README 特别提醒:npm 上的 dsh-session-delete 包可能是另一位作者的另一插件;若要本文描述的「投影缓存、工作区索引、插件数据、孤儿附件、覆盖擦除」能力,请只从上述 GitHub 仓库安装。

核心功能:它删什么、不删什么

一个 DSH 会话不是单个文件,而是散在多个目录里的一组数据。插件按落点逐层清理,并在扫描结果里说明「删什么、多大、哪些不删、为什么」。

落点 位置(相对 <DSH_HOME>) 为何必须处理
会话记录 sessions/<工作区>/<id>/session.vN.jsonl.zstd 每一代都要删;只删最新代时旧代可能在读取时顶上来
投影缓存 storages/session_projcache/sessions/<id>.json[.bak.*] 含标题与逐轮 prompt/response 原文
工作区索引 storages/workspace.json 会话顺序、置顶、归档中的 id;不清会留空行
插件数据 storages/<任意插件域>/.../<id>.json 有限深度扫描,不硬编码插件名
附件对象 attachments/v1/... 内容寻址、去重、默认不自动删;仅「彻底」档且确认无其他会话引用时处理

明确不删的包括:工作区里由命令产生的文件(无法可靠归属到单会话)、运行日志与会话日志导出(无到会话的映射)、spill 溢出文件(系统临时目录按时间自清)。

三档删除范围

  1. 仅对话记录:会话记录 + 投影缓存 + 工作区索引
  2. 记录 + 插件数据:在上述基础上再加各插件按会话存的数据
  3. 彻底(含附件):再删仅被本会话引用的附件对象

任意档位都会清理工作区索引,否则侧栏仍会留下指向已删数据的行。

两种擦除方式

  • 普通删除:直接解除链接,较快;数据块可能仍被恢复工具读到。
  • 覆盖擦除:先写零并 fsync 再删,抬高恢复门槛;对 SSD 磨损均衡、CoW 文件系统等不是物理级保证。

本地删除不能撤回已经发给模型提供商的内容。例如 dsh-session-log-deepseek 默认会把会话日志增量作为请求字段上传;开关在 设置 → 通用 →「在使用官方模型 API 时上传 Session Log」。

安装与启用

装完后需要重开 DSH(客户端 boot 图谱在启动时组装)。任选一种方式:

A. 从本地目录安装(README 推荐,便于审计)

在 Web 端 设置 → 插件 选本地目录,或手动改 profile 三处:

1. profile/node_modules/ 里放入本包(或建指向源码目录的联接)
2. profile/package.json:
   "dependencies": { "dsh-session-delete": "file:<绝对路径>/dsh-session-delete" }
   "dsh.profile.bundles": [ ..., "dsh-session-delete" ]

B. 从 Git 安装并锁 commit

"dsh-session-delete": "github:<user>/dsh-session-delete#<commit-sha>"

C. npm

pnpm add dsh-session-delete

然后把 dsh-session-delete 追加进 dsh.profile.bundles。

不要改 profile 的 cordis.patch.yml 去插 session-delete——bundle 自带 patch,重复会插入同一个 id。

卸载可用 plugin_manager 的 remove_bundle,或手动清理 dependencies、bundles 与 node_modules 中的包。挂载成功会在 <DSH_HOME>/logs/session-delete.log 写 mounted …;每次删除追加 <DSH_HOME>/logs/session-delete-audit.jsonl 一行。

典型用法

  1. 在会话列表某一行打开 ... 菜单,选择 删除会话。
  2. 弹窗先只读扫描,展示各层待删项与不删项及原因。
  3. 必须无默认值地选定三项:删除范围、擦除方式、我已知晓:删除后无法恢复;三项齐全后删除按钮才可点,缺项时按钮旁会提示。
  4. 正在运行的会话会被拒绝删除(插件无法安全 teardown 他人的 AgentHandle)。
  5. 若删的是当前打开的会话,完成后会重载页面;否则侧栏对应行当场消失,无需整页刷新。

删当前打开会话时,数据清完后还会调用 archiveSession 让 live 行从列表消失;插件下次挂载时会清理「已归档但既不在内存也不在磁盘」的 id,避免 workspace.json 里长期留墓碑。

适用场景与安全边界

适合谁:需要在自托管 DSH 上主动清除本地会话正文、缓存、索引与部分插件侧车数据的 admin 或注重隐私的用户;需要删除前看清清单、留审计 jsonl 的场景。

安装前务必知晓:DSH 的 Host 插件在宿主进程内、工作区沙箱之外运行(与官方描述一致)。安装即信任作者与约 650 行、零第三方依赖的 lib/index.js。误删无回收站;覆盖擦除在 SSD 上也不是物理不可逆。

插件自述的安全设计包括:宿主仅用 node:fs/promises、node:path、node:os;package.json 无 scripts;唯一 API 路由 /api/session-delete 且由 DSH 连接层校验 owner;待删路径需落在 sessions/、storages/、attachments/ 根内并经过 realpath 闸门;会话 id 白名单 ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$;不跟随符号链接/目录联接做递归删除。

兼容性:针对 DSH 0.2.1-rc.x 存储布局;会话格式升到 v5 时会话日志文件名规则需复核。运行期依赖 ctx.sessionPersistence、ctx.workspaceRegistry、ctx.sessions、ctx.connection.fetch 及客户端 slots/locale/sessions。

自测(零依赖):

node test/selftest.mjs
node test/client-test.mjs

结尾

DSH 生态强调「一切皆插件」;社区目录 skillhub.cn 与 DeepSeek / 幻方无官方从属关系。若你的需求是「归档隐藏」以外的本地彻底清理,dsh-session-delete 把官方未提供的删除面补全到日志各代、投影缓存、索引、插件域与可选孤儿附件,并在 UI 上用扫描清单与三项门控把误操作空间压小。

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

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

小夜