dsh-archived-cleanup:批量彻底删除已归档会话的本地痕迹

前言

DeepSeek Harness(DSH)官方设计里,会话可以归档,但没有「从本机彻底删除」的一等原语:SessionPersistence 没有 delete,归档只是把会话藏进设置里的「已归档会话」列表。磁盘上的会话日志、投影缓存、工作台记账、spill 暂存和附件引用仍会留在 DSH_HOME 下。输入框 @ 提及候选来自 live 内存 store、磁盘 sessionPersistence.list() 等并集,已归档但进程仍驻留的会话会继续出现在 @ 里,和「我以为已经归档了」的直觉不一致。

下面介绍社区插件 dsh-archived-cleanup(维护者 wxy123-ctrl,分类 admin-security,MIT 许可证)。它在设置面板「已归档会话」页下方增加 「归档会话清理」 页,对归档集内的会话做批量勾选与二次确认,在文件系统与官方存储域层按固定顺序删干净,并在每次删除后自动做一次全局孤儿清扫。插件不写持久状态、不注册设置命名空间;官方若将来内置会话删除,用 plugin_manager remove_bundle 或 Plugins 页移除即可剥离。

这是什么

dsh-archived-cleanup 是 DSH 独立 bundle 插件(当前 package 版本 0.6.2,Node >=18)。一句话定位:在合规边界内(仅接受注册表归档集内的 session id),彻底移除选中会话在本机的落盘与索引痕迹,并幂等清理悬空数据。

目录页:SkillHub - wxy123-ctrl/dsh-archived-cleanup
源码与完整说明:GitHub - wxy123-ctrl/dsh-archived-cleanup

SkillHub 为社区插件目录,与 DeepSeek / 幻方无官方从属关系;本插件标注为非官方。

核心功能

设置页 UI

宿主 index.js 负责删除管线;浏览器 client.js 经 settings.section 插在官方已归档页(order 25)与后续插件页之间(order 26)。列表与官方「已归档会话」同源(归档集 ∩ 已加载 summaries),并对 live 子树、缓存/工作台残留等做 status 预标注。

工具栏只有一个动作按钮,两种形态:

  1. 有勾选:彻底删除…(红色),二次确认后执行删除;
  2. 空选集:清扫孤儿数据…(中性描边),无归档会话时也可单独执行。

自 0.3.0 起,删除完成后总是再跑一遍全局孤儿清扫,不再需要第二个按钮。自 0.4.0 起,「仍在使用」且无法即时卸载的拒删会话在页面横幅与结果摘要中单列。自 0.5.0 起,空闲的 live 归档会话可在不重启 DSH 的情况下删除:删除前按官方 teardown 同类步骤卸载本进程内存态(运行中回合的子树仍须先停止)。

本地会删什么

README 中按 0.1.7-alpha.2 实测整理了落盘位置;0.2.0 起的删除行为如下(节选):

数据 典型位置 处理方式
会话日志 ~/.dsh/sessions/<项目>/<encodeSegment(id)>/session.vN.jsonl[.zstd] fs.rm 整目录(含子代理子树)
空项目目录 ~/.dsh/sessions/<项目编码目录>/ 日志删完后目录为空则 rmdir
投影缓存 ~/.dsh/storages/session_projcache/sessions/<id>.json 官方 session_projcache 域 table('sessions').delete(id)
注册表归档集 ~/.dsh/storages/workspace.json → global.archivedSessionIds 官方幂等 unarchiveSession
工作台记账 同上 → tables.workspaces[*].sessionIds 对各工作台官方幂等 detachSession(id)
spill 暂存 %TEMP%\dsh-spill-*\session-<sha256(id) 前 12 位>\ 按宿主同名公式删除
附件对象 ~/.dsh/attachments/v1/{objects,file-objects,files}/ 引用感知 GC,仅删独占对象
附件请求变体缓存 ~/.dsh/cache/attachments/request-images/ 有附件被删则整体清空

本地无法删除、文档如实声明的项包括:走官方 API 时的远端会话日志增量(dsh-session-log-deepseek)、telemetry 远端投递、manager.log 中的生命周期行、WebView2 Local Storage 里的 UI 状态快照等。

删除后的孤儿清扫

孤儿清扫是幂等的:只处理已无日志的投影缓存与工作台记录、死归档条目、别处空项目目录等悬空数据。POST /plugins/dsh-archived-cleanup/sweep 仍可作为脚本二次校验入口;UI 在删除流程里已内联执行。

安全边界(摘要)

  1. 仅接受当前读到的归档集内的 id,不是任意路径删除入口;
  2. 子树整体判定:父会话及其 parentSession 传递闭包内,若有成员 agents.get(id).status === 'running',整棵子树拒删(status: 'busy');
  3. live 且空闲:在宿主内部可达点齐全且未设置 deleteLiveSessions: false 时运行时卸载后删除;否则退回「重启 DSH 后可删」(status: 'live');
  4. 附件 宁可漏删不可误删:扫描失败或读不出日志时保留候选附件。

未归档的冷会话不能在本页直接删,须先在官方「已归档会话」页归档后再来清理。

