🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

会话删除 BigPizzaV3/dsh-session-delete

DeepSeek Harness
BigPizzaV39 天前有提交已提供中文文档扫描:含敏感能力

DeepSeek Harness(dsh)的非官方删除会话插件:会话菜单项加应用内对话框,在已鉴权的 /api 通道上挂 Fetch 路由,挂载中的会话排队删除。附带离线 host/client 测试。

30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/26 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add BigPizzaV3/dsh-session-delete
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · other
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 9 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 43 处,展示前 24 条)
  • 删除本地文件递归
    index.js:474
    await rm(directory, { recursive: true, force: true });
  • 读取本地文件
    index.js:644
    const parsed = JSON.parse(await readFile(pendingPath(), 'utf8'));
  • 删除本地文件
    index.js:660
    await rm(file, { force: true });
  • 写入本地文件
    index.js:663
    await mkdir(dirname(file), { recursive: true });
  • 写入本地文件
    index.js:664
    await writeFile(file, `${JSON.stringify({ version: 1, sessionIds }, null, 2)}\n`, 'utf8');
  • 读取本地文件
    index.js:738
    projects = await readdir(root, { withFileTypes: true });
  • 读取本地文件
    index.js:746
    if ((await stat(candidate)).isDirectory()) return candidate;
  • 删除本地文件
    index.js:772
    await rm(projection, { force: true });
  • 读取本地文件
    index.js:808
    await stat(path);
  • 发起网络请求
    client.js:150
    const response = await fetch(path, {
  • 删除本地文件递归
    test-host.mjs:28
    await rm(HOME, { recursive: true, force: true });
  • 写入本地文件
    test-host.mjs:39
    await mkdir(join(SESSIONS, PROJ, id), { recursive: true });
  • 写入本地文件
    test-host.mjs:40
    await writeFile(join(SESSIONS, PROJ, id, 'session.v4.jsonl.zstd'), id);
  • 写入本地文件
    test-host.mjs:42
    await mkdir(join(SESSIONS, '_no-cwd', 'session-orphan'), { recursive: true });
  • 写入本地文件
    test-host.mjs:43
    await writeFile(join(SESSIONS, '_no-cwd', 'session-orphan', 'session.v4.jsonl.zstd'), 'orphan');
  • 写入本地文件
    test-host.mjs:44
    await mkdir(PROJECTION_DIR, { recursive: true });
  • 写入本地文件
    test-host.mjs:46
    await writeFile(join(PROJECTION_DIR, `${id}.json`), '{}');
  • 读取本地文件
    test-host.mjs:116
    if (existsSync(directory)) records.push({ header: { id } });
  • 读取本地文件
    test-host.mjs:133
    state.disposeSawDirectory = existsSync(join(SESSIONS, PROJ, id));
  • 发起网络请求
    test-host.mjs:218
    const response = await route.fetch(
  • 读取本地文件
    test-host.mjs:277
    check('cold log dir removed', existsSync(join(SESSIONS, PROJ, 'session-abc')), false);
  • 读取本地文件
    test-host.mjs:278
    check('cold projection removed', existsSync(join(PROJECTION_DIR, 'session-abc.json')), false);
  • 读取本地文件
    test-host.mjs:302
    check('live log dir removed after dispose', existsSync(join(SESSIONS, PROJ, 'session-live')), false);
  • 读取本地文件
    test-host.mjs:303
    check('live projection removed after dispose', existsSync(join(PROJECTION_DIR, 'session-live.json')), false);
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
@local/dsh-session-delete 给 dsh 补上官方刻意没有的「删除会话」。dsh 0.2.x 里会话只能归档: dsh-session-persistence 与 dsh-session-persistence-jsonl 的文档都写明「seam 无删除接口,日志在 root 下累积,直到外部移除」, dsh-client-ui-workspace 也把「没有 Session 删除」列为已知限制。 本插件在不修改 app 本体的前提下,把「外部移除」这一步做成可点的操作。 它做什么 删除一个会话,或一个 Workspace 分组下的全部会话。每删一个会话,清理两处磁盘产物: | 内容 | 路径 | | 会话日志目录 | $DSH_HOME/sessions/<项目目录>/<session-id>/(读 ctx.sessionPersistence.root,缺省 ~/.dsh/sessions) | | 投影缓存 | $DSH_HOME/storages/session_projcache/sessions/<session-id>.json | | 粒度 | 入口 | Host 路由 | | 单个会话 | 会话行 … → 删除会话…
展开完整文档(README 剩余 1 节)
@local/dsh-session-delete

给 dsh 补上官方刻意没有的「删除会话」。dsh 0.2.x 里会话只能归档: dsh-session-persistence 与 dsh-session-persistence-jsonl 的文档都写明「seam 无删除接口,日志在 root 下累积,直到外部移除」, dsh-client-ui-workspace 也把「没有 Session 删除」列为已知限制。
本插件在不修改 app 本体的前提下,把「外部移除」这一步做成可点的操作。

它做什么

删除一个会话,或一个 Workspace 分组下的全部会话。每删一个会话,清理两处磁盘产物:

| 内容 | 路径 |
| 会话日志目录 | $DSH_HOME/sessions/<项目目录>/<session-id>/(读 ctx.sessionPersistence.root,缺省 ~/.dsh/sessions) |
| 投影缓存 | $DSH_HOME/storages/session_projcache/sessions/<session-id>.json |

| 粒度 | 入口 | Host 路由 |
| 单个会话 | 会话行 … → 删除会话…(slot sidebar.workspaces.session.menu.item,order 500) | POST /api/dsh-session-delete/session |
| 整个分组 | 分组行 hover → 垃圾桶按钮;或任意会话 … → 删除分组内全部会话…(order 600) | POST /api/dsh-session-delete/workspace |
| 单个会话(无 UI) | /session-delete <session-id> | 同一 Host 实现 |

分组删除默认包含已归档会话,确认框里可以用 同时删除已归档会话 取消勾选;「未分组」桶也可以整组删除。

为什么走 Fetch 路由,而不是 RPC 通道

宿主半侧用 ctx.connection.fetch.register({ path, methods, requestBody, fetch }) 注册一条 /api/... 下的精确 Fetch 路由——和随附的 /api/session.export (会话日志导出)、/api/session/uploadFileBinary(附件上传)完全同一套机制,由 Connection 已经挂好的 /api 前缀路由做 Host/Origin 校验 + 浏览器认证,因此插件只需要 inject: ['connection', 'sessions']。

不要改成 ctx.connection.rpc.handle()。 那个方法在 dsh-client-connection/lib/index.js:656 用 owner.webServer.register(route) 注册路由,而 owner 来自服务自身的 shadow context;dsh-client-connection 只在自己的
ctx.inject(["webServer"], …) 子上下文里用过 webServer,根上下文从不注入它,
所以任何调用方都会撞上 cannot get property "webServer" without inject (0.2.0-rc.2 里没有任何随附包调用 rpc.handle,只有 intercept 和 fetch.register 的调用方)。
1.0.0/1.0.1 就是踩了这个坑。

安全边界

- 先关闭,再 unlink:目标还挂在 ctx.sessions / ctx.agents 里时,宿主先用 agent 工厂自己的 teardown 句柄(agentLoop.prepare() 返回的 dispose,和 ACP session/close 同一条路径)取消回合、等待 idle、关闭 JSONL 写句柄并释放写锁、从两个 store detach;只有这些都完成后才 rm 目录。因此不会出现「写入方继续往已解除链接的 inode 追加」的静默丢数据。
- 拿不到句柄才排队:极少数在插件加载前就已发布、且控制器 effect 也定位不到的活会话,仍写进 session-delete-pending.json,下次启动时删除;这是兜底,不再是「打开过会话」的常态。
- 拒绝路径穿越:sessionId 必须是单一安全路径段,含 .. 或 / 一律 400。
- 分组成员由 Host 解析:浏览器只传 workspaceId(或 null 表示未分组),Host 用
workspaceRegistry.get(id).sessionIds 取成员;未分组由 Host 列会话并排除 origin: 'subagent'
的子代理。客户端递来的 id 不会越过分组边界。
- 分组 Header 是装饰,不是替换:随附 Workspace Header 的 … 菜单是硬编码的 rename/delete 数组,没有 additive slot。浏览器半侧只在已渲染的 [data-row-key^="workspace:"] 行里插入一个 hover 垃圾桶按钮,并用 capture 阶段代理点击;找不到 rowActions 结构时自动跳过,不替换/重绘官方 UI。会话菜单里的同一分组功能始终可用。
- 找不到就拒绝:不会猜测 cwd 编码,而是在会话根下逐个项目目录找同名目录(涵盖 _no-cwd)。
- 不碰附件:$DSH_HOME/attachments/v1 是内容寻址的共享对象,按会话删会连累其他会话,本插件不动它。
- 不可撤销,也没有回收站。

安装

先在任意位置拿到本仓库(git clone https://github.com/BigPizzaV3/dsh-session-delete.git,或直接下载 zip 解压)。安装入口都要求这个目录的绝对路径,并会在 profile 目录跑 pnpm、把包选进 dsh.profile.bundles——不要手工改 profile 的 package.json / cordis.patch.yml (随附的 cordis-plugin-development 技能明确禁止):

- A. Web 侧栏「插件」页 → 添加插件 → 填本仓库目录的绝对路径,例如 ~/Documents/dsh-session-delete(展开成绝对路径)。
- B. 切到 cordis(Creator)会话预设,让智能体用 plugin_manager 工具 install_bundle,target 同样是那个绝对路径。

也可以先跑一遍自带测试确认宿主侧逻辑(纯 Node,无依赖):

node test-host.mjs # 64/64
node test-client.mjs # 52/52

本机 bundle 已经装入(配置档的 node_modules/@local/dsh-session-delete 是指向本目录的符号链接),因此装/改代码后重启一次进程即可加载新的模块代际,不必重装。cordis-plugin-loader 用裸 import() 且无缓存击穿,hmr.root: [] 不热重载模块——改 JS 必须重启才加载新代码;只有改 cordis.patch.yml 配置才走 HMR 即时生效。注意:这次重启只是为了加载补丁,删除操作本身不再需要重启。卸载:插件页卸载该 bundle,或 plugin_manager remove_bundle。

使用

1. 删单个会话:会话行 … 菜单点 删除会话…,或在输入框执行 /session-delete session-xxxxxxxx-...。
2. 删一个分组:把鼠标移到分组行上,点垃圾桶按钮;或在组内任意会话的 … 菜单点 删除分组内全部会话…。确认框会显示分组成员数,默认勾选 同时删除已归档会话;取消勾选就只删当前可见的(未归档)成员。点确认后 Host 逐个关闭/删除并返回摘要(已删除、已排队、原本不存在、失败数)。
3. 冷会话(本次启动以来没被打开过):立即删除日志目录 + 投影缓存,宿主半侧同时把该 id 从 Workspace 记账里 detachSession 掉;浏览器半侧 ctx.sessions.refresh() 重拉会话基线,侧栏那行当场消失;若删的正是当前主视图,先 uiWorkspace.clearMain() 释放引用,不会停在「历史加载失败」上。
4. 已打开的活会话:宿主先发 workspace/session-stop 停掉该会话的回合、子代理、任务和终端,再调用工厂的 teardown 句柄(取消 → 等 idle → 关闭写句柄/释放 lease → detach)。session/disposed 会转成 Session 控制器的 api-session/removed,所有已连接的侧栏当场移除该行,随后才删日志目录与投影缓存。整个过程不需要重启。分组删除会逐个会话走同一条路径。
5. 兜底队列:只有「活会话存在、但工厂句柄和控制器 effect 都拿不到」的极端情况才写 $DSH_HOME/storages/session-delete-pending.json,对话框显示「已安排删除,重启后消失」;插件在下次启动时(apply 阶段,浏览器还没挂载任何会话)删除并清空队列。分组摘要里这部分计入「已排队」。

为什么现在能立即删 live 会话

会话被打开后 attach 到宿主进程,ctx.sessions / ctx.agents 的 enter() 只把 detach 句柄交给创建它的工厂(dsh-agent-loop),没有任何公开 API 能让第三方插件卸载一个活会话。但工厂在
prepare() 里已经返回了 { agent, dispose }——ACP 的 session/close 用的正是这个 dispose。
本插件在激活时包住 agentLoop.prepare(),按 Session id 记住这个 teardown 句柄;删除时直接调用它,因此能先安全关闭写入方再 unlink。若某个会话在插件加载前就已发布,则回退到控制器 fiber 上的
agentLoop.lifecycle(<id>) owner effect;两条路都不可达时才排队。

1.0.2 及更早:文件删掉了,但侧栏行要手动刷新页面(Cmd+R)才消失——那是浏览器缓存的会话基线快照,删除动作本身不产生任何 UI 事件。1.0.3 起冷会话自动刷新;1.0.7 起活会话走 session/disposed → api-session/removed,连刷新都不需要。

已验证 / 未验证

- 宿主半侧:node test-host.mjs(64/64 通过)覆盖两条路由注册形状(/api 前缀、 POST、buffered)、冷会话立即删除、投影缓存清理、Workspace 记账 detach、活会话先 workspace/session-stop → 调用工厂 dispose → 确认 dispose 时文件还在 → 之后才删目录、拿不到句柄时的排队兜底 → 下次启动扫描删除 → 队列清空、分组删除的 archived 过滤、 Workspace 记账同步、缺失分组 404、非法 body 400、未分组桶、subagent 排除、.. 穿越拒绝、未知 id 拒绝、非 JSON 请求体、_no-cwd 项目、命令入口;并用 Cordis 风格的 inject 守卫断言宿主半侧 不再触碰 webServer。
- 客户端半侧:node test-client.mjs(52/52 通过)用最小 React 替身(带 hook 槽)加载 window.__ModuleLoader__ 模块,断言 slot 注册形状、中英两套文案(单会话/分组菜单项、对话框标题/正文/按钮、排队提示、活会话拒绝、分组摘要/失败)、菜单行悬停高亮与键盘焦点环、点击行打开对话框、分组菜单在单成员组隐藏、archived 勾选改变计数、分组请求成功摘要与「找不到分组」本地化、未分组桶、成功删除关闭浮层并刷新基线、蒙板 token,以及源码里 没有 window.confirm/alert 调用、分组 Header 装饰选择器存在。
- 仍未做:在真实页面上点一次分组垃圾桶(DOM 装饰的视觉与 React reconciliation 行为);分组功能在会话 … 菜单里有同一实现的备用入口,不依赖该装饰。

变更记录

- 1.0.8 — 新增删除整个分组:宿主新增 POST /api/dsh-session-delete/workspace
({ workspaceId, includeArchived }),由 workspaceRegistry 解析分组成员,再逐个复用单会话的
stop → dispose → detach → rm 路径,返回 deleted/queued/missing/failed 摘要;workspaceId:null 走未分组桶并排除 subagent。客户端新增分组确认框(成员数、已归档勾选、摘要/失败列表),并在分组行 hover 区插入一个垃圾桶按钮;由于随附 Header 菜单是硬编码数组、没有 additive slot,该按钮是 DOM 装饰,找不到结构时自动跳过。同一功能也挂在任意会话 … 菜单(order 600)作为不依赖 DOM 装饰的备用入口。测试:宿主 64/64、客户端 52/52。
- 1.0.7 — 修复「删除会话必须重启才生效」。宿主在激活时包住 agentLoop.prepare(),按 Session id 捕获每个 live Agent 的工厂 teardown 句柄(与 ACP session/close 同一个 dispose);删除时先 workspace/session-stop,再 dispose()(取消回合 → 等 idle → 关闭写句柄/释放 lease → 从 ctx.agents/ctx.sessions detach → 触发 session/disposed),随后才 rm 日志目录并清理投影缓存。session/disposed 由 Session 控制器转成 api-session/removed,侧栏行立即消失,不再需要重启。投影缓存删除会等待 storage domain 写链并重试,避免 session/disposed 的异步 checkpoint 把文件写回来。只有句柄与控制器 effect 都不可达的活会话才保留排队兜底。测试:宿主 44/44、客户端 34/34。
- 1.0.6 — 支持删除已挂载会话:宿主侧在 $DSH_HOME/storages/session-delete-pending.json 维护待删队列——目标 live 时不 unlink(会静默丢数据且留下幽灵行),而是排队,并在插件 apply(下次启动、浏览器尚未挂载任何会话)时扫描删除、清空队列;客户端对话框新增「已安排删除 / 知道了」状态,并把 session-delete/not-found、session-delete/bad-request 映射成中文文案,不再回显宿主英文原文。测试:宿主 28/28、客户端 29/29。
- 1.0.5 — 两个观感问题的修复:
1. 菜单行没有选中效果:自绘行补上悬停/焦点态——背景用 --dsw-alias-interactive-bg-hover-danger(回退 --dsw-alias-interactive-bg-hover),键盘焦点加 --dsw-alias-border-l4 焦点环,并加了一枚自绘 14px 描边垃圾桶图标,与相邻的 pin/rename/fork/archive 行对齐。
2. 蒙板盖住整个界面:之前误用 --dsw-alias-bg-overlay——那是实色表面色 (做计数徽标背景用的),所以铺满全屏就成了不透明挡板。改用真正的弹窗蒙板 --dsw-alias-bg-mask-1(亮色 #0000003d / 暗色 #00000080)加 --dsw-mask-blur,并用随附弹窗同款写法 top: var(--dsh-frame-chrome-top, 0px) 让蒙板从窗口顶栏下方开始,不再压住标题栏。
- 1.0.4 — 文案接入 client locale:ctx.locale.register('sessionDelete', { zh, en }), slot 注册带 locale: NS,因此跟随 Harness 语言(之前用 navigator.language,在中文 UI 里判成了 en-US 而显示英文);确认框改为自绘浮层(shell.overlay + useSyncExternalStore 的待确认状态),不再使用 window.confirm/alert,样式用 --dsw-alias-* 主题变量。
新增 test-client.mjs。
- 1.0.3 — 修复「删除了但侧栏行不消失」:浏览器半侧删除成功后调用
ctx.sessions.refresh()(重拉 session.list,缺失的 summary 会被 mergeOrderedBaseline
丢弃),被删会话若正是当前主视图则先 uiWorkspace.clearMain();宿主半侧新增 workspaceRegistry 的 detachSession 清理。测试增至 24/24(含 detach 断言)。
- 1.0.2 — 把宿主侧通道从 ctx.connection.rpc.handle() 换成
ctx.connection.fetch.register()。前者在 0.2.0-rc.2 里对任何调用方都会抛
cannot get property "webServer" without inject(见上「为什么走 Fetch 路由」);后者是随附导出/上传路由同款机制,inject 回到 ['connection', 'sessions']。
浏览器半侧改为对 /api/dsh-session-delete/session 发 POST JSON。
- 1.0.1 — 尝试给 rpc.handle 补 webServer 注入(无效,原因见上)。
- 1.0.0 — 首个版本。

文件

| 文件 | 作用 |
| package.json | bundle 清单:dsh.bundle.patch + dsh.client(platform: web) |
| cordis.patch.yml | 插入一行宿主插件 session-delete |
| index.js | 宿主半侧:/api/dsh-session-delete/session Fetch 路由 + /session-delete 命令 + 活会话 teardown + 删除实现 |
| client.js | 浏览器半侧:单会话/分组菜单项、分组确认框、分组 Header hover 装饰、相对路径 fetch 调宿主 |
| locale/{en,zh}.json | 插件页展示元信息 |
| test-host.mjs | 宿主半侧离线冒烟测试(含活会话 dispose 顺序、分组路由) |
| test-client.mjs | 浏览器半侧结构测试(最小 React 替身) |

License

MIT © 2026 BigPizzaV3
预览分享卡片长什么样 ↓BigPizzaV3/dsh-session-delete
分享 · DeepSeek Harness Hub
BigPizzaV3/dsh-session-delete

DeepSeek Harness(dsh)的非官方删除会话插件:会话菜单项加应用内对话框,在已鉴权的 /api 通道上挂 Fetch 路由,挂载中的会话排队删除。附带离线 host/client 测试。

这是你的仓库?认领条目

回到顶部