dsh-session-hygiene:给 DSH 会话加上回收站、孤儿清理和工作区分组

前言

DSH 的侧边栏自带归档,但没有真正删除会话的入口:想丢掉一个误开的会话,只能让它躺在归档里继续占磁盘。删掉一个工作区更干脆,磁盘上的会话不受影响,只是 cwd 再也匹配不到任何已注册工作区,侧边栏连列它的地方都没有。工作区一多,侧边栏也是一长条平铺,没有分组。

dsh-session-hygiene 就是补这三处缺口的插件。它由 liudapeng0311 维护,分类 admin-security,社区目录上 Star 为 0,功能不代表成熟度未经广泛验证,源码可以直接读。

这是什么

一句话定位:给 DSH 的会话生命周期补上三件事——可恢复的删除、孤儿会话清理、工作区分类。作者在 README 里强调,插件全程是增量式的:不替换或隐藏任何内置行,也不改写这些组件以外的 DOM,卸载后侧边栏回到 shell 原始渲染状态。

三个触发点分别落在:

  • 会话行的 ... 菜单:新增 Delete session (to trash)。
  • Settings → Session cleanup:扫描孤儿会话,支持归档、移入回收站、恢复、永久删除。
  • Settings → Workspace categories:新建分类,侧边栏显示分组标题,支持拖拽分配与折叠。

核心功能

在侧边栏把鼠标放到某个会话上,打开 ... 菜单,选择 Delete session (to trash)。会话行立即从列表消失,但数据只是被移动。

底层步骤按顺序是:先停掉正在运行的任务并隐藏该行,再把会话 id 从所有工作区解绑并取消 pin,然后把 <home>/sessions/<group>/<id>/ 整个目录改名移进回收站,同时记录一条 preview,并通过 api-session/removed 让已打开的页面无刷新地丢掉这一行。投影缓存(projection cache)会保留,所以恢复回来的会话还能显示原来的标题和开场提示。

如果移动报 “the session data is still in use”,说明还有另一个视图占着这个目录,切到别的会话再试。移动失败时归档会回滚,会话照原样显示。

清理被删掉工作区留下的孤儿会话

打开 Settings → Session cleanup,页面打开时就扫描,Rescan 可以重新扫。

Orphaned sessions 的定义是:header.cwd 匹配不到任何已注册工作区的已存储会话。每一行显示标题、开场 preview、原属工作区、目录名和大小。处理方式有三种:

  • 逐行 Move to trash。
  • 批量 Archive N:放进 shell 的归档里,跳过 subagent 会话(通常由父会话持有)。
  • 批量 Move all to trash:包含 subagent,会要求二次确认。

另有一类 Detached 会话:cwd 匹配的工作区存在,但那个工作区没有把这个会话列进去,所以侧边栏把它归到了 Ungrouped。它们显示在标签页上方的一条 strip 里,提供 Attach all,比删进回收站更省事也更安全——会话本身是健康的。

回收站:恢复或永久删除

Trash 标签页列出被移入的内容:

  • Restore 把目录改名回记录中的路径,并重新挂到拥有该 cwd 的工作区。如果原路径已经被占用,会返回 409 拒绝,得先挪走或删掉占用物;如果原工作区已不存在,会话以未分组状态回来,因为没有任何工作区认领它的 cwd。
  • Delete permanently 会 unlink 目录并丢掉投影缓存条目。这是唯一不可逆的操作,界面会指明具体删除什么,且需要再点一次确认。

工作区分类

打开 Settings → Workspace categories:

  • Add category,可直接内联重命名,用 ↑/↓ 调顺序,Delete 删除分类后,其下工作区自动回到未分类。
  • 通过下拉框给工作区分配分类,或者在侧边栏把工作区行拖到某个分类标题上。
  • Save and regroup 写入分配结果,并重排工作区注册表,使每个分类的行连续排列,未分类工作区排在最后。内置的拖拽排序仍然有效,插件只在保存时重排。
  • Clear assignments 把所有工作区打回未分类,但不删除分类本身。
  • 点击标题可以折叠/展开分类,折叠状态会被记住。Show category headers in the sidebar 开关可以只隐藏分组条而不取消分配。

