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

会话目录隔离 sweet-boby/dsh-session-isolation

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

为每个会话分配独立工作目录,避免并行写冲突

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · chat
装得上吗
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 42 天前
档位由哪些信号合成

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

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

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 8 处,展示前 8 条)
  • 发起网络请求
    lib/client.js:46
    const response = await fetch(LIST_ROUTE, { headers: { accept: 'application/json' } })
  • 发起网络请求
    lib/client.js:53
    const response = await fetch(TOGGLE_ROUTE, {
  • 删除本地文件递归
    lib/patch.js:183
    await rm(cwd, { recursive: true, force: true }).catch(() => {})
  • 读取本地文件
    lib/isolate.js:37
    return (await stat(join(root, MARKER_NAME))).isFile()
  • 删除本地文件
    lib/isolate.js:65
    await rm(marker, { force: true })
  • 写入本地文件
    lib/isolate.js:68
    await mkdir(root, { recursive: true })
  • 写入本地文件
    lib/isolate.js:69
    await writeFile(marker, MARKER_TEXT, 'utf8')
  • 写入本地文件
    lib/isolate.js:112
    await mkdir(candidate)
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

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

功能亮点

  • 会话独立工作目录
  • 避免并行写冲突

DSH 插件,为每个会话单独设工作目录:让并行的智能体会话不再互相覆盖。

README

由 DeepSeek 最新模型翻译生成
dsh-session-isolation License: MIT tests: 25 passing DSH plugin DSH 的「每个会话一个独立工作目录」插件——即 Codex 那种体验,按项目选择开启,可以在 Web 界面里点开关,也可以在对话里让 agent 打开,或者直接放一个标记文件。 要解决的问题 DSH 会把所选工作区目录交给每个会话,于是同一项目里的两个会话写的是同一批文件。 三个 agent 跑在同一个目录上,后一个会把前一个刚写完的文件"顺手修掉"。 它做什么 某个目录开启隔离后,在那里新建的每个会话都在自己的 session- 子目录里工作。 这个子目录(而不是项目目录)成为该会话 workspace-write 沙箱的写入根,因此并行会话互相写不到对方的文件;而项目本身的文件对所有会话仍然可读。 project/ ← 你选择的工作区(每个会话都能读) ├── .dsh-isolate ← 开关(一个空文件;删掉即关闭隔离) ├── src/ … ← 项目自己的文件(对会话只读) ├── session-1a2b3c4d/ ← 会话 A 的沙箱根,只有它能写 └── session-9f8e7d6c/ ← 会话 B 的沙箱根,只有它能写 * 目录在会话创建之前就建好,名字取自会话 id 的前八个字符(极小概率重名时加 -2、-3)。
展开完整文档(README 剩余 1 节)
dsh-session-isolation

License: MIT
tests: 25 passing
DSH plugin

DSH 的「每个会话一个独立工作目录」插件——即 Codex 那种体验,按项目选择开启,可以在 Web 界面里点开关,也可以在对话里让 agent 打开,或者直接放一个标记文件。

要解决的问题

DSH 会把所选工作区目录交给每个会话,于是同一项目里的两个会话写的是同一批文件。
三个 agent 跑在同一个目录上,后一个会把前一个刚写完的文件"顺手修掉"。

它做什么

某个目录开启隔离后,在那里新建的每个会话都在自己的 session- 子目录里工作。
这个子目录(而不是项目目录)成为该会话 workspace-write 沙箱的写入根,因此并行会话互相写不到对方的文件;而项目本身的文件对所有会话仍然可读。

project/ ← 你选择的工作区(每个会话都能读) ├── .dsh-isolate ← 开关(一个空文件;删掉即关闭隔离) ├── src/ … ← 项目自己的文件(对会话只读) ├── session-1a2b3c4d/ ← 会话 A 的沙箱根,只有它能写 └── session-9f8e7d6c/ ← 会话 B 的沙箱根,只有它能写

* 目录在会话创建之前就建好,名字取自会话 id 的前八个字符(极小概率重名时加 -2、-3)。
* 会话在侧边栏里仍归属该项目;AGENTS.md 发现与项目技能查找照常工作——它们都从会话 cwd 向上走。
* 已存在的会话不会被搬动:隔离改的是「下一个会话在哪里工作」,不是正在跑的会话。
* 关掉开关后不再新建私有目录;此前创建的会话保留自己的目录,并继续归属于该项目。

没有改动 DSH 任何源码:插件走标准 Cordis 组合挂载,加载时包装两个接缝,卸载时复原。

安装

插件无需构建,除 DSH 宿主本身外没有运行依赖。仓库包含 Cordis 入口、六个 lib/ 模块、浏览器半边、bundle patch 和完整测试。已在 DSH 0.1.6-alpha.2 上验证,要求 Node.js 22+。

从 GitHub 安装

dsh plugin --profile add \
https://github.com/sweet-boby/dsh-session-isolation.git

安装后重启一次宿主。插件管理器会安装包、选中 bundle 并应用 cordis.patch.yml;重启是为了让浏览器模块表发现新的 dsh.client bundle。

从 Web 界面安装

打开 插件 → 添加插件,粘贴 GitHub 地址:

https://github.com/sweet-boby/dsh-session-isolation

如果当前 DSH 版本的安装器只接受本地 bundle 路径,就先克隆仓库,再粘贴本地目录的绝对路径。

从本地检出安装

git clone https://github.com/sweet-boby/dsh-session-isolation.git
dsh plugin --profile add \
/绝对路径/dsh-session-isolation

手工写入 profile

在 ~/.dsh/profiles//package.json 里加依赖并选中 bundle:

{
"dependencies": {
"dsh-session-isolation": "github:sweet-boby/dsh-session-isolation"
},
"dsh": {
"profile": {
"bundles": ["…", "dsh-session-isolation"]
}
}
}

本地开发时,把依赖改成 file:/绝对路径/dsh-session-isolation,然后在 profile 目录安装:

cd ~/.dsh/profiles/
pnpm install --ignore-scripts

无论用哪种方式安装,最后都要重启宿主。

运行要求

* Node.js 22 或更新版本。
* DSH 组合里需要有 sessionController、workspaceRegistry、tools 三个服务——所有 base 系 profile 都有。缺任何一个时插件保持 pending,而不是半加载状态。
* Web 服务(ctx.webServer)是可选依赖:没有它时插件保留策略与工具,只是不提供 GUI 页面。

开启隔离

隔离是目录的属性,持久形态就是目录里的 .dsh-isolate 标记文件——设置跟着文件夹走,用文件管理器也能改。

1. Web 界面:设置 → 内置插件 → 工作区隔离。每个工作区一行,显示路径、会话数和一个开关。
列表每五秒刷新一次,所以在别处做的改动也会同步过来。
2. 对话里:让 agent 打开隔离。它会调用 session_isolation 工具,动作有 status、list、 enable、disable,可选绝对路径 path(默认取当前会话的工作区)。
3. 宿主代码:await ctx.isolatedSessions.setIsolated(workspaceId, true) 或
setIsolatedPath(path, true);list() / isIsolated(id) 读取当前状态。
4. 手工:在项目目录里建一个空的 .dsh-isolate 文件。

怎么确认生效了

在该工作区里新开一个会话,问它的工作目录(pwd,或让它写一个文件)。答案会是一个 session- 子目录;项目根目录在它的文件策略里是只读位置。开两个这样的会话,会得到两个不同的目录。

GUI 页面

浏览器半边是手写的客户端 bundle(lib/client.js),通过 dsh.client 与
exports["./client"] 声明,因此 Web 客户端模块表会像对待打包插件一样提供它。它用
ctx.slots.inject 注册一个 settings.plugins.tab 条目,也就是先等 Settings 侧声明该 slot 再注册——插件激活顺序并不稳定,往未声明的 slot 里注册会让整个浏览器启动失败。

外部插件的浏览器半边无法声明 Remote 命名空间,所以两半通过 Web 服务上的两个具名路由通信:

| 路由 | 方法 | 请求体 | 响应 |
| /session-isolation/workspaces | GET | — | { workspaces: [{ workspaceId, title, path, isolates, sessionCount }], isolatedCount } |
| /session-isolation/toggle | POST | { workspaceId, enabled } | 刷新后的列表,或 { error } |

路由本身不持有状态——所有答案都是从标记文件现场投影出来的;它们和其他插件资源路由一样,是绑定在回环地址上的免认证路由。没有 Web 服务的宿主不会注册它们。

页面出现需要重启一次宿主。 客户端模块表在激活时扫描 dsh.client 声明,并按包名缓存「这不是客户端包」的判定,所以宿主启动之后才出现的 bundle 要等下次启动才会被拾取。
宿主侧改动可以通过配置重载生效,新的客户端 bundle 不行。在此之前,其他开关(工具、标记文件、宿主服务)都已经是可用的。

实现原理

两个接缝,加载时包装、卸载时复原;未接管的调用一律委托原实现;接缝若被上游挪动会显式报错(… this DSH build moved it),而不是静默地什么都不隔离。

1. ctx.sessionController.create——GUI 调用的 Remote 入口。DSH 解析新会话 cwd 的规则是 workspace.path ?? request.cwd ?? default,而控制器会拒绝同时携带 workspaceId 与 cwd 的请求,所以插件在这一次调用期间把目标工作区实体指向新分配的私有目录。持久记录不动,重定向在 finally 里移除,创建失败会删掉刚分配的目录。重定向期间实体的自身写入落在一个可变槽位里,因此本次调用刚记账的会话不会在移除重定向时被回滚。
2. 工作区注册表的会话路径索引——每个 WorkspaceEntity 实际读取的那个 host 对象(注册表只构造一份并共享)。位于隔离工作区内的会话目录会解析回该工作区根路径,于是原有的挂载校验、持久化成员裁剪、一次性历史 bootstrap、以及「一个会话只属于一个工作区」不变量全都继续成立,无需改动源码。

隔离状态本身不由插件持久化:每次都从标记文件重算,因此重启、外部编辑、其他工具最终都会收敛到同一个答案。扫描是串行的;若某次扫描落在"按调用重定向"进行期间,它会合并而不是回退一个当时看不见的决定。

限制与实话

* 项目根目录对会话不可写。 这正是隔离本身。如果某个会话必须改项目自己的文件,就别给那个项目开隔离,或者把共享材料放进会话目录。
* 它不是 git worktree 的替代品。 会话目录在仓库内部,git 能对上父仓库,但分支仍是共享的。
要做到每个 agent 一条分支需要 worktree,本插件不创建 worktree。正常的代码仓库建议保持关闭:开了之后 agent 改不到仓库本身的文件。
* 读权限不变。 隔离约束的是写入,与 DSH 自己的 workspace-write 语义一致;会话仍能读项目。
用户也可以为某一轮批准 danger-full-access 绕过边界——那是 DSH 的审批策略,不是本插件的行为。
* 卸载插件会让隔离过的会话变成未分组。 注册表的成员规则是"规范化 cwd 全等",没有插件时私有目录不再与项目匹配。重新启用插件即可恢复分组;无论哪种情况,会话日志与目录都不会被改动。
* 嵌套遵循最近的已标记祖先。 把一个工作区注册在隔离项目的路径本身上时,该路径以那个工作区为准;其内部的会话目录归属于最近的已标记祖先。
* 本地 file: 安装是拷贝。 pnpm 对 file: 依赖做拷贝而不是软链,所以改完插件要在下次启动宿主前重新 pnpm install(或删掉 node_modules/dsh-session-isolation 再装)。

常见问题

| 现象 | 原因 | 处理 |
| 设置里没有「工作区隔离」标签页 | 宿主启动时客户端 bundle 还不存在 | 重启一次宿主(见上文重启说明) |
| /session-isolation/workspaces 返回 404 | 插件没加载,或宿主没有 Web 服务 | 确认 bundle 已选中且已安装;查看宿主启动日志里 session-isolation fiber 是否失败 |
| 新会话仍在共用项目目录 | 标记不在该工作区自己的目录里,或会话早于标记 | 确认 .dsh-isolate 就在页面显示的工作区路径下;只有之后新建的会话才隔离 |
| 隔离过的会话显示为未分组 | 该宿主上插件没生效 | 重新启用插件;目录与日志都完好 |
| agent 写不了项目根目录的文件 | 设计如此 | 关掉该项目的隔离,或让会话写进自己的目录 |

卸载

1. 逐个项目关闭隔离(各自删掉 .dsh-isolate),也可以直接留着——没有插件时它们不起作用。
2. 从 profile 的 dsh.profile.bundles 与 dependencies 中移除 dsh-session-isolation,在 profile 目录执行 pnpm install --ignore-scripts。
3. 重启宿主。

卸载不会触碰任何会话目录与日志。

开发

node --test "tests/*.test.js"

| 测试文件 | 覆盖内容 |
| tests/isolation.test.js | 标记策略、目录分配、两个接缝包装、状态缓存、服务 API,以及用桩件驱动的 HTTP 路由 |
| tests/integration.test.js | 真实的 dsh-storage → dsh-storage-domain → dsh-workspace 栈加真实 dsh-tools:会话创建、并发会话、成员归属、同一介质上的重启、开关切换 |
| tests/tool.test.js | session_isolation 工具对外暴露的 JSON Schema |
| tests/client.test.js | 浏览器半边的模块表交接与 slot 声明等待 |

tests/integration.test.js 用绝对路径导入某个 DSH 检出里的构建产物(文件顶部的 CHECKOUT 常量),检出位置变化时改它即可。

目录结构

index.js Cordis 插件:接缝包装、服务、工具、可选 Web 路由 lib/isolate.js 标记策略与会话目录分配 lib/state.js 隔离状态缓存:标记扫描、重定向守卫、串行化 lib/patch.js 两个接缝包装 + ctx.isolatedSessions 服务 lib/tool.js session_isolation 模型工具 lib/web.js GUI 页面背后的两个 HTTP 路由 lib/client.js 浏览器半边(设置 → 内置插件 页面) cordis.patch.yml 插入插件行的 bundle patch

许可证

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

为每个会话分配独立工作目录,避免并行写冲突

这是你的仓库?认领条目

回到顶部