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

会话写入隔离 TOP1Wu/dsh-session-isolation

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

为每个会话划定独立产出目录,防止互相覆盖文件

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/09/27·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 42 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件
查看扫描证据(共 2 处,展示前 2 条)
  • 写入本地文件
    lib/index.js:248
    mkdirSync(outputDir, { recursive: true })
  • 读取本地文件
    lib/index.js:309
    if (!existsSync(absolutePath)) return
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 会话独立产出目录
  • 防止跨会话文件覆盖

为 DeepSeek Harness 提供工作区级会话隔离:同一工作区里多个会话各自写自己的产出目录,拒绝覆盖其他会话的文件。

README

由 DeepSeek 最新模型翻译生成
dsh-session-isolation DeepSeek Harness 插件:让同一个工作区里的多个会话互不覆盖对方的产出。 这个插件是干什么用的 一句话:给同一个工作区里的每个会话划一条写入边界。 它要解决的问题 DeepSeek Harness 的会话,在“对话”这一层本来就是隔离的——每个会话有自己独立的事件日志、独立的 agent、独立的上下文窗口。唯一被共享的东西是工作目录。 于是在同一个工作区里开多个会话时,会出这种事(下面是一个真实案例): 1. 在同一个工作区里开了两个会话,分别做两个不相干的项目(下面叫 A 项目和 B 项目); 2. 会话 A 建了一份“目录级”文档 README-文件索引.md,用来索引它自己那批产出; 3. 会话 B 看到这个工作区,按“这个目录是我的项目”的假设去改这份索引,把它自己项目的内容也塞了进去; 4. 结果一份文档里混着两个项目的内容。甚至出现了这样的标题: 五之三、B 项目(独立于 A 项目) —— 一边声明“独立于 A 项目”,一边被写进同一个索引。 并行跑的时候更直接:两个会话写同一个路径,后写的把先写的整文件覆盖。 这不是“会话隔离坏了”,而是多个写入方共享了同一批文件。
展开完整文档(README 剩余 1 节)
dsh-session-isolation

DeepSeek Harness 插件:让同一个工作区里的多个会话互不覆盖对方的产出。

这个插件是干什么用的

一句话:给同一个工作区里的每个会话划一条写入边界。

它要解决的问题

DeepSeek Harness 的会话,在“对话”这一层本来就是隔离的——每个会话有自己独立的事件日志、独立的 agent、独立的上下文窗口。唯一被共享的东西是工作目录。

于是在同一个工作区里开多个会话时,会出这种事(下面是一个真实案例):

1. 在同一个工作区里开了两个会话,分别做两个不相干的项目(下面叫 A 项目和 B 项目);
2. 会话 A 建了一份“目录级”文档 README-文件索引.md,用来索引它自己那批产出;
3. 会话 B 看到这个工作区,按“这个目录是我的项目”的假设去改这份索引,把它自己项目的内容也塞了进去;
4. 结果一份文档里混着两个项目的内容。甚至出现了这样的标题:

五之三、B 项目(独立于 A 项目)

—— 一边声明“独立于 A 项目”,一边被写进同一个索引。

并行跑的时候更直接:两个会话写同一个路径,后写的把先写的整文件覆盖。

这不是“会话隔离坏了”,而是多个写入方共享了同一批文件。

装上之后是什么样

- 每个会话(以及它派生的子代理)自动获得自己的产出目录: /.sessions//
- 会话的第一步会收到一条说明,告诉它产出目录在哪、哪些东西不能碰;
- 当一个会话想覆盖另一个仍然存活的会话的文件时,写入被拒绝,并被告知改写到自己的产出目录;
- 归属会话结束、或应用重启之后自动放行,不会永久锁死文件。

它不做什么

- 它不改变会话的 cwd。会话的工作目录仍然由 DSH 创建时决定,所以这是“约定 + 拒绝”式的隔离,不是物理隔离;
- 它不拦 bash。bash 里的 >、tee、python -c "open(...,'w')" 写文件不会被守卫拦住(详见“已知边界”);
- 要做到物理隔离,仍然是“一个话题一个工作区”或 git worktree。

怎么工作

两条机制,都挂在 DSH 自己的扩展接缝上,没有一行 hack:

机制 1 · 产出目录约定(挂 agent/pre-step)

每个会话在第一步收到一条注入说明,内容是:

- 本工作区目录;
- 本会话的产出目录绝对路径;
- 四条写入边界(新文件写自己的目录 / 不动别人的文件 / 目录级索引文件默认不碰 / 拿不准就问用户)。

每个会话只注入一次。

机制 2 · 跨会话写入守卫(挂 ctx.tools.guard)

write / edit / str_replace_editor / apply_patch 在落地之前检查目标路径:

