DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

TOP1Wu /

TOP1Wu/dsh-session-isolation

Verified

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

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@5354b726

dsh-session-isolation

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


这个插件是干什么用的

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

它要解决的问题

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

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

  1. 在同一个工作区里开了两个会话,分别做两个不相干的项目(下面叫 A 项目和 B 项目);

  2. 会话 A 建了一份"目录级"文档 README-文件索引.md,用来索引它自己那批产出;

  3. 会话 B 看到这个工作区,按"这个目录是我的项目"的假设去改这份索引,把它自己项目的内容也塞了进去;

  4. 结果一份文档里混着两个项目的内容。甚至出现了这样的标题:

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

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

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

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

装上之后是什么样

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

它不做什么

  • 它不改变会话的 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

—/ 5

No ratings yet

Verified DSH bundle

Commit 5354b7262368

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout