前言¶
用 DSH Web GUI 做智能体开发时,一个常见的别扭之处是工作区只有一个:代码在一个目录,数据集在另一个目录,参考资料又在第三处。想让 agent 跨这些目录工作,要么手动把文件搬进同一个工作区,要么干脆不让 agent 碰它们。
dsh-multi-root 针对的就是这个问题。下面介绍这个插件:它在侧边栏加一个 Roots(多根)面板,允许把任意数量的独立文件夹挂载为工作区根目录,再通过一组受控的 host 端工具,让 agent 在这些根之间 list / read / write / glob——思路接近 VS Code 的 multi-root workspace。
这是什么¶
dsh-multi-root 是 DeepSeek Harness(DSH)Web GUI 的多根工作区插件,由 luoyu-xingu 维护,当前版本 0.1.1,MIT 许可证。
它以 cordis profile bundle 的形式激活在 web profile 中,热插拔,不需要修改 DSH 源码——这也符合 DSH「一切皆插件」的设计。几条基本约定先交代清楚:
1、所有根平等,没有主工作区之分;根集合由所有会话与 agent 共享。
2、GUI 与 agent 共享同一份根目录存储。
3、UI 文案双语(zh / en),跟随文档语言。
核心功能¶
根目录管理¶
- 侧边栏
Roots(多根)入口,点击后中央栏切换为管理面板。 - 挂载任意数量的文件夹:可以直接输入路径,也可以用 host 目录浏览器选择(Windows 从盘符级开始,Linux/macOS 从 home 目录开始),每个根可配一个可选的显示别名。
- 支持重命名、移除、排序根目录;每一行显示实时目录状态(
available/directory missing)。 - 根目录持久化在
~/.dsh/dsh-multi-root.json:所在目录权限 0700,文件权限 0600,原子写入。
注册给 agent 的工具¶
插件向 DSH 工具管线注册五个工具,全部限定在已注册的根内操作:
| 工具 | 作用 |
|---|---|
workspace_roots |
列出所有已挂载的根(id、name、path、status) |
workspace_root_list |
列出某个根内的一个目录 |
workspace_root_read |
读取根内的文本文件,256 KB 上限并报告截断 |
workspace_root_write |
写入或覆盖根内的文本文件,自动创建父目录 |
workspace_root_glob |
在根内做 glob 匹配,结果封顶 |
面向 agent 的通告与配置¶
插件会在系统提示词中加一段内容,向每个 agent 通告自身及上述工具;不想通告可以关掉。host 端配置经 schemastery 校验,共三项:
multi-root:
enabled: true # 路由、工具、提示词段落的总开关
announceToAgent: true # 系统提示词通告开关
hotReload: true # host 半部监听自身 lib/,重建后重挂载
安装与启用¶
推荐从 npm 安装,任意平台可用:
# 1. 把插件装入 web profile
dsh plugin --profile web add @luoyu_xingu/dsh-multi-root
# 2. 启动 Web GUI(Ctrl+C 停止,--port 可改默认端口)
dsh web
打开 dsh web 打印的地址,默认是 http://127.0.0.1:3080。侧边栏出现 Roots(多根)入口即说明生效,也可以用下面的命令确认安装:
dsh plugin --profile web ls @luoyu_xingu/dsh-multi-root
升级和移除:
dsh plugin --profile web update @luoyu_xingu/dsh-multi-root
dsh web # 升级后重启
dsh plugin --profile web remove @luoyu_xingu/dsh-multi-root
如果想从源码安装:
git clone https://github.com/luoyu-xingu/dsh-multi-root.git
cd dsh-multi-root
pnpm install
pnpm build
# file: 方式装入 checkout 的绝对路径,profile 内保存自包含副本
dsh plugin --profile web add file:<checkout 绝对路径>
# Windows 示例:
dsh plugin --profile web add file:E:/dsh_plugins/dsh-multi-root
改了代码重新构建后,先把新的 lib/ 同步进 profile 里的自包含副本,再重启:
pnpm build
# PowerShell:
Copy-Item lib\* $env:USERPROFILE\.dsh\profiles\web\node_modules\@luoyu_xingu\dsh-multi-root\lib\ -Recurse -Force
# bash:
cp -r lib/* ~/.dsh/profiles/web/node_modules/@luoyu_xingu/dsh-multi-root/lib/
dsh web # 重启
有一点务必注意:安装或每次重建后都要重启 dsh web。web profile 禁用了 cordis HMR,文件变更不会热加载;host 还会校验 bundle revision 与启动文件哈希,旧进程对旧 revision 一律返回 404(bundle script ... failed to load)。
典型用法¶
经过上面的步骤,日常使用只有三步:
1、点击侧边栏 Roots 入口。
2、用路径输入或 Browse 对话框挂载文件夹(Windows 先选盘符),按需给每个根起别名。
3、直接让 agent 跨文件夹干活——agent 会先用 workspace_roots 发现根,再用其他 workspace_root_* 工具在其中操作。
如果你要参与开发,仓库提供了三条命令:
pnpm typecheck # tsc -b + 测试 tsconfig 的类型检查
pnpm test # vitest run
pnpm build # 声明文件 + lib/(node 半部与 client bundle)
安全模型¶
这个插件刻意绕过了 DSH 的文件沙箱:所有操作以 host 进程权限运行,信任边界就是根集合本身。具体约束如下:
- 根只能由用户在 GUI 中挂载,agent 永远不能挂载或移除根。
- 路径防逃逸:所有路径相对根拼接、经
fs.realpath规范化,且必须落在注册根之内;..、绝对路径、盘符以及 symlink 逃逸在读写时均被拒绝,写入时还会额外校验解析后的父目录;glob 不跟随符号链接。 - 输出限额:读取 256 KB、写入 5 MB、列目录 500 条、glob 结果 1000 条,保证模型拿到的内容有界。
- 所有
/api/dsh-multi-root/*路由仅限 loopback 并带浏览器同源标记,LAN 暴露的部署访问不到这些路由。 - 存储文件不含机密,但仍以 0600 权限原子写入。
- 已知限制:工具以 host 用户权限运行并占用真实磁盘;覆盖已存在的文件前,agent 需先与用户确认;目录浏览器会列出 host 目录(按设计仅限 loopback,它是选择器的数据来源)。
适用场景与注意事项¶
适合的场景很直接:文件本来就分散在多个目录,不想为了 agent 把它们搬进单一工作区,又希望 agent 能在明确划定的范围里读写。
使用前有两件事要清楚:
1、插件以当前 dsh 进程的权限运行,相当于给 agent 打开了这些根目录下真实的磁盘读写通道。挂载哪些根、挂载多大范围,是你要做的信任决策。
2、安装前建议检查源码与许可证。仓库以 MIT 发布,代码在 GitHub 上公开;运行环境要求 Node ^22.19.0 || >=24.0.0,peer 依赖为 @deepseek-ai/dsh-* ^0.1.0-rc.6 与 react/react-dom ^18.2.0,另依赖 fast-glob ^3.3.3。
小结¶
dsh-multi-root 用一个插件补上了 DSH Web GUI 在多工作区上的缺口:挂载与管理在侧边栏完成,agent 侧通过五个 workspace_root_* 工具受控访问,路径校验、输出限额、路由限制都在插件内部闭环,全程不需要改 DSH 源码。
- GitHub:https://github.com/luoyu-xingu/dsh-multi-root
- 社区目录页:https://www.skillhub.cn/plugins/luoyu-xingu/dsh-multi-root
需要说明的是,社区目录为独立站点,与 DeepSeek、幻方无官方从属关系。