Skip to main content
C

dsh-session-delete

coldrainlab/dsh-session-delete

Adds "move to trash" and a session trash to the sidebar: restore removed sessions or delete them for good.

Install

dsh plugin --profile web add github:coldrainlab/dsh-session-delete

README

dsh-session-delete(会话垃圾箱)

给 DSH 侧栏加一套可恢复的删除:会话「…」菜单里的「移入垃圾箱」,以及侧栏底部(工作区列表下方、设置旁边)的「🗑 垃圾箱」入口。 DSH 本身只提供「归档」(隐藏),没有删除;本插件补齐「外部移除 + 垃圾箱」能力,只有「彻底删除」才真正删磁盘。

功能

删除(移入垃圾箱)

  • 侧栏会话行 →「…」菜单 →「移入垃圾箱」(危险色,位于归档 / 会话 ID 之后)。
  • 确认框显示会话标题,并说明「可随时恢复,彻底删除才永久移除」;可取消(按钮 / Esc / 点遮罩)。
  • 确认后:
    1. 会话日志目录 <DSH_HOME>/sessions/<项目键>/<会话 id>/ 整体移动到垃圾箱 <DSH_HOME>/trash/dsh-session-delete/<trashId>/session/(同一卷上是 rename,跨卷自动复制+删除);
    2. 垃圾箱条目 entry.json 记录 sessionId / title / cwd / workspacePath / deletedAt / sizeBytes / archived / pinned;
    3. 会话从工作区账目 detach,并清掉归档集合 archivedSessionIds、置顶集合 pinnedSessionIds 里的残留。
  • 删除成功后刷新会话列表;若删的是当前展示的会话,清空主面板(无法清空时退回页面刷新)。

垃圾箱(显示在工作区侧栏)

  • 侧栏底部 sidebar.footer.action 出现「🗑 垃圾箱」入口,紧贴工作区列表下方、设置上方;有待恢复会话时显示红色数量徽标,侧栏折叠成 56px 轨道时只显示图标。
  • 点击打开垃圾箱面板(shell.overlay 帧级浮层,不挤压会话列表):
    • 列出每条:标题(无标题时回退会话 id)、删除时间、占用大小;
    • 每条可「恢复」或「彻底删除」(行内二次确认);
    • 左下「清空垃圾箱」(确认后删除全部);
    • 空状态提示从哪里删除会话。
  • 恢复:会话目录移回原位置 <sessions root>/<项目键>/<会话 id>/,并重新挂回所属工作区(保留原归档/置顶标记);列表立即刷新,面板内条目消失。目标位置已有同名目录时拒绝(409),条目保留。
  • 失败时错误就地显示在弹窗/面板里,不会假装成功。

兼容性

项值
DSH 版本>=0.2.1-rc.2 <0.3.0(package.json → engines.dsh 范围声明;已验证 0.2.1-rc.2 与 0.2.1-rc.3,不在范围内会被宿主跳过)
profile桌面端(--profile desktop)与网页端(--profile web)
客户端 slotsidebar.workspaces.session.menu.item(菜单行)、sidebar.footer.action(侧栏垃圾箱入口)、shell.overlay(确认框 + 垃圾箱面板)
平台Windows 已验证构建/加载;路径逻辑为 Node path 通用实现

DSH 自动升级后「删除 / 垃圾箱不见了」? 那是宿主启动时的兼容性准入把整个插件跳过了,插件和垃圾箱数据都还在。 典型日志:skipping profile bundle "dsh-session-delete": Plugin dsh-session-delete@x is incompatible with dsh y。 处理:安装声明了兼容范围的新版插件;或临时给这一对版本授权 dsh plugin --profile desktop allow-version dsh-session-delete@<版本> --dsh-version <DSH版本> --accept-risk,然后重启 DSH。

安装

桌面端(本机即此形态):

& "D:\Program Files\Deepseek Harness\resources\runtime\cli\bin\dsh.cmd" plugin --profile desktop add "C:/Users/ROG-STRIX/.dsh/plugin-archives/dsh-session-delete/v0.2.3/dsh-session-delete-0.2.3.tgz"