- 如果这个文件已被同一工作区里另一个仍然存活的会话占用 → 直接拒绝,并给出替代路径;
- 归属在 tools/result 里按“文件确实落到磁盘上”记账,失败或被拒绝的调用不会产生归属。

归属按血缘计算(关键设计)

- 子代理(header.origin === 'subagent')沿 parentSession 上溯到顶层会话,所以整棵委派树算同一个归属:父会话和它的子代理可以自由互相修改产出;
- 两个无关的顶层会话之间才互相隔离;
- 用户手动 fork 出来的会话不是子代理,因此是独立归属。

归属只在该顶层会话存活期间生效。会话结束或应用重启后自动放行——避免“文件被永久锁死”这种反向麻烦。

安装

命令行 profile

dsh plugin --profile web add /绝对路径/dsh-session-isolation

本插件零第三方依赖,只用 node: 内置模块,所以不需要构建步骤、也不需要联网。

DSH Desktop

⚠️ 桌面版真正的 DSH_HOME 是

~/Library/Application Support/dsh-desktop/harness

不是 ~/.dsh。 直接在终端跑 dsh plugin 会装进 ~/.dsh,对桌面版不生效。
要么用桌面版内置的插件市场安装,要么显式指定 home:

DSH_HOME="$HOME/Library/Application Support/dsh-desktop/harness" \
dsh plugin --profile web add /绝对路径/dsh-session-isolation

装完重启 DSH(CLI 安装不会热加载)。

验证装上了

dsh --profile web --dump-config | grep -A2 session-isolation

应能看到:

== dsh-session-isolation
- id: session-isolation
name: dsh-session-isolation

验证真的生效

重启后,在任意工作区开一个会话并让它做事,然后:

ls "/.sessions"

应该出现以会话短 id 命名的目录(短 id 就是 $DSH_SESSION_ID 去掉 session- 前缀后的第一段)。

配置

全部通过环境变量:

| 变量 | 默认 | 作用 |
| DSH_SESSION_ISOLATION | guard | guard = 约定 + 守卫;advise = 只注入约定、不拒绝;off = 完全关闭 |
| DSH_SESSION_ISOLATION_DIR | .sessions | 产出目录名 |
| DSH_SESSION_ISOLATION_MKDIR | 1 | 设 0 则不主动创建产出目录,只告知路径 |

用 advise 或 off 可以随时把插件软化/静默掉,不用卸载。

已知边界(重要)

1. 只拦文件工具,不拦 bash。
bash 里的 > / tee / python -c "open(...,'w')" 这类写文件不会被守卫拦下——可靠地解析 shell 命令很困难,硬拦会误伤正常命令。这条路径只由机制 1 的约定覆盖,没有强制。
2. 归属记录是进程内内存,DSH 重启后清空。
重启后已存在的文件重新变成“无主”,第一个写入它的会话会取得归属。

3. 不做物理隔离。 见上文“它不做什么”。

4. 只对顶层会话之间生效。 子代理按血缘并入其父会话,不独立成归属。

测试

node test/logic.test.mjs

21 项离线测试,用一个最小 fake ctx 复现 ctx.agents.get / ctx.tools.guard / ctx.on 三个接缝,覆盖:

- 两个会话争同一文件的拦截
- 归属会话自身放行
- 血缘归属(父会话的子代理放行 / 别的会话的子代理照样拦)
- 其他工作区不受影响
- 归属会话离线后放行
- 只读工具与非文件工具放行
- edit / str_replace_editor 同样受守卫
- pre-step 只注入一次,reject 决策不被污染

卸载

dsh plugin --profile web remove dsh-session-isolation

实现要点(给维护者)

| 依赖的 DSH 接缝 | 参考位置 |
| ctx.on('agent/pre-step', handler, { prepend: true }) | packages/context/time-context/src/index.ts |
| ctx.tools.guard(fn),返回字符串即拒绝 | packages/core/tools/src/index.ts |
| ctx.on('tools/result', (exec) => …) | packages/context/agent-instructions/src/index.ts |
| agent.session.header 的 cwd / id / origin / parentSession | packages/core/session/src/types.ts |
| 子代理写 parentSession | packages/subagent/subagent/src/child-agent.ts |
| 消息来源 { kind: 'plugin', form: 'snapshot', sections: [...] } | packages/llm/llm/src/message.ts |

本插件刻意不 import 任何 @deepseek-ai/* 包:以本地路径安装时 peer 依赖不一定解析得到,而运行期的消息 id 只是普通字符串(brand 只存在于类型层),所以手工构造消息与工厂函数等价。

License

MIT
预览分享卡片长什么样 ↓TOP1Wu/dsh-session-isolation
分享 · DeepSeek Harness Hub
TOP1Wu/dsh-session-isolation

为每个会话划定独立产出目录,防止互相覆盖文件

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部