dsh-session-trash-90d:给 DSH Web GUI 加一个会话回收站

前言

DSH 的会话散落在 $DSH_HOME/sessions/<工作区编码>/<会话 id>/ 下,官方只提供了归档能力,没有真正删除。想清理掉某个旧会话,只能手动上去删目录;更麻烦的是,只要这个会话还被宿主加载在内存里,删了文件它也会被写回来,重启后照样出现。

full626/dsh-session-trash-90d 就是来填这个缺口的:一个 DSH 客户端组合包,在 Web GUI 里给出会话列表、回收站、恢复、彻底清除,以及官方缺失的「取消归档」。下文按「它解决什么 → 怎么用 → 哪里要注意」来讲。

这是什么

一句话定位:DSH Web GUI 的会话管理插件,提供列表、归档 / 取消归档,以及真正删除(可恢复的回收站先接住,再做不可恢复的彻底清除)。

  • 维护者:Full626
  • 分类:客户端(DSH 组合包 bundle,不是独立应用)
  • 星标:0
  • 许可证:MIT
  • 适用宿主:DSH >=0.2.0 <0.3.0,Node >=22

它的入口是「设置 → 会话管理」,不新增独立界面。

为什么不能直接删文件

DSH 0.2.x 的 sessionPersistence 只有 create/open/stat/list/flush,sessions 只有 create/prepare/enter/announce/flush/get/list/fork,没有删除会话的 API。所以「真删」只能直接删磁盘上的工件。

而以前的「真删」插件在这里踩坑:它们只跳过 agent.status === 'running'(正在生成回复),但 running 和 live(已加载进内存)是两回事。于是「idle 但 live」的会话被删掉文件后,宿主会把它写回来,重启后等于没删。

这个插件的做法是墓碑 + 启动重放:

删除请求
 ├─ 非 live → 直接删文件(干净)
 └─ live    → 记一条墓碑 + 尝试释放 + 删文件,并如实标记 pending
宿主每次启动(+5 秒后补一次)→ 重放墓碑:此时没人打开它们,删了就真没了
确认消失且不再 live 后,墓碑才被清掉

每次删除会同时清理:会话目录、投影缓存、归档集合、workspace 记账。

设计上有一个取舍值得记一笔:host 半侧只依赖文件系统,加上两个可选服务——workspaceRegistry 管归档集合,sessions 做 liveness 探测——不碰任何私有 API。将来 DSH 重构时,这个插件的表现是降级(列表变空)而不是崩掉。

核心功能

功能 说明
会话列表 标题、工作区、最近修改、大小,以及 内存中 / 已归档 标记
移入回收站 不直接抹掉:会话目录带投影缓存一起搬进 sessions-trash,保留 90 天
恢复 放回原来的工作区,缓存一并还原
彻底清除 / 清理过期 手动清单个,或清掉超过 90 天的;列回收站时也会自动清
空会话折叠 只开过没用过、只有头部记录的会话默认隐藏,可展开
归档 / 取消归档 官方只有归档没有取消,这里补上
墓碑状态 界面提示还有几个待下次启动处理

导出没有做,官方 /export 已经够用,不重复造。

回收站的目录结构

$DSH_HOME/sessions-trash/<删除时间戳>-<会话 id>/
├─ meta.json      原工作区、标题、大小、删除时间
├─ session/       会话目录(原样搬过来)
└─ cache.json     投影缓存(原样搬过来)

每个条目自带元数据,没有全局清单,所以不会出现清单和实际文件对不上的情况。目录名以时间戳开头,天然按时间排序;恢复就是原路搬回去。过期清理在两个时机触发:宿主启动时,以及每次打开回收站时。

安装与启用

本包是 DSH 组合包(bundle):profile 只要把包名选进 dsh.profile.bundles,加载器就会应用自带的 cordis.patch.yml。

仓库里的 install.ps1 脚本支持三种干跑方式:

cd dsh-session-trash-90d
.\install.ps1 -Profile desktop          # 默认就是 desktop
.\install.ps1 -Profile desktop -DryRun  # 只看将要做的改动
.\install.ps1 -Profile desktop -Uninstall

