右键永久删除会话并级联清理子代理
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/1 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add apherchin/dsh-session-delete该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:待复验
是什么
dsh 原生插件 · chat
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 33 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 12 处,展示前 11 条)
- 读取本地文件index.mjs:70
entries = await readdir(sessionDir, { withFileTypes: true }); - 读取本地文件index.mjs:88
const raw = await readFile(projectionCacheFile, "utf8"); - 读取本地文件core.mjs:40
projects = await readdir(rootResolved, { withFileTypes: true }); - 读取本地文件core.mjs:60
info = await stat(candidate); - 读取本地文件core.mjs:84
entries = await readdir(target, { withFileTypes: true }); - 读取本地文件core.mjs:95
info = await stat(child); - 读取本地文件core.mjs:117
const raw = await readFile(projectionCacheFile, "utf8"); - 读取本地文件core.mjs:201
info = await stat(target); - 删除本地文件core.mjs:224
await rm(target, rmOptions); - 读取本地文件cascade.mjs:163
const info = statSync(logFilePath); - 读取本地文件cascade.mjs:175
buffer = readFileSync(logFilePath);
扫描于 2026/11/2(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 永久删除会话
- 级联清理子代理
- 拒绝删除活跃会话
DSH 会话行菜单「删除会话」:永久删除会话,级联到子代理会话,拒绝删除活跃会话。宿主 + 客户端 Cordis 插件(打包形式)。
README
由 DeepSeek 最新模型翻译生成@apherchin/dsh-session-delete
给 DeepSeek Harness 补上官方缺失的会话删除能力。
在会话行的右键菜单里加两行:「复制会话 ID」(只读,随时可用)与「删除对话」(破坏性,永远排在最后)。
点删除 → 统计 → 确认 → 真删磁盘数据;顺带级联删掉子代理会话。
会话右键菜单效果图:官方四项之后是本插件新增的「复制会话 ID」与「删除对话」
☝️ 效果图:置顶会话 / 重命名 / 分叉会话 / 归档会话 是官方项;复制会话 ID(order 450)与 删除对话(order 500) 是本插件新增的两行 —— 破坏性动作排在最后。
中文 | English
它解决什么
DSH 官方只有「归档会话」(隐藏,日志保留),没有删除。于是:
- 会话列表里堆着测试用的、跑废的会话,只能一直藏着;
- 手动去 ~/.dsh/sessions/... 删目录也能删掉文件,但侧栏条目仍在(宿主列表 = 内存里活着的 attached + 磁盘上的 persisted),看起来像"删除没生效";
- 子代理会话(一个父会话派生出多个)得自己去辨认、一个个删。
本插件把这三件事一次做完,并且在删之前把代价摆给你看。
功能
| 入口 | 行为 |
| 会话行 …
展开完整文档(README 剩余 1 节)
@apherchin/dsh-session-delete
给 DeepSeek Harness 补上官方缺失的会话删除能力。
在会话行的右键菜单里加两行:「复制会话 ID」(只读,随时可用)与「删除对话」(破坏性,永远排在最后)。
点删除 → 统计 → 确认 → 真删磁盘数据;顺带级联删掉子代理会话。
会话右键菜单效果图:官方四项之后是本插件新增的「复制会话 ID」与「删除对话」
☝️ 效果图:置顶会话 / 重命名 / 分叉会话 / 归档会话 是官方项;复制会话 ID(order 450)与 删除对话(order 500) 是本插件新增的两行 —— 破坏性动作排在最后。
中文 | English
它解决什么
DSH 官方只有「归档会话」(隐藏,日志保留),没有删除。于是:
- 会话列表里堆着测试用的、跑废的会话,只能一直藏着;
- 手动去 ~/.dsh/sessions/... 删目录也能删掉文件,但侧栏条目仍在(宿主列表 = 内存里活着的 attached + 磁盘上的 persisted),看起来像"删除没生效";
- 子代理会话(一个父会话派生出多个)得自己去辨认、一个个删。
本插件把这三件事一次做完,并且在删之前把代价摆给你看。
功能
| 入口 | 行为 |
| 会话行 … 菜单 → 删除对话(order: 500,排在官方「归档会话」(400) 之后) | 打开确认弹窗;确认后永久删除该会话 |
| 会话行 … 菜单 → 复制会话 ID(order: 450) | 复制 id(只读动作,运行中的会话也能复制)—— 细节见下一节 |
| 会话行 … 菜单 → 悬停/点击后弹窗里显示 | 删除前统计:目标字节数、将被一并删除的子代理会话数、子会话 ID 清单(可选中复制) |
- 级联删除:删父会话时,把它派生的子代理会话一并删掉(子会话走与目标同一套删除序列 + 同一条广播)。
- 活跃会话一律拒绝:目标在运行 ⇒ 409 SESSION_ACTIVE;任一子会话在运行 ⇒ 409 CHILDREN_ACTIVE —— 整单拒绝,一个字节都不删(客户端也会提前把删除键置灰)。
- 诚实的成功反馈:删完不自动关弹窗。宿主按内存里是否还挂着该会话回三种状态:
- attached === true(打开过、仍在内存里)→ 明说「磁盘已删,但侧栏条目会一直显示,请关闭它的标签页或重启 DSH」;
- attached === false → 「已删除会话:」;
- 判不了 → 通用兜底(绝不猜)。
- 统计失败绝不影响删除:dryRun 失败或 5 秒超时一律降级为"未统计",删除键保持可用。
「复制会话 ID」:它复制的是什么、ID 从哪来、拿来干嘛
复制的是什么 —— 该会话的原始 ID 字符串,逐字不改:不剥 session- 前缀、不补前缀、不做大小写或格式转换。
之所以"照抄不加工",是因为这个串是要拿去和磁盘目录名 / 日志文件 / 别的工具对账的 —— 插件一旦替你改写,反而对不上。
ID 从哪来 —— 这一行由官方槽位 sidebar.workspaces.session.menu.item 渲染,ID 就是该槽位交给插件的 sessionId 属性(即宿主会话投影里的会话 ID)。插件不猜、不生成、不额外查库;又因为它是纯只读动作,运行中的会话也能复制(不碰宿主的活体判据,也不带任何 disabled)。
两种历史形态并存(本机 ~\.dsh 实测):
| 形态 | 实例 | 本机数量 |
| 带前缀(较早) | session-7a87d682-0631-4781-94c6-73ceccb6f111 | 46 个会话目录 / 55 个投影缓存 |
| 裸 UUIDv7(较新) | 019c8fef-cb98-4f2c-8521-a28e67e5e9ae | 266 个会话目录 / 266 个投影缓存 |
你复制到的就是那个会话真实使用的那一个。删除/定位路径对两种都成立:入口先 isValidSessionId(两种形态都放行),再在 sessions 根目录的第一层项目目录下按 basename 精确匹配定位(另有反穿越三重断言),不自己重实现「cwd → 目录名」的转义规则(避免与后端逻辑漂移)。
反馈(不会静默失败) —— 先弹「正在复制」,剪贴板结果回来后回填:
- 成功 → 已复制会话 ID:
- 失败(剪贴板 API 不可用 / 被拒绝)→ 复制失败,请手动复制会话 ID:,并把 id 以 + user-select: all 摆出来 —— 单击即可全选抄走
- 提示 约 2 秒后自动消失;后一次复制会取代前一次的提示(旧提示不会被"复活");整条路径 绝不抛(菜单回调里抛错会变成无人处理的错误)
拿来干嘛(下表路径均为本机实测存在):
| 用途 | 形式 |
| 会话正文日志 | ~\.dsh\sessions\\\session.v4.jsonl.zstd(项目目录名是路径转义形态,如 --D-DSH-Day1--) |
| 侧栏投影缓存(标题 / 待办等) | ~\.dsh\storages\session_projcache\sessions\.json |
| 归档 / 置顶记账 | ~\.dsh\storages\workspace.json → global.archivedSessionIds / global.pinnedSessionIds |
| 报 bug / 排查 | 直接给出 ID 就能精确定位到那一个会话(不用再描述"哪个项目里的第几个") |
| 和本插件交互 | 宿主路由 POST /api/session.delete 吃的就是同一个 sessionId |
| 和本仓库另一个插件联动 | 通知插件的点击回调协议 dsh-attention:open/ |
| 级联删除时 | 确认弹窗里列出的子代理会话也是同一套 ID 串(可选中复制) |
为什么它是单独一行而不是塞在删除弹窗里:它只读、随时可用;而删除是破坏性动作。
菜单里 order: 450(复制)在 order: 500(删除)之前,破坏性动作永远排最后。
安全边界
- 只动三处:sessions// 目录、storages/session_projcache/sessions/.json、workspace.json 里的 archivedSessionIds / pinnedSessionIds 记录。
- 不碰附件目录(附件只增不减是设计如此)。
- 破坏性动作排在菜单最后;确认框默认焦点在「取消」;危险色用官方 --dsw-alias-state-error-primary。
- 顺序不变量:先读子会话列表、再删任何东西(日志一旦被删就读不出子会话了)。
安装
dsh plugin --profile add @apherchin/dsh-session-delete
包内声明了 dsh.bundle.patch,所以 dsh plugin 会自动把它记进 dsh.profile.bundles,不需要手工编辑 profile 文件。然后重启 DSH(打包版没有“刷新页面”)。
手动兜底(不用 dsh plugin 时):pnpm add @apherchin/dsh-session-delete,再在 cordis.patch.yml 追加
- insert:
- id: session-delete
name: "@apherchin/dsh-session-delete"
兼容性
- 实测环境:DSH 桌面壳 0.1.7-rc.2(Windows / Electron)。
- 用到的主机服务:connection、workspaceRegistry、agents(并可选探测 sessions,不可用不影响任何功能)。
- 用到的客户端槽位:sidebar.workspaces.session.menu.item(官方槽位)、shell.overlay。
- 无 npm 依赖、无安装脚本、无构建步骤:client.js 就是可直接加载的单文件浏览器工件。
与同类插件的区别
npm 上已有两个做“DSH 会话删除”的包,本插件的差异在入口与安全性:
| | vtxf/dsh-session-delete | youqu68/dsh-delete-chat | 本插件 |
| 入口 | 侧栏会话菜单 | 设置页里的会话管理页 | 侧栏会话菜单(官方槽位) |
| 菜单怎么挂 | DOM 注入 + MutationObserver 克隆现有菜单项(作者自述“官方未开放该菜单的扩展 Slot”) | 不挂菜单(自带页面) | 官方槽位 sidebar.workspaces.session.menu.item |
| 批量操作 | 目录级归档/删除全部 | 列表页勾选 | 不做(有意,见下) |
| 子代理会话 | 不处理 | 不处理 | 级联删除 + 运行中整单拒绝 |
| 删除前统计 | 无 | 两步确认(显示路径) | 字节数 + 子会话数 + 子会话 ID 清单 |
| 删除后的诚实反馈 | 无 | 无 | attached 三态(打开过的会话会照实说“行还在”) |
本插件有意不做批量删除全部:那是不可逆的高危操作,而侧栏菜单没有足够的确认空间。请用官方的归档,或逐个删。
架构
index.mjs 主机半边:路由 POST /api/session.delete(含 dryRun 分支)、活体拒绝、级联计划、 attached 三态探测、门控摘记账、api-session/removed 广播 core.mjs 纯逻辑:校验 / 定位 / 删除序列(可离线单测) cascade.mjs 纯只读:从多帧 zstd 会话日志里认出子代理会话(不写任何东西) client.js 客户端半边:window.__ModuleLoader__ 单文件工件—— 菜单两行 + 确认/结果弹窗 + 复制提示;自带全部原语(见下) cordis.patch.yml 本 bundle 的装配层:一行 insert
locale/{zh,en}.json GUI 卡片上的标题与描述
合规说明(按官方 cordis-plugin-development 技能逐条对齐)
- bundle 形态:package.json 声明 dsh.bundle.patch(官方交付单位;缺它 install_bundle 会回滚整次安装)。
- 客户端 manifest:dsh.client.platform = "web" + 导出 ./client,浏览器工件的 factory id 等于包名。
- 不 require 任何 Harness Client 包。官方 practices 明文禁止 require("@deepseek-ai/dsh-client-ui-primitives") 等,理由不是“拿不到”(平台静态模块表里能解析),而是升级稳定性:它们会无预告变更、纯 JS 无类型检查,而抛错的组件会让整块 slot entry 空白。
⇒ 本插件把用到的 5 个原语(MenuItemButton / Modal / Button / 两个图标)与 1 个 store (createSnapshotStore)全部按行为自包含实现:SVG 路径、CSS 规则、每一条 --dsw-alias- token 引用都取自官方 dsh-client-ui-primitives 的 lib/index.js 与 lib/{Button,Menu,Modal}.module.css,类名统一加 dsd- 前缀(官方建议的做法)。运行期只 require react / react-dom / react/jsx-runtime(基座)。
- 主机半边零 @deepseek-ai/ 运行时 import(只读 ctx 上的服务)。
- 不 append 新的 session 事件类型(官方不变量;否则会话会打不开)。
- 缺失的服务一律降级为 no-op 且不打日志,apply 绝不外抛(client 插件抛错会撞渲染端「每条 client entry 必须 active」的全有全无启动门禁 ⇒ 整机起不来)。
开发与验证
node test/host-smoke.test.mjs # 主机接线与路由分支:90/90
node test/cascade.test.mjs # 级联识别(含真实多帧 zstd 样本):52/52
node test/client-bench.test.mjs # 客户端离线验证台(结构断言):256/256
node test/client-prime-probe.test.mjs # 正面探针:portal / 样式注入 / 弹窗键盘层:21/21
⚠️ 逐个文件跑,不要用 node --test:本机沙箱禁止命名管道,runner 会 spawn EPERM 并给出误导性的 # fail 1。
⚠️ 浏览器半边改了之后必须整机重启 DSH 才生效(打包版没有「刷新页面」)。
Session context menu: the last two rows are added by this plugin
The screenshot above: Pin / Rename / Fork / Archive are the official rows; Copy session ID (order 450) and
Delete conversation (order 500) are added by this plugin — the destructive action goes last.
What it solves
DeepSeek Harness ships archive but no delete. Deleting ~/.dsh/sessions/... by hand removes the files but
leaves the sidebar row behind (the host list is attached sessions plus persisted ones), which looks like the
deletion failed. Subagent sessions must be hunted down one by one. This plugin does all of it, and shows you the
cost before you confirm.
Features
- Session row … menu → "Delete conversation" (order: 500, after the official "Archive" row).
- Session row … menu → "Copy session ID" (order: 450; read-only, works on running sessions too).
- Pre-delete dry run: target byte count, how many subagent sessions will go too, and their IDs (selectable).
- Cascade: deleting a parent also deletes the subagent sessions it spawned.
- Live sessions are refused: target running → 409 SESSION_ACTIVE; any child running → 409 CHILDREN_ACTIVE
and not a single byte is deleted (the client greys out the delete button ahead of time).
- Honest success feedback: the dialog does not auto-close. The host reports whether the session is still
resident in memory (attached: true | false | undefined) and the three cases get different text — when a session was opened, it says plainly that its sidebar row will keep showing until you close the tab or restart DSH.
- Statistics never block deletion: a failed or 5s-timed-out dry run degrades to "not measured" and the delete
button stays enabled.
"Copy session ID": what it copies, where the ID comes from, what it is for
- What it copies — the session's raw ID string, verbatim: no prefix stripping, no reformatting. The string is meant to be reconciled against directory names, log files and other tools, so rewriting it would only break the match.
- Where the ID comes from — the row is rendered by the official sidebar.workspaces.session.menu.item slot, and the ID is exactly the sessionId prop that slot hands to the plugin (the session ID from the host's session projection). 该插件从不猜测、生成或查找任何内容;而且由于该操作是只读的,它也能在运行中的会话上工作(没有存活门控,也没有 disabled 状态)。
- 两种历史形态并存(在本机上实测):session-(46 个会话目录 / 55 个缓存文件)以及裸 UUIDv7,例如 019c8fef-…(266 / 266)。你始终复制该会话实际使用的那一个;两者都被 isValidSessionId 接受,并且目录是通过在 sessions/ 的一级项目目录内进行精确 basename 匹配来定位的(带有三个防穿越断言),而不是重新实现 cwd→dirname 的转义。
- 反馈从不静默——先出现一条“copying”提示,然后解析为 已复制会话 ID: 或复制失败,请手动复制会话 ID:(该 ID 以 渲染并带有 user-select: all,因此点击一次即可选中)。
该提示约 2 秒后自动消失,较新的复制会取代较旧的提示,并且整条路径从不抛出异常。
- 它的用途——该 ID 是访问该会话产物的钥匙:
| 用途 | 形式 |
| 会话记录 | ~\.dsh\sessions\\\session.v4.jsonl.zstd(项目目录是转义后的路径,例如 --D-DSH-Day1--) |
| 投影缓存(标题、待处理) | ~\.dsh\storages\session_projcache\sessions\.json |
| 归档 / 固定簿记 | ~\.dsh\storages\workspace.json → global.archivedSessionIds / global.pinnedSessionIds |
| Bug 报告与日志分诊 | 引用该 ID,即可精确定位到那一个会话 |
| 与此插件通信 | 宿主路由 POST /api/session.delete 接受相同的 sessionId |
| 与此仓库中其他插件通信 | 通知插件的点击回传协议 dsh-attention:open/ |
| 级联删除 | 确认对话框中列出的子会话使用相同的 ID 字符串(可选中) |
它之所以是单独的一行,而不是埋在删除对话框里的某个东西,是因为它是只读的,并且随时可用: order: 450(复制)先于 order: 500(删除),因此破坏性操作始终排在最后。
安全边界
- 只触及三个位置:会话目录、其投影缓存文件,以及 workspace.json 中的 archivedSessionIds / pinnedSessionIds 簿记。附件目录保持不动。
- 破坏性行位于菜单最后;确认对话框默认聚焦取消。
- 顺序不变量:子会话列表在删除任何内容之前读取(列出子会话的那条日志正是要被移除的东西)。
安装
dsh plugin --profile add @apherchin/dsh-session-delete
该包声明了 dsh.bundle.patch,因此 dsh plugin 也会将其记录到 dsh.profile.bundles 中——无需编辑 profile 文件。
之后重启 DSH(打包构建没有“reload page”)。
兼容性
已在 DSH 桌面版 0.1.7-rc.2(Windows/Electron)上测试。宿主服务:connection、workspaceRegistry、agents (外加对 sessions 的可选探测)。客户端插槽:sidebar.workspaces.session.menu.item(官方插槽)和 shell.overlay。无 npm 依赖,无安装脚本,无构建步骤。
它与其他两个有何不同
另外两个 npm 包已经可以删除 DSH 会话。这个包的不同之处在于入口点和安全性:它使用官方菜单插槽(而非 DOM 注入 + MutationObserver),它会级联到子代理会话,并且如果有任何子会话正在运行,就拒绝整个请求;它在确认前显示字节数/子代理数量,并且如实报告 attached 状态,而不是声称已干净删除。批量“删除全部”被刻意未实现。
合规性(与官方 cordis-plugin-development 技能保持一致)
- Bundle 形式:声明了 dsh.bundle.patch(官方交付单元;没有它,install_bundle 会回滚整个安装)。
- 客户端清单:dsh.client.platform = "web" + 一个 ./client 导出,其工厂 id 等于包名。
- 没有 require 任何 Harness Client 包。 官方实践禁止
require("@deepseek-ai/dsh-client-ui-primitives") 之类的做法——不是因为它们无法被解析,而是因为它们
会在毫无通知的情况下变化,纯 JS 插件没有类型检查,而且一个抛错的组件会让你的插槽条目变成空白。
这里使用的五个原语(MenuItemButton / Modal / Button / 两个图标)和一个 store (createSnapshotStore)因此都是自包含重新实现的,其 SVG 路径、CSS 规则以及每一处 --dsw-alias- token 引用都取自随附的 dsh-client-ui-primitives,并且类名在 dsd- 前缀下重命名。运行时只要求 react / react-dom / react/jsx-runtime(基线)。
- 宿主端不导入任何 @deepseek-ai/ 运行时包,并且不追加任何新的会话事件类型。
- 缺失的服务会降级为 no-op,且不记录日志,并且 apply 从不抛错(一个抛错的客户端入口会触发渲染器的全有或全无启动门禁,并导致整个应用崩溃)。
开发与验证
node test/host-smoke.test.mjs # host wiring and route branches: 90/90
node test/cascade.test.mjs # child-session detection on real multi-frame zstd: 52/52
node test/client-bench.test.mjs # offline client bench with structural assertions: 256/256
node test/client-prime-probe.test.mjs# positive probe: portal / style injection / modal keyboard layer: 21/21
⚠️ 请逐个运行这些文件——这里不要使用 node --test(沙箱禁止命名管道;运行器会以误导性的 # fail 1 失败)。
⚠️ 更改浏览器端后,你必须重启 DSH;打包构建没有页面重载。
许可证
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
apherchin/dsh-session-delete
右键永久删除会话并级联清理子代理
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,482已汉化DSH
73
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,848已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,246已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
DS Bot 是一个基于 DeepSeek Harness简称 dsh的 bot 插件,插件将 dsh 改造为 bot…
★ 4,717已汉化DSH
71.1
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,711已汉化DSH
71.1