@xrn1997/dsh-session-delete
给 DeepSeek Harness(DSH)加一个删除会话的能力。DSH 官方有归档、没有删除——归档只是把会话从列表里挪走,文件还在。本插件补上删除,并且让删除可恢复:删除 = 移入回收站,另有一个显式的「彻底删除」。
回收站面板:左边一列是按项目分组的会话清单,右边是选中那条的详情(元信息与正文),页脚是整页唯一的实心红按钮「清空回收站…」
- 安装:
dsh plugin --profile <profile> add @xrn1997/dsh-session-delete
- 许可:Apache-2.0
- 数据:回收站本体留在本机
~/.dsh/session-trash/,不联网、不上传
目录
功能特性
- 删除 = 移入回收站:会话条目「…」菜单里的「删除」把会话搬进回收站,可随时恢复;删完有一条停留 6 秒的撤销提示
- 显式彻底删除:单条「彻底删除…」或页脚「清空回收站…」,两者共用同一个二次确认
- 回收站面板:清单在左、详情在右——左栏是按项目分组的会话列表(每条两行:标题 / 删除时间 · 大小,「恢复」与「彻底删除…」在行右侧),右栏是选中那条的详情(时间/体量/计数/位置四组元信息,加人与助手的文字;逐格名单以
src/client/trash-detail.tsx 与现状稿 §7 为准,这份不列——列成清单就是一条会漂的东西);中央列不够宽(<900px)时改成下钻:点一条看详情,「← 返回清单」回来。清单为空或读不到时也只一列——那时右栏既没得选也没得点
- 那一列自己可以收:组头可折叠(也可以一键全部折叠)、两栏之间那根线可拖(也能用键盘 ←→/Home/End 调);宽度夹在「元信息那一行读得完」与「详情还读得开」之间
- 多选挑着彻底删:那一排的「多选」进入,勾选若干条后页脚那颗从「清空回收站…」换成「彻底删除 N 条」,一次确认后逐条执行,没删掉的把原因留在它自己那一行;组头那颗可以一次把整个项目的会话全选上(包括折叠起来看不见的)
- 运行中的会话拒绝删除:菜单项置灰并说明原因——不替用户终止正在进行的活
- 不自动过期:不设天数上限,清空是显式动作
- 失败不吞:回收站读不到时把宿主原文上屏,并给一个「重试」
- 不可用时不出现:取数通道探测不过就一个入口都不注册——页面上看不出本插件,但也不会因此把宿主拖死
- 文案随宿主语言:中文 / English 挂在宿主 locale 服务上,跟随设置的界面语言
安装
dsh plugin --profile <profile> add @xrn1997/dsh-session-delete
装完重启宿主(Node 半不走 HMR)。卸载:
dsh plugin --profile <profile> remove @xrn1997/dsh-session-delete
卸载只是移除插件;~/.dsh/session-trash/ 下已有的目录仍留在原处,不会被自动清理。
也可以离线分发:pnpm pack 出 tarball 后 dsh plugin add ./dsh-session-delete-<版本>.tgz。包里带的是预构建产物(prepack 在打包时替你跑 build),所以这条路上用户不需要为构建脚本授权。
兼容性分两层,别混:
- 装得上由
package.json 的 peerDependencies 决定——宿主 dsh plugin add 会拿运行中的宿主版本逐项比对插件的 @deepseek-ai/dsh* peer 区间,不满足即拒绝并回滚。本插件一条 dsh-* peer 都没有(界面用的控件与图标已固化成 src/client/ui/*,浏览器半只 require React 家族这三个冻结平台模块),所以这道闸不限制它装在哪些代上。
- 真跑过由
dsh.compatibility.dshReleases 记录,只列实测过的宿主:DSH Desktop 0.2.0-rc.2(compatible)。别的 rc 装得上,但没验过。
用法
两个入口。
删除:会话条目右边的「…」菜单 → 「删除」→ 确认框(「移入回收站」)→ 会话进回收站。正在运行的会话这一行是置灰的,悬停给出「会话正在运行,先停止再删除」——本插件不替用户终止正在进行的活。
回收站:侧栏面板列表里常驻的「回收站」一行(与「插件」「小说」同层)。打开后是中央面板:
- 清单按项目分组,每条两行——标题 / 「刚刚删除 · 24KB」或「删除于 7分钟前 · 350KB」;「恢复」与「彻底删除…」在行右侧(前者描边、后者安静的红),点行本身是选中并在右边看详情
- 头部是条数与合计占用(「2 个会话 · 共 49KB」);页脚是「清空回收站…」——整页唯一一块实心红
- 头部下面那一排(不随清单滚走):全部折叠 / 全部展开、多选(「刷新」已删——每次读清单都会先与回收站目录对账,不再需要手动刷)
- 组头可以单独折叠(也可以一键全部折叠),折叠起来的组条目直接收掉、计数还留在组头上;多选态下组头多出一颗三态勾选框——点它就是把这个项目的全部会话选上(包括折叠起来看不见的),只勾了几条时显示半选
- 两栏之间那根线可以左右拖(也能聚焦后用 ←→ 调,Home 回默认 420):最窄 330(再窄「删除于 … · 大小」那一行就被截断了),最右拖到「详情还读得开」为止
- 多选态下:行右侧两颗按钮退场、标题左侧出勾选框,点行就是切换勾选;页脚那颗换成「彻底删除 N 条」(一条没勾时置灰并说明原因),确认后按清单顺序逐条执行,失败的那条把原文留在自己身上。退出多选即清空勾选,不留看不见的勾选
- 面板四态:读数中 / 空(「回收站是空的」,此时底部不出现「清空回收站…」)/ 读数失败(宿主原文 + 「重试」)/ 有条目
- 详情四态:未选中(一句引导)/ 读数中 / 读数失败(原文 + 重试,只坏详情这一块,清单照常选、动作照常点)/ 有内容。正文读的是回收站目录里那条会话自己的日志:只列你真实发的提问与助手的文字,宿主注入的上下文与工具调用不进正文(条数会在页面上说明)。助手的文字按 Markdown 排版(与宿主会话区同一套字号与 token),你的提问保持原话(不解析,换行与反引号照原样)
- 「恢复」按记录的原目录名放回原项目目录,并还原它原本的可见性:删除前未归档的,恢复后仍未归档;删除前已归档的,恢复后仍在归档态
回收站与数据
| 东西 | 位置 |
|---|
| 回收站本体 | ~/.dsh/session-trash/<时间戳>-<原目录名>/ |
| 回收站清单 | 本插件自己的 storage domain(介质在 ~/.dsh/storages/) |
- 回收站与
~/.dsh/sessions/ 同卷:搬进搬出靠整目录 rename,原子、瞬时
- 清单丢了不致命:会话文件自描述,解压后第一行即 header,含
id 与 cwd
- 不自动过期:不设天数上限,清空是显式动作;界面显示条数与占用
- 附件不连坐:附件是全局内容寻址的,与会话不是父子关系——删除不连带,也不会回收;被删会话独享的附件会留成垃圾(要回收得先有引用计数,属另一件事)
界面语言
中文 / English 挂在宿主自己的 locale 服务上,跟随设置的界面语言;服务不可用时退回内置中文。
常见问题
装完侧栏没有「回收站」,会话菜单里也没有「删除」?
先重启宿主。若仍没有,确认这一代宿主上本插件激活过——取数通道探测不过时,本插件一个入口都不注册:页面上看不出它的存在,但它也不会因此把宿主拖死。这是有意用「入口不出现」表达不可用,不是禁用态。
删完之后侧栏那一行怎么还在?
本插件只在宿主确实不再列它时才通告客户端把那一行去掉;拿不准时宁可沉默(那时说「已移除」是假话)。刚巧遇上就刷新页面,那一行会自己消失。本机运行期没打开过的冷会话走的是正常路径,删完即走。
正在运行的会话为什么删不掉?
判据用的是宿主自己的活跃检查(与官方归档的准入同源)。首版一律拒绝,不替用户终止正在进行的活——先停下这个会话再删。
能恢复多久?
不存在时间上限。不自动过期,只有你显式清空或彻底删除才会真的丢字节。
开发
pnpm install
pnpm build # tsdown:Node 半 + 浏览器半(含浏览器半的纯度门)
pnpm test # vitest run
pnpm typecheck # tsc --noEmit
本地源码调试
lib/ 是构建产物且不入库,从源码目录链进 profile 的安装方式不会替你构建它。
pnpm build # 必须在源码目录手动跑一次
dsh plugin --profile <profile> add "link:<本仓绝对路径>"
改动生效分两半:浏览器半(src/client/)由宿主 HMR 推到浏览器,无需重启;Node 半不在热重载链路内,必须重启宿主。
设计(五个触点、边界、错误形状、验证门、界面规格)住在 docs/design/2026-09-30-session-delete-design.md,README 不复述。
贡献
欢迎 Issue 与 PR。提交改动前请确保 pnpm test 与 pnpm typecheck 都通过,且两条命令的退出码都亲眼看过——跑门要把输出先灌进文件、再单独打印退出码,管道会把红吃掉。提交即表示你同意以 Apache-2.0 协议授权你的贡献。
许可
Apache-2.0