一个分类只有在行连成一块时才会显示标题;被拆开时它宁可不显示标题,也不在归属别的分类的行上面放标题。分组条是插件自己挂上去的节点,插件移除后侧边栏完全复原。

安装与启用

插件发布在 npm registry 上,可以在 DSH 的 Plugins 页面安装,也可以通过 agent:

plugin_manager install_bundle dsh-session-hygiene

如果要装本地 checkout,传它的绝对路径:

plugin_manager install_bundle <path to this checkout>

插件的 host 端 JavaScript 不热重载,装完需要重启一次 host。卸载在 DSH 的 Plugins 页面移除 bundle 即可,侧边栏的分类条会立即消失。

一个实务提醒:卸载前请先把回收站清空或恢复。插件移除后 <home>/storages/session-hygiene/ 目录仍然留在磁盘上,但回收站里的会话已经没有任何 UI 能恢复,只能照着各自的 entry.json 手工把目录改名回去。

典型用法

下面按 README 的路径走一遍最常见的清理流程。

1. 删掉误开的会话,之后又后悔

侧边栏找到会话 → ... 菜单 → Delete session (to trash) → 打开 Settings → Session cleanup → Trash 标签页 → 选中那行 → Restore。

2. 清理删掉工作区后残留的大量孤儿会话

先 Settings → Session cleanup 看 Orphaned sessions 列表,确认不是误判(见下面的已知限制),再选择批量 Archive N;确认不会再用,再选 Move all to trash,按提示二次确认。subagent 会话请保留在归档之外,它们是父会话的一部分。

3. 把工作区按项目归类

Settings → Workspace categories → Add category → 用工作区行的下拉框或侧边栏拖拽做分配 → Save and regroup。之后侧边栏会出现带标题的分组条,点标题折叠。

数据落在哪里

插件只写 <home>/storages/session-hygiene/ 这一处:

<home>/storages/session-hygiene/
  categories.json
  trash/<sessionId>__<stamp>/
    entry.json
    session.v4.jsonl.zstd ...

entry.json 记录 sessionId、cwd、from(原目录)、title、preview、createdAt、sizeBytes、deletedAt。这是插件唯一自己创建的文件,也是恢复能力的来源。想手工清空回收站,删掉这个目录树即可。投影缓存是派生产物,进回收站时刻意保留,永久删除时才一并清除。

适用场景与注意

适合这类人:在 DSH 里把工作区当项目用、会话数量已经上百,删工作区时想顺带处理掉它留下的会话,并且希望删除动作有后悔药。

需要注意几点:

  • 插件以当前 dsh 进程的权限运行,安装前先读一遍源码和许可证再启用。本插件许可证为 MIT,仓库地址见文末。
  • 已知限制:孤儿判定拿 header.cwd 和工作区注册表记录的目录对比,磁盘上把目录改名过的会话会被误判成孤儿;删除工作区时仍然不会提前警告它有多少会话,插件只在事后把它们列在 Settings 里,因为要拦内置删除流程就得接管 sidebar.workspaces 这个 shell 所有的 single slot;subagent 会话会单独标记、不进 Archive N,但会进批量回收站;分类标题依赖行连续,单行分类中间插入行会按上方标题猜,未必准确;host 端 JS 不热重载,安装或更新后都要重启。
  • 此插件是社区目录(独立站点)上的第三方包,与 DeepSeek / 幻方没有官方从属关系。

结尾

dsh-session-hygiene 做的事很收敛:把删除变成可恢复的移动,把删掉工作区留下的孤儿暴露出来,再给侧边栏加上分组。三件事都是加法,不改变内置行为。你如果正在被会话堆积和离散工作区困扰,值得试一轮;如果只是想先看看实现,entry.json 的字段设计和 README 里的槽位表都写得比较清楚。

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

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

小夜