HTTP 调用通道(脚本 / 高级维护)

静态 bundle 无 host.call,插件借用宿主 webServer 同源 POST(信任围栏与官方 /api 同类):

POST /plugins/dsh-archived-cleanup/status
Content-Type: application/json

{"ids": ["<session-id>", "..."]}
POST /plugins/dsh-archived-cleanup/delete
Content-Type: application/json

{"ids": ["<session-id>"]}

ids 可为空数组,表示仅执行孤儿清扫。响应在删除结果之外附带 sweep 字段。

自 0.6.0 起有一次性维护入口(破坏性,不进 UI,须显式确认串):

POST /plugins/dsh-archived-cleanup/purge-all
Content-Type: application/json

{"confirm": "purge-all-except-live", "keepIds": []}

行为:除 live 会话子树(及可选 keepIds)外,先官方 archiveSession 再整批走 delete 管线;候选来自磁盘、工作台记账、projcache 与归档集的并集。

安装与启用

插件通过官方 bundle 机制挂载:package.json 声明 dsh.bundle.patch 指向 cordis.patch.yml,无需手工 junction 或编辑 profile 里的全局 cordis.patch.yml。启停后 web 模板 patchReload: live,浏览器半边可随 HMR 热更新。

先将 wxy123-ctrl/dsh-archived-cleanup 源码放到本机某一目录,再执行(路径换成你的绝对路径):

plugin_manager install_bundle target=<本仓库绝对路径>

也可在 DSH Web 侧 Plugins 页安装并启用。卸载:

plugin_manager remove_bundle target=dsh-archived-cleanup

验收时可检查配置是否注入插件行:

dsh web --dump-config | findstr archived-cleanup

可选配置(默认一般不用)在 profile 的 cordis.patch.yml 里按插件 id 覆盖,例如关闭 live 即时删除或附件 GC:

- id: archived-cleanup
  name: dsh-archived-cleanup
  config:
    purgeAttachments: false
    deleteLiveSessions: false

完整字段见 README(sessionsRoot、attachmentsRoot、spillRoots 等用于非默认布局)。

典型用法

在设置页清理归档会话

  1. 打开 DSH 设置,进入 归档会话清理(在「已归档会话」下方)。
  2. 勾选要永久删除的已归档会话;若行上标注「正在运行」,须先停止再删。
  3. 点击 彻底删除…,在宿主原生 Modal 中确认(非浏览器 alert)。
  4. 查看结果摘要:各类删除计数、warnings,以及内联孤儿清扫行;仍在使用且拒删的 live 会话在 0.4.0 起会单独列出。

删除成功后,官方已归档页、侧栏与本页对应行应一起消失;@ 列表对已成功删除的 id 会即时收敛(0.5.0 起 live 空闲会话无需重启)。

只清扫孤儿数据

不勾选任何会话(或归档集为空),点击 清扫孤儿数据… 并确认。用于清理历史遗留的无日志 projcache、悬空工作台记账、死归档条目、空项目目录等;状态正常时二次执行计数应全为 0。

本地自测(维护者提供)

在插件目录执行:

node selftest.mjs

README 说明该脚本覆盖 encodeSegment、子树闭包、live 三分区、附件 GC、purge-all 确认门等 46 项检查(含临时目录端到端)。

适用场景与注意

适合谁

  • 需要在本机清掉已归档会话的日志、缓存、spill 与独占附件,降低磁盘占用与隐私残留;
  • 归档很多实验会话后,希望 @ 列表与侧栏不再被「已归档但仍 live」的 id 干扰(在 0.5.0 能力可用时);
  • 愿意在理解边界的前提下,用 purge-all 做一次性历史清场(须自行承担数据不可恢复风险)。

务必注意

  1. 插件以当前 DSH 进程权限读写 DSH_HOME 与临时目录;安装前请阅读源码与 MIT 许可证,确认信任维护者 wxy123-ctrl。
  2. 删除不可通过官方 UI 撤销;共享附件会被保留,独占附件会被 GC。
  3. 插件不能代替你清理远端 API 日志或 telemetry;Windows 下若持久化写句柄未成功 close(),日志目录可能因文件锁删除失败,结果中会体现为单根错误,可重跑幂等收敛。
  4. SkillHub 目录页可提供「发送给 DeepSeek Harness 安装」的自然语言提示;具体仍以 README 的 plugin_manager install_bundle 与 Plugins 页为准。

结尾

DSH 生态强调「一切皆插件」:dsh-archived-cleanup 在官方「只归档不删除」的产品决策下,补了一条可审计、有边界的本机清理路径——设置页可视化操作,必要时用同源 HTTP 或 purge-all 做维护。若你只需要偶尔删几个冷归档会话,用勾选 + 确认即可;删除后自带的孤儿清扫减少手工扫盘。

  • 目录页:https://www.skillhub.cn/plugins/wxy123-ctrl/dsh-archived-cleanup
  • GitHub:https://github.com/wxy123-ctrl/dsh-archived-cleanup
羽毛球分组比赛记分
小程序二维码

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

小夜