为 DSH 项目提供副工作目录:agent 保持主工作区为 cwd,同时对已配置的副目录获得同等读写/执行权限,可在会话头部与新会话页配置。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-multi-folder
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:AngelosZou/dsh-multi-folder
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
为 DeepSeek Harness 项目提供副工作目录——不离开主工作区,同时编辑源码库、测试库与文档库。
一个 DeepSeek Harness 插件 bundle,为一个 Project(工作区)提供一组副工作目录:
- Agent 的核心
cwd等属性始终指向主工作目录; - 在 Workspace Write 模式下,Agent 对配置的副工作目录拥有与主工作目录同等的读取、写入、编辑与命令执行权限——实现方式是重定向会话自身的沙箱策略根,因此每种模式语义都自然保持(
read-only依旧拒绝、workspace-write放行、danger-full-access放行); - 目录列表注入系统提示词,每次组装按会话求值;
- 配置变更通过不打断的消息队列通知 Agent——在下一次消息边界(用户发送或工具调用结束)送达,且仅在目录集合实际变化时发送;
- 会话开始前即可配置:会话创建页(新会话界面)提供「多工作目录」入口(英文界面显示 "Multi-folder"),通过无会话远程 API(
multiFolder/*端点)读写同一份 per-workspace 配置——无需 session id; - 不新增任何工具:改动全部位于框架级(工具流水线拦截)与 UI 级(会话级头部入口)。
环境要求
- Node.js >= 20
- 由
@deepseek-ai/dsh-base+@deepseek-ai/dsh-web-app组成的 DSH profile
安装
将本仓库链接进 DSH profile:
dsh plugin --profile web add dsh-multi-folder
然后重启 DSH 后端(宿主组合在进程启动时装载)并刷新浏览器页面(客户端 bundle 以 no-cache 提供)。
兼容性
请选择与你的 DeepSeek Harness 版本匹配的插件版本:
| DeepSeek Harness | 安装 |
|---|---|
| 0.1.1 及更早 | dsh-multi-folder@0.1.7 |
| 0.1.2-alpha 及更新 | 最新版 dsh-multi-folder |
使用
会话头部出现「多工作目录」按钮(英文界面显示 "Multi-folder");会话创建页的入口位于输入框上方——与 git 分支胶囊同一条 dock 带,左边缘对齐新会话界面的工作区/预设胶囊,点击后面板以锚定在该胶囊上的浮层展开。会话创建页始终只显示一个入口:插件注册三个候选座位并选用当前可用的最佳者(上游 conversation.hero.workspaceExtras chip > conversation.input.dock 行 > 两者皆未声明时的右下角浮动按钮)。打开面板即可:
| 操作 | 行为 |
|---|---|
| 添加目录 | 打开原生目录选择器 |
| 移除 / 刷新 | 立即生效 |
| 切换会话 | 面板自动切换为该会话的副工作目录 |
| 重新打开面板 | 使用会话级缓存,不产生冗余命令行 |
等价的用户斜杠命令:
/multi-folder list
/multi-folder add "D:\path\to\repo"
/multi-folder remove "D:\path\to\repo"
/multi-folder set "D:\a" "D:\b"
Agent 无需任何额外操作:read / glob / grep 随处可用;write / edit / pwsh / bash 在路径(或 workdir)落入副目录时自动拦截并以该目录为沙箱根执行。
权限模型
每条受沙箱约束的命令只拥有唯一一个可写根——即本次调用被换根到的那个目录(Windows ACL runner 为每个进程树只授予一个工作区写 SID)。由此:
- cwd 停留在主工作区的命令不能在副目录创建文件。
git -C <副目录> commit、脚本内cd <副目录>、git clone <url> <副目录>、按绝对路径写文件等都会以操作系统级Permission denied失败(例如fatal: Unable to create '.../.git/index.lock': Permission denied)。 - 对称地,被换根到副目录的命令在同一次调用中也不能写主工作区(或另一个副目录)。
- 创建文件的命令必须把
workdir设为它要写入的目录,且必须使用该目录的绝对路径——相对workdir只会相对主工作区解析;在命令内部切换进程目录(Set-Location/cd)也不会扩大可写根(写入会以操作系统级拒绝失败,Windows 错误码 5)。对 git 而言,请进入仓库目录执行(workdir指向该仓库),而不是从主工作区用git -C。该规则同样适用于run_in_background: true的后台任务。 - 读操作不受限制,无需
workdir。
当 shell 命令以这类拒绝失败且命令引用了已配置的副目录时,插件会在工具结果后附带一条简短的诊断提示,说明 workdir 的修正方式。后台任务的拒绝发生在工具调用返回之后,只出现在该任务的 job_output 输出里,那时不会再附带提示——请读取任务输出,并用绝对 workdir 重跑。
工作原理
- 拦截——监听
tools/execute环绕分派瀑布,对解析路径(或workdir)落在副目录内的write/edit/pwsh/bash调用短路,并以换根后的会话站立策略({ ...standingPolicy, workspaceRoot: secondaryDir })执行。模式本身不变,因此各种沙箱模式与主工作区的语义天然一致。匹配前先经fs.resolve+processPath规范化,..、符号链接与大小写差异均正确处理。 - 提示词注入——一个有序
systemPrompt段落,text provider 每次组装按会话求值,仅为配置了副目录的会话渲染。 - 通知——命令处理器仅在目录集合实际变化时置位 pending notice;
agent/pre-step(前置注入进入批次)与tools/post-execute(附加为additionalContexts)两个通道中先触发者消费——均使用框架原生的插件来源notice上下文。 - 配置与安全边界——per-workspace 配置存储于 Agent 沙箱之外的宿主自有目录(
<DSH_HOME>/storages/multi-folder/<workspace-key>.json)。对配置文件的任何直接write/edit都会收到显式拒绝——Agent 永远无法自我授予目录,配置权仅属于用户。详见 SECURITY.md。 - 无会话远程 API——经
ctx.typert.register注册multiFolder命名空间(手写src-json描述符),并以普通对象服务multiFolder提供;list/add/remove/set以工作区路径为键,与/multi-folder命令共享同一套校验核心,因此会话尚未建立时创建页也能直接配置。 - 客户端——手写维护的 factory bundle(
window.__ModuleLoader__.load),无需构建工具链;面板经两条通道驱动宿主:会话内走 Remote BFF(ctx.remote.commands.execute),无会话端点走共享/apiRPC 通道(ctx.connection.rpc.call)。
目录结构
| 路径 | 作用 |
|---|---|
cordis.patch.yml |
profile patch 层,插入 dsh-multi-folder 行 |
lib/index.js |
宿主插件:配置存储、工具流水线拦截、提示词注入、双通道通知、/multi-folder 命令、无会话 multiFolder/* 远程 API |
lib/client.js |
客户端插件(factory bundle):会话头部按钮 + 覆盖层面板 + 会话创建页入口(输入框上方的 dock 胶囊 / 上游 hero chip / 右下角兜底浮动按钮) |
test/ |
免 DSH 运行时的行为测试(见开发) |
docs/ |
设计与分析文档 |
开发
零构建步骤:宿主半边为纯 ESM,lib/client.js 为 DSH client-modules 格式的手写 factory bundle。测试直接用 Node 运行:
node test/smoke-host.mjs # 宿主 apply 冒烟 + 远程 API 行为
node test/intercept.mjs # 拦截 / 命令 / 通知行为
node test/smoke-client.mjs # 客户端 bundle 与面板流程(React shim)
修改 lib/client.js 前请先阅读 docs/design.md 中的 bundle 契约。
文档
- docs/design.md — 架构与安全模型(英文)
- docs/upstream-hero-slot.md — 上游
conversation.hero.workspaceExtras插槽改动(B1)与插件的对接方式(英文)
参与贡献
见 CONTRIBUTING.md。欢迎提交 issue 与 PR。
许可证
链接
同类插件
Tencent/WeKnora#dsh-weknora★ 31002
把 WeKnora 知识库接入 dsh 的四个只读工具:列出知识库、混合检索原文片段、按顺序还原单篇文档,以及直接取用 WeKnora 自己带引用的 RAG 或 ReAct agent 回答(含可续聊的 session id)。
superdesigndev/treg★ 3752
给 Agent 的工具目录:按「要做的事」检索约 2,600 个外部接口(SEO 与 SERP、外链、社交、人物与公司信息补全、广告库、抓取),查看参数与单次调用价格后直接调用,凭据由服务端注入。附带技能,MCP 行在未设置 TREG_TOKEN 前保持禁用。
TencentCloudBase/CloudBase-AI-Toolkit#dsh-plugin★ 1127
把腾讯云 CloudBase 后端接入 DeepSeek Harness——在对话里搭好并部署全栈应用,查询结果渲染为表格卡片(分页、排序、导出 CSV),部署后可预览真实域名,并提供 CloudBase MCP 工具集(`mcp__cloudbase__*`),登录走 device-code 流程。
gitroomhq/postiz-agent#dsh-postiz★ 498
通过 MCP 将 DeepSeek Harness 连接到 Postiz:列出已连接的社交媒体渠道、获取各平台发帖规则,并向 X、LinkedIn、Instagram、Facebook、Threads、TikTok、YouTube、Reddit、Bluesky、Mastodon、Discord、Slack、Telegram 等平台排期、存草稿或发布帖子;附带 postiz 工作流技能。
EthanYoQ/Invoice-Downloader#dsh-invoice-downloader★ 465
面向 DeepSeek Harness 的本地 IMAP 发票下载、OCR 识别、归档与 Excel 报销汇总。
anysearch-team/anysearch-dsh★ 432
基于 AnySearch 的实时网页与垂直搜索插件,为 DeepSeek Harness 提供搜索工具。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。