前言¶
DeepSeek Harness(DSH)里,每个会话在对话层是隔离的:各自有事件日志、agent 和上下文窗口。但多个会话往往共用同一个工作目录。在同一工作区并行开两个会话做不同事情时,agent 会按「这个目录就是我的项目」去写文件——改同一份索引、写同一路径,后写的整文件覆盖先写的,并不是会话隔离失效,而是多个写入方共享了同一批文件。
下面介绍社区插件 dsh-session-isolation(维护者 TOP1Wu,分类:工作流)。它为同一工作区里的每个会话划定写入边界:各自产出进独立目录,并在工具层拒绝覆盖仍由其他存活会话占用的文件。
这是什么¶
一句话:给同一工作区里的每个会话划一条写入边界。
- 仓库:TOP1Wu/dsh-session-isolation
- 社区目录:skillhub.cn 插件页
- 许可证:MIT(README)
- 版本:package.json 中为 0.1.0
DSH 生态里插件通过官方接缝扩展能力;社区目录是独立站点,与 DeepSeek / 幻方无官方从属关系。安装前建议自行查看源码与许可证——插件以当前 dsh 进程权限运行。
要解决的问题与装上之后的行为¶
典型冲突¶
README 描述的场景包括:会话 A 建目录级文档做索引,会话 B 在同一工作区把 B 项目内容写进同一份索引;并行时两路写同一路径,后者覆盖前者。
装上之后¶
- 每个会话(及其派生子代理)自动对应产出目录:
<工作区>/.sessions/<会话短id>/ - 会话第一步会收到说明:工作区路径、本会话产出目录、写入边界(新文件写自己目录、不动别人文件、目录级索引默认不碰等)
- 当会话试图覆盖同一工作区里另一个仍存活会话已占用的文件时,
write/edit等文件工具在落地前被拒绝,并提示改写到自己的产出目录 - 归属会话结束或应用重启后自动放行,不会永久锁死文件
明确不做的能力¶
- 不改变会话 cwd,是「约定 + 拒绝」式隔离,不是把进程 chroot 到子目录
- 不拦截 bash 里的
>、tee、python -c "open(...,'w')"等写文件方式 - 若要物理级隔离,仍应「一个话题一个工作区」或使用 git worktree
核心机制¶
插件只依赖 DSH 扩展接缝,无第三方依赖,仅用 Node 内置 node: 模块。
机制 1:产出目录约定(agent/pre-step)¶
每个会话在第一步注入一次说明,包含工作区目录、本会话产出目录绝对路径,以及四条写入边界。子代理与父会话按血缘算作同一归属,可互相改产出;用户手动 fork 的会话是独立顶层归属。
机制 2:跨会话写入守卫(ctx.tools.guard)¶
在 write、edit、str_replace_editor、apply_patch 落地前检查目标路径:若文件已被同工作区另一存活顶层会话占用则拒绝;归属在 tools/result 里按「文件确实写到磁盘」记账,失败或被拒绝的调用不产生归属。
安装与启用¶
命令行 profile¶
插件为零第三方依赖,无需构建、无需联网。安装命令(README 原文):
dsh plugin --profile web add /绝对路径/dsh-session-isolation
装完后重启 DSH(CLI 安装不会热加载)。
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 --profile web --dump-config | grep -A2 session-isolation
应能看到类似:
# == dsh-session-isolation
- id: session-isolation
name: dsh-session-isolation
验证是否生效¶
重启后,在工作区开会话并让 agent 写文件,然后:
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 可在不卸载的情况下软化或关闭行为。
适用场景与注意¶
适合: 在同一工作区开多个并行会话、分别推进不同子任务,又暂时不想拆多个 clone 或 worktree 时,用约定 + 工具守卫降低互相覆盖的风险。
务必知晓的边界:
- 只拦文件类工具,不拦 bash 写文件;可靠解析 shell 困难,该路径仅靠机制 1 的约定
- 归属记录在进程内内存,DSH 重启后清空;已存在文件变为「无主」,谁先写入谁取得归属
- 不做物理隔离;强依赖 shell 或外部脚本大量写盘时,隔离不完整
- 仅顶层会话之间互斥;子代理并入父会话归属
维护者提供的离线测试:
node test/logic.test.mjs
README 称共 21 项测试,覆盖争用拦截、血缘归属、跨工作区不受影响、会话离线后放行等。
卸载¶
dsh plugin --profile web remove dsh-session-isolation
结尾¶
dsh-session-isolation 在 DSH「一切皆插件」的思路下,用 pre-step 约定和 tools guard 解决「多会话共享工作目录」带来的覆盖与混写问题。它不能替代「一话题一工作区」的硬隔离,但在工作流分类里,对同一目录多会话并行是可直接落地的折中。
- 目录页:https://www.skillhub.cn/plugins/TOP1Wu/dsh-session-isolation
- GitHub:https://github.com/TOP1Wu/dsh-session-isolation