第一步,先 DryRun。 它会打印将要改哪些 profile 文件,确认无误再真正执行。

也可以走 profile 自己的插件管理器(设置里的「插件」页),填仓库地址:

https://github.com/Full626/dsh-session-trash-90d

或命令行:

dsh plugin --profile desktop add 'github:Full626/dsh-session-trash-90d'

第二步,重启应用。 新组合层要下次组合才生效,装完不重启看不到变化。

第三步,打开设置 → 会话管理。

典型用法

装完重启后,日常操作都在「设置 → 会话管理」里完成:

1、会话列表里看到所有已存储会话及其元信息,区分 内存中 和 已归档。
2、要清理某个会话,点「移入回收站」——它连目录带缓存一起搬走,不是直接抹掉。
3、需要找回时,在回收站里点「恢复」,它会回到原来那个工作区。
4、确认不要了,才用「彻底清除」,或把超过 90 天的交给「清理过期」。

宿主内存里正活着、又没能释放的会话,删除后不会立即消失。界面上会提示「还有 N 个待下次启动处理」,这是刻意的诚实:下次宿主启动时重放墓碑,确认消失且不再 live,墓碑才会被清掉。

命令行侧也有一组接口可用于自动化:

方法 路径 说明
GET /list 会话列表 + 待处理墓碑 + 保留天数
GET /trash 回收站条目(顺带清理过期项)
GET /state 墓碑、home、两个根目录、保留天数
POST /delete body {"ids":[...]} —— 移入回收站
POST /restore /purge
POST /archive /unarchive

验证时怎么跑

主机半侧有一套不碰真实数据的测试:在临时 $DSH_HOME 里造假会话,用最小 fake ctx 驱动真实插件代码,专门覆盖那个回归——假造「内存回写」,再验证启动重放把它清掉。

node scripts/test-host.mjs     # 27 项:列表/删除/墓碑/重放/归档/错误处理

跑在真实桌面端上的检查,默认只读:

# 只读:列出会话、墓碑状态
node scripts/check-api.mjs --url http://127.0.0.1:19387

# 真要删几个(谨慎)
node scripts/check-api.mjs --url http://127.0.0.1:19387 --delete session-xxxx

适用场景与注意

适合这些人:

  • 在 DSH 0.2.x 上做开发,受够了「会话删不掉 / 删了又回来」。
  • 需要批量清理旧会话,又不希望误删后无法找回。
  • 需要取消归档这项官方没提供的能力。

需要留意的几点:

1、删除默认保留 90 天;「彻底清除」和过期清理才是不可恢复的。所以别把回收站当成无限期保险箱,也别把彻底清除当常规操作。
2、回收站占用磁盘,删得多了记得清,或让它自己过期。
3、宿主正在运行某个会话时不会删它(会跳过并告知),这是刻意设计,不是 bug。
4、插件以当前 DSH 进程权限运行,装的是就直接改 profile 文件——安装前先读源码和 MIT 许可证,install.ps1 先加 -DryRun 看一遍。
5、会话正文是 JSONL + 多帧 zstd,本插件只做管理,不解析正文内容,拿不到「这会话讲了什么」的语义。
6、路径布局按 DSH 0.2.x 的 $DSH_HOME/sessions/<工作区编码>/<会话 id>/ 解析;将来若改布局,表现是列表变空而不是误删。
7、本插件是社区第三方包,目录页与仓库都是独立站点项目,与 DeepSeek / 幻方没有官方从属关系。

小结

dsh-session-trash-90d 的价值在于它承认了「会话删了会复活」这个真实约束,并给出一个可验证的解法:墓碑 + 启动重放,加上 90 天回收站、原工作区恢复、取消归档。如果你正在 DSH 0.2.x 上做会话治理,值得先 node scripts/test-host.mjs 看那 27 项测试跑通,再装到 profile 上。

目录页:https://www.skillhub.cn/plugins/Full626/dsh-session-trash-90d

仓库:https://github.com/Full626/dsh-session-trash-90d

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

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

小夜