宿主半边由 HMR 热加载(无需重启进程);客户端 bundle 由宿主 /plugins 图热更新,刷新页面(Ctrl+R)后可见「垃圾箱」入口。若菜单里仍没有,完整退出 DeepSeek Harness 再打开。

网页端:

dsh plugin --profile web add "link:<仓库或本目录绝对路径>/plugins/dsh-session-delete"
# 然后重启 dsh web,刷新浏览器页面

安装只做两件事:把包注册进 profile 的 dependencies,并因包内 dsh.bundle.patch 自动加入 dsh.profile.bundles;不改动其它插件。

使用

  1. 侧栏会话列表 → 悬停会话行 →「…」→ 移入垃圾箱 → 确认。
  2. 侧栏底部「🗑 垃圾箱(N)」→ 面板里 恢复 或 彻底删除。
  3. 「清空垃圾箱」一次性彻底删除全部条目。

数据位置与保留策略

  • 垃圾箱根:<DSH_HOME>/trash/dsh-session-delete/,每个条目一个 <trashId>/ 目录(entry.json + session/)。 默认 DSH_HOME 为 ~/.dsh;它是 sessions 根(~/.dsh/sessions)的兄弟目录,因此会话后端永远不会把垃圾箱里的会话当成活会话列出来。
  • 没有自动过期:条目一直保留,直到手动「彻底删除 / 清空垃圾箱」,或者直接删除垃圾箱目录。
  • 体积 ≈ 被删会话的日志目录大小,可在面板里看到每条的大小。

版本记录

0.2.4

  • 「移入垃圾箱」菜单项固定排到最后(order 10000),其它插件新增的会话菜单项(如「移动到工作区…」)都排在它前面。

0.2.3

  • 修复 DSH 自动升级到 0.2.1-rc.3 后「移入垃圾箱」与侧栏「垃圾箱」入口一起消失:engines.dsh 从精确的 0.2.1-rc.2 改为范围 >=0.2.1-rc.2 <0.3.0。宿主的兼容性准入按 engines.dsh 判定,精确 pin 会在补丁升级后被整体跳过(日志 skipping profile bundle "dsh-session-delete"),插件本身与垃圾箱数据不受影响。已在 0.2.1-rc.3 上验证:无跳过警告、health 返回 0.2.3、删除→垃圾箱→恢复端到端通过。

0.2.2

  • 空闲但仍驻留内存的会话(本次启动后打开过、但没有在跑回合)现在可以直接移入垃圾箱:删除前先 sessions.flush(),再走宿主会话存储的内部 detach(与 agent 生命周期结束时同一条路径)释放持久化写入句柄与内核租约,然后移动目录;空闲 agent 的注册表项一并释放,恢复并重新打开同一 id 时不会和旧 agent 冲突。
  • 真正在跑(回合 / 任务 / 子代理 / 提醒)的会话仍以 409 session-active 拒绝;若未来 DSH 改动内部 detach 接口,则退回 409 session-live 并提示重启,不会动仍被占用的目录。

0.2.1

  • 修复弹窗 / 面板显示 dialog.title、trash.empty 等原始 i18n key:locale 改为声明式依赖(inject: ['slots', 'locale']),不会再在 locale 服务激活前注册槽位而漏掉 locale.register();组件另有一层兜底,宿主 t 解析不到时回退到包内 zh/en 表。
  • 修复「删除失败:Failed to execute 'fetch' on 'Window': Illegal invocation」:请求前的 fetch / transport.fetch 不再被摘成裸函数调用,始终带上原 receiver(此前 target.doFetch(...) 会把 this 绑到目标对象上)。
  • 修复垃圾箱面板点击后不出现:setTrashState 改为每次发布新对象(原来原地改旧快照,React 收到同一引用会 bail out,只有侧栏父组件碰巧重渲染时面板才显示)。

