dsh-multi-root:给 DSH Web GUI 挂载 VS Code 式多根工作区

前言

用 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、幻方无官方从属关系。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