在侧边栏会话三点菜单的「归档会话」下面加一项「删除会话」:先把会话从内存里摘掉,再删磁盘记录与投影缓存,并立刻移除左侧那一行。永久删除,没有回收站。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:Dcmwfg/dsh-session-menu-delete
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
在 DSH Web GUI 的侧边栏,会话行三点菜单里加一项 删除会话(排在「归档会话」下面)。 确认后:永久删除该会话的磁盘记录与投影缓存,并立刻把左侧那一行摘掉。
DSH 自带的会话操作只有「归档」——归档只是收起来,日志文件还在磁盘上一直累积,没有删除入口。这个插件补的就是这一个缺口。
删了就没了。 这个插件不做回收站,删掉之后没有任何恢复入口。要可恢复的删除,别用这个。
- 纯本地:宿主半只监听回环地址,不联网、不调外部接口。
- 不改 profile 的
cordis.patch.yml:走插件自带的 bundle patch。 - 平台:Windows / macOS / Linux(不依赖任何平台专有 API)。
装
先克隆到本地(路径别带空格,Windows 上 link: + pnpm install 会做 junction,带空格或特殊字符容易失败):
git clone https://github.com/Dcmwfg/dsh-session-menu-delete.git
然后改 profile 的 package.json 两处:
// ~/.dsh/profiles/desktop/package.json
"dependencies": {
// 指向上一步克隆下来的目录(Windows 用正斜杠,别用反斜杠)
"dsh-session-menu-delete": "link:/path/to/dsh-session-menu-delete"
},
"dsh": {
"profile": {
"bundles": [
// …原有的…
"dsh-session-menu-delete"
]
}
}
profile 目录按系统不同:
- Windows:
%USERPROFILE%\.dsh\profiles\desktop - macOS / Linux:
~/.dsh/profiles/desktop
然后在 profile 目录里 pnpm install,重启 DSH。重启后侧边栏会话行的三点菜单里应该多出「删除会话」。
装完想看有没有装坏,重启前先跑一遍 dsh-plugin-guard(若已安装):
node <path-to>/dsh-plugin-guard/guard.mjs check --profile desktop
插件自带 cordis.patch.yml(- insert: 一条),由 bundle patch 机制加载,不用改 profile 的 cordis.patch.yml。
只想先试试,不想装
克隆下来直接跑自检,只碰临时目录和你的真实 .dsh 里的哑会话(real-home-test 会自己造自己删):
cd dsh-session-menu-delete
node scripts/selftest.mjs
卸载
- 从 profile 的
dsh.profile.bundles里删掉"dsh-session-menu-delete"; - 从
dependencies里删掉同名条目; - profile 目录里
pnpm install,重启 DSH。
卸载后菜单项消失。已经删掉的会话不会回来——这个插件不做回收站。
用
侧边栏 → 会话行右侧「…」→ 删除会话 → 永久删除。
实现
浏览器半(lib/client.js)注册两个插槽:
sidebar.workspaces.session.menu.item,order440:菜单项。shell.overlay:确认对话框。
宿主半(lib/index.js)起一个只监听回环的路由:
GET /api/dsh-session-menu-delete/healthPOST /api/dsh-session-menu-delete/delete{ "sessionId": "<uuid>" }
删除顺序(不能改):
- 会话还活在内存里 →
sessions.liveEntryFor()+detachEntered()摘掉,再摘 agent; - 等 800ms,让持久化 writer 的 drain 写完;
- 删
<DSH_HOME>/sessions/<workspaceKey>/<id>/与storages/session_projcache/sessions/<id>.json; - 等 400ms 补删投影缓存并
table.delete(id)(缓存服务会在 disposed 时异步回写一次); ctx.emit('api-session/removed', id)。
目录名与缓存名都有两种形态:裸 UUID 和 session-<uuid>(新会话未命名时落盘是后者)。插件先按传入的 id 精确找,找不到再试另一种写法——同一个 uuid 的两种写法指向同一个会话。目录没找到、只找到缓存时不报成功,直接返回 500 partial:只删缓存会让那一行在下次刷新时冒回来。
自检
node --check lib/index.js && node --check lib/client.js
node scripts/selftest.mjs # 40 项:路径解析、日志名版本兼容、目录名双形态、live 判定、删除、权限校验
node scripts/route-test.mjs # 14 项:真 HTTP 路由 + 403 护栏(只在临时目录里跑)
node scripts/client-test.mjs # 30 项:客户端渲染与 POST 契约
node scripts/real-home-test.mjs # 9 项:真实 DSH_HOME 下造哑会话删掉
兼容性
宿主没有公开的「会话文件操作」API,这个插件靠三样东西:侧边栏插槽、会话目录布局、内存会话服务。前两个是稳定契约,第三个是内部实现。
会话日志文件名不写死。 宿主自己生成的名字随格式版本走(session.jsonl / session.vN.jsonl,压缩时再加 .zstd),读的时候是「扫目录、取版本号最大的那个」。插件照同样规则认文件,所以:
- 老会话(v3 之类)能删;
- 将来框架升到 v5、v6,只要命名规则不变就继续能删;
- 目录里没有 canonical 日志名的目录,当杂项跳过,不误删。
依赖的内部 API(没有公开契约,宿主改内部实现就可能失效):
| 位置 | 用法 | 失效后的现象 |
|---|---|---|
sessions.liveEntryFor() / detachEntered() |
判断并摘除热会话 | live 会话删不掉,返回 409 带原因;冷会话不受影响 |
agents.store?.get?.() / agents.detachEntered() |
摘 agent | 可选调用,失败不影响删盘 |
ctx.get('sessionProjectionCache') 的 table |
直接删投影缓存条目 | 可选,退化成只删 json 文件 |
前两类都做了可选链与兜底,宿主不提供时降级而不是崩掉。代价是:如果哪天 DSH 改了这些方法名,卸载干净、最坏情况是「点了删除,磁盘删了但左侧列表还在」,刷新页面即正常——不会丢别的会话数据。
磁盘布局假设:<DSH_HOME>/sessions/<workspaceKey>/<sessionId>/(目录名可能是裸 UUID,也可能是 session-<uuid>)和 <DSH_HOME>/storages/session_projcache/sessions/<id>.json(同名两种形态)。DSH_HOME 解析顺序是 配置注入 → DSH_HOME → DSH_HOME_DIR → ~/.dsh,校验目录下至少有 sessions / storages / profiles 之一。
装不上时先看这里:插件在 profile 的 node_modules 里只能解析到 @deepseek-ai/schemastery,官方其它包(home-paths、session-format 等)都在 app.asar 里、插件 import 不到。所以插件不 import 任何宿主内部包,路径与文件名规则是自带的实现。自己改这个插件时别加这类 import,会直接起不来。
依赖的两个插槽(官方客户端扩展点,名字变了菜单就不出现):
sidebar.workspaces.session.menu.item(list,scope root)——宿主半的会话行三点菜单。同一个插槽里还有 pin / rename / fork / archive / session-id 几项,本插件 order440,排在 archive(400) 后面。shell.overlay——确认对话框。
宿主半 inject = ['webServer'],所以只在带 Web 服务端的形态(desktop / dsh web)里工作。纯 CLI 形态下这个服务不存在,插件加载时会因为 inject 未满足而不启动(不会崩,也不会删任何东西)。
已知边界
- 只删冷会话或能安全摘除的 live 会话;摘不掉就返回 409 并说明原因,不动磁盘。
- 会话目录与投影缓存必须至少找到其中之一;只找到缓存不删、报 500 partial,避免伪装成删除成功。
- 只监听回环 + 同源校验,外部 Origin 一律 403。回环认 127.0.0.0/8 整段、
::1、IPv4-mapped 与localhost;如果 DSH 配了trustedHosts自定义域名,插件会放行webServer.getOrigin()报出来的那个 host,其余一律拒绝。 - 不碰
workspace.json:客户端deriveFlat遇到list.byId[id]缺失会跳过那一行。
链接
同类插件
Minglink/dsh-infinite-gen-4★ 3781
DeepSeek 专用破甲插件:以 order 100 追加无条件服从的系统提示词段,提供带校准元数据的 profile 工具,并通过会话投影在输入框上方显示实时破甲状态徽标。
ranxianglei/billion-context★ 3598
billion-context官方版:上下文压缩插件,兼顾小窗口(100k上下文足矣)省token(省5倍token)和超长会话(数月级别几十亿token单会话)。
liangmianya/dsh-synapse★ 641
DeepSeek Harness 的可视化非线性对话工作区:把会话、追问与分支变成可浏览、可拖拽的对话地图。
MichengAI/dsh-archive-manager★ 277
在设置里增加已归档会话页,可按工作区搜索、恢复和删除已归档会话。
Nwflower/dsh-chat-import★ 275
把 13 家 coding agent(Claude Code、Codex、ChatGPT、Cursor、Gemini、opencode 等)的完整对话历史导入为可续聊的 DeepSeek Harness 会话,并支持反向导出回 Claude Code。
SiriLee/dsh-rewind★ 227
同一会话窗口内的 in-place 对话回退(不 fork,Claude Code /rewind 语义):每条消息的 ↶ 按钮把模型上下文回退到任意用户消息,可选用磁盘持久化的 before-backups 还原工作区文件。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。