已知限制

  1. 正在运行的会话不能移入垃圾箱:宿主会以 409 session-active(回合/任务/子代理/提醒在跑)拒绝,等它停下来即可。仅「打开过但仍驻留内存」的空闲会话可以直接删除(0.2.2 起会先关闭再移动);若宿主内部接口变化导致无法关闭,会返回 409 session-live,此时重启 DSH 后再处理。
  2. 仅处理本地数据,不做云端/远端操作。
  3. 会话投影缓存 storages/session_projcache/ 里的旧记录可能残留成孤儿文件(很小),不影响使用。
  4. 插件加载失败不会阻止 DSH 启动,只表现为「菜单/侧栏里没有这一项」;此时看 DSH 日志里的 dsh-session-delete 行。
  5. 恢复要求原路径可写、目标目录不存在;多实例同时操作同一 DSH_HOME 未做跨进程锁。
  6. DSH 升级到 engines.dsh 范围之外的大版本(例如 0.3+)会再次被宿主跳过:需要更新插件的兼容范围,或按上文用 allow-version 临时授权。

卸载

& "D:\Program Files\Deepseek Harness\resources\runtime\cli\bin\dsh.cmd" plugin --profile desktop remove dsh-session-delete

重启 DSH。卸载不会删除垃圾箱目录里的会话:想彻底清掉,先「清空垃圾箱」,或手动删除 <DSH_HOME>/trash/dsh-session-delete/。

实现与验证

半边文件说明
宿主lib/index.js纯 ESM Cordis 插件:health / info / delete(移入垃圾箱)/ trash / trash/restore / trash/purge / trash/empty
浏览器lib/client.jswindow.__ModuleLoader__.load bundle:菜单行、垃圾箱入口(sidebar.footer.action)、确认框与垃圾箱面板(shell.overlay)
宿主单测tests/host.test.mjs42 tests / 40 pass / 0 fail / 2 skipped(符号链接用例受沙箱限制)
客户端单测tests/client.test.mjs34 tests / 34 pass
调研记录research/host.md · research/client.md · research/trash.md每条结论附 DSH 源码文件:行号证据

宿主侧接口(均为 JSON,{ ok:false, error:{ code, message } } 为失败信封):

方法路径作用
GET/api/session-delete/health{ ok, version }
GET/api/session-delete/info?sessionId=会话快照(路径/大小/运行中/归档/置顶)
POST/api/session-delete/delete { sessionId, displayTitle? }移入垃圾箱(运行中/打开中的会话 409 拒绝)
GET/api/session-delete/trash列出垃圾箱 { entries, totalBytes, trashRoot }
POST/api/session-delete/trash/restore { trashId }恢复(文件回原位 + 重新挂回工作区)
POST/api/session-delete/trash/purge { trashId }彻底删除一条
POST/api/session-delete/trash/empty清空垃圾箱

实现要点:

  • 活跃判定复用 DSH 归档准入的同一接缝:ctx.waterfall("workspace/session-activity", { sessionId }),并兜底 agent.status === "running"。
  • 账目清理/恢复走公开 API:Workspace.detachSession() / attachSession()、workspaceRegistry.unarchiveSession() / archiveSession() / unpinSession() / pinSession();这些写入经 storage-domain 提交,工作区 follow 流会把行从各客户端移除/加回。
  • 顺序:先做可回滚的账目变更,再移动文件;移动失败逆序回滚账目。移动 + entry.json 写入要么都成功,要么把会话放回原位(不会留半个条目)。
  • 路径安全:sessions 根 realpath、逐级 lstat、拒绝 symlink/junction、严格包含关系,移动前二次复查(TOCTOU);垃圾箱根必须是 sessions 根的兄弟目录,restore 目标必须在 sessions 根内且尚不存在。
  • 所有删除/恢复/清空操作在 core 内串行化。

运行测试(沙箱里 node --test 无法 spawn,直接执行文件):

& "C:\Users\ROG-STRIX\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\node\bin\node.exe" plugins\dsh-session-delete\tests\host.test.mjs
& "C:\Users\ROG-STRIX\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\node\bin\node.exe" plugins\dsh-session-delete\tests\client.test.mjs

隐私与安全

  • 不联网:插件只处理本机文件与宿主已有服务,无遥测、未引入任何第三方依赖。
  • 数据写入仅限:会话目录在 sessions/ 与 trash/ 之间移动、垃圾箱元数据、工作区账目(经注册表公开 API)、归档/置顶集合。
  • 路由不做鉴权(与宿主其它插件路由一致,仅绑定在本机回环地址上);请勿把 DSH 暴露到不可信网络。

License

MIT

Related plugins