在 DeepSeek Harness 宿主内部提供本机回环 MCP 端点,让另一个智能体如 Codex把任务派给…
31.5/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Dogtiti/dsh-plugin-subagent-bridge该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · tool
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 4 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0🔴 扫描:高危尚无人工评估
静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。
命令参数由运行时变量拼接读写/删除本地文件
查看扫描证据(共 14 处,展示前 13 条)
- 读取本地文件index.js:28
return JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version ?? '0.0.0' - 执行外部命令表达式求值index.js:654
async spawn({ taskName, message, forkTurns, from, cwd, model, reasoningEffort, workspace }) { - 写入本地文件index.js:1189
await mkdir(cwd, { recursive: true }).catch(() => {}) - 读取本地文件index.js:1215
parsed = JSON.parse(await readFile(settings.workersFile, 'utf8')) - 写入本地文件index.js:1261
await mkdir(dirname(settings.workersFile), { recursive: true, mode: 0o700 }) - 写入本地文件index.js:1262
await writeFile(settings.workersFile, `${JSON.stringify(payload, null, 2)}\n`, { mode: 0o600 }) - 删除本地文件递归index.js:1567
await rm(temp, { recursive: true, force: true }).catch(() => {}) - 读取本地文件index.js:1611
return existsSync(expanded) ? expanded : undefined - 读取本地文件index.js:1614
if (directory !== '' && existsSync(join(directory, 'codex'))) return 'codex' - 读取本地文件index.js:1618
if (existsSync(expanded)) return expanded - 读取本地文件index.js:1630
return await readFile(path, 'utf8') - 写入本地文件index.js:1718
await mkdir(dirname(endpointFile), { recursive: true, mode: 0o700 }) - 写入本地文件index.js:1719
await writeFile(endpointFile, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 })
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
Codex 与 DeepSeek Harness 之间的子代理式桥接:Codex 通过回环 MCP 端点启动 DSH 工作进程并取回最终答案,DSH 智能体也能反向派发给 Codex。
README
由 DeepSeek 最新模型翻译生成dsh-plugin-subagent-bridge
M8ven Score
在 DeepSeek Harness 宿主内部提供本机回环 MCP 端点,让另一个智能体(如 Codex)把任务派给 DSH 会话并取回结果。
插件运行在宿主进程内,直接使用公开的 sessionController 服务 —— 不需要读取 ~/.dsh/.credentials.yaml,也不需要伪造 cookie。
指定模型
dsh_task、dsh_spawn、dsh_followup 都可以带 model,让 worker 跑在指定模型上:
dsh_task({ prompt: "…", model: "zai-coding-cn/glm-5.3", reasoningEffort: "max" })
dsh_spawn({ task_name: "review", message: "…", model: "opencode-go/deepseek-v4.1-flash" })
dsh_followup({ worker: "review", message: "…
展开完整文档(README 剩余 1 节)
dsh-plugin-subagent-bridge
M8ven Score
在 DeepSeek Harness 宿主内部提供本机回环 MCP 端点,让另一个智能体(如 Codex)把任务派给 DSH 会话并取回结果。
插件运行在宿主进程内,直接使用公开的 sessionController 服务 —— 不需要读取 ~/.dsh/.credentials.yaml,也不需要伪造 cookie。
指定模型
dsh_task、dsh_spawn、dsh_followup 都可以带 model,让 worker 跑在指定模型上:
dsh_task({ prompt: "…", model: "zai-coding-cn/glm-5.3", reasoningEffort: "max" })
dsh_spawn({ task_name: "review", message: "…", model: "opencode-go/deepseek-v4.1-flash" })
dsh_followup({ worker: "review", message: "…", model: "deepseek-account/deepseek-flash" })
- 写法是 provider/model;只写模型名时沿用当前默认 provider(model: "glm-5.3");
- reasoningEffort 可选,取值随模型(low / medium / high / max 等);
- 不传 model 就完全不动会话,行为和以前一致;
- 实测(Host 侧 sessionController.selectModel):请求头里的 provider/model 确实变成指定的那组,且不会改写 profile 的默认模型。
实现上就是在建好会话、发第一个 prompt 之前调一次 selectModel,所以 worker 的第一轮就已经在新模型上跑。
工具
| 工具 | 作用 |
| dsh_task | 同步派活:开会话、投递、阻塞到这一轮结束,只返回最终回答(最后一条 assistant 消息) |
| dsh_spawn | 异步派活:立刻返回 task_name + sessionId,可同时开多个 worker 并行跑 |
| dsh_followup | 给已有 worker 再派一轮(复用它的上下文) |
| dsh_close | 关闭 worker,释放并发名额(不删除会话) |
| dsh_list_workers | 列出本桥开的 worker 及其实时状态 |
| dsh_wait | 一次等多批 worker:targets + timeoutMs,任一到达终态即返回 {completed} / {errored} / "running" / "not_found" |
| dsh_dispatch | 向指定会话投递一条用户消息并开始一轮;返回 requestId 与 seqAtDispatch |
| dsh_read_result | 长轮询读进度:返回该会话在 seqAtDispatch 之后的全部助手文本(用于看过程;要结果用 dsh_wait) |
| dsh_list_sessions | 列出会话元数据(id、标题、工作目录、是否运行、最后活动时间) |
反向:DSH → Codex
插件同时给本部署的 Agent 注册了一个工具:
| 工具 | 参数 | 返回 |
| codex_dispatch | prompt(必填)、cwd、resume(线程 id)、sandbox | { ok, text, threadId, exitCode, durationMs, error? } |
它执行 codex exec [resume <id>] --json -o <临时文件>,从事件流取 thread.started、从 -o 文件取最终消息;工具结果里会带 [codex thread <id> · 12s],把那个 id 传给 resume 就能继续同一个 Codex 线程(实测能记住上一轮的回复)。
注意:resume 时 sandbox 与 cwd 不生效 —— codex exec resume 子命令本身不接受 -s / -C,线程沿用它原来的设置。
边界(v0 硬约束):
- dsh_list_sessions 只返回元数据,不含任何消息内容。
- dsh_read_result 只对本桥派发过的会话生效;从未派发过的会话一律拒绝。
安装
本地目录安装
git clone https://github.com/Dogtiti/dsh-plugin-subagent-bridge
Plugins → 添加 → 选该目录。
启动后插件在 127.0.0.1:47821 监听,并写入端点文件(权限 0700/0600):
{
"url": "http://127.0.0.1:47821/mcp/<token>",
"port": 47821,
"token": "<token>",
"pid": 12345,
"startedAt": "2026-10-22T12:30:00.000Z"
}
路径:~/.dsh/bridge/endpoint.json
接到 Codex
codex mcp add dsh-bridge --url "$(node -p "require(process.env.HOME+'/.dsh/bridge/endpoint.json').url")"
验证:
codex mcp list
codex mcp get dsh-bridge
Codex 桌面 App 与命令行共用 ~/.codex/config.toml,所以两端都能看到这条。
token 放在 URL 路径里(能力 URL),因此不需要在 Codex 侧配置环境变量 —— 桌面 App 从 Finder 启动时拿不到自定义环境变量。若你更想用 bearer,也可以 --bearer-token-env-var 指向环境变量,插件同时支持 Authorization: Bearer <token>。
移除:
codex mcp remove dsh-bridge
配置
- insert:
- id: subagent-bridge
name: 'dsh-plugin-subagent-bridge'
config:
port: 47821
| 键 | 默认 | 说明 |
| enabled | true | 总开关;关闭后不监听、不写端点文件 |
| port | 47821 | 回环监听端口;固定端口是为了让 Codex 侧那条 URL 在重启后依然有效 |
| endpointFile | ~/.dsh/bridge/endpoint.json | 端点与令牌的落盘位置 |
| maxResultChars | 20000 | 单次 dsh_read_result 返回的最大字符数(超出保留尾部) |
| taskTimeoutSeconds | 300 | dsh_task 等待一轮结束的默认上限(客户端可用 timeoutSeconds 覆盖,最大 600) |
| workersFile | ~/.dsh/bridge/workers.json | worker 注册表与重基线的落盘位置(0600) |
| maxHops | 1 | 跨工具委派层数上限(1 = 只允许一层,和 Codex / DSH 的默认 maxDepth: 1 一致) |
| dispatchPerMinute | 10 | 滚动窗口内允许的派发次数(spawn / task / dispatch / followup / codex_dispatch 合计) |
| dispatchWindowMs | 60000 | 上述窗口长度 |
| maxWorkersPerRoot | 4 | 每个工作目录的 worker 上限(cwd 自动分桶,调用方不需要传 owner) |
| maxWorkers | 12 | 全局兜底上限,防止多个项目一起把机器压满 |
| workerTtlMs | 86400000 | 记录超过这个时间没更新就不再占名额(过期自动释放,无需手动清理) |
| waitTimeoutMs | 240000 | dsh_wait 的默认超时(1s ~ 240s,客户端可用 timeoutMs 覆盖) |
| readWaitSeconds | 25 | dsh_read_result 的默认长轮询时长(上限 55,客户端可用 waitSeconds 覆盖) |
| codexBin | codex | Codex 可执行文件;含 / 时按路径严格解析,找不到就报错而不回退 |
| codexSandbox | workspace-write | codex_dispatch 的默认 sandbox(resume 时无效) |
| codexTimeoutMs | 300000 | 单次 codex_dispatch 超时,超时先 SIGTERM 再 SIGKILL |
端口被占用时插件不会静默换端口:端点文件里会写入 error 字段,并在宿主日志打印 subagent-bridge: could not start on port …。
防环护栏
两个智能体都接了同一个桥时,存在真实的环路:DSH worker → codex_dispatch → 那次 Codex 运行也能看到 dsh-bridge → 又 dsh_spawn → …。两边各自进程内的深度规则都管不到这条链(Codex 的 agent_max_depth 只数自己的 spawn_agent,DSH 的 maxDepth 只看 delegationDepth,而桥建的 worker 是顶层会话,深度恒为 0)。
所以桥自带两道:
① 深度(maxHops,默认 1)
- 每次都计算这次派发会产生的深度:max(当前在飞的链路深度, 调用方深度) + 1;
- 调用方是桥建的 worker 时按其深度 1 起算;
- codex_dispatch 运行期间会把链路标记为"在飞",嵌套回来的调用继承该深度;
- 超限直接报错,措辞可执行: codex_dispatch would create delegation depth 2, but maxHops is 1. Carry the work out directly instead of delegating again.
默认 1 的含义:Codex 可以派给 DSH,但 DSH 不能再用桥派回去 —— 与两个产品各自的 maxDepth: 1 语义对齐。
② 速率(dispatchPerMinute,默认 10 / 60s)
拦截广度型失控(一次开很多 worker)和客户端紧循环重试,与提示词无关,是纯兜底:
rate limit: 10 dispatches per 60s reached; retry in 23s
名额怎么算
worker 名额按工作目录分桶,调用方不用传任何 owner:
- 每个 cwd 默认 4 个(maxWorkersPerRoot);
- 全局默认 12 个(maxWorkers),跨项目兜底;
- 完成但没 dsh_close 的仍占名额(与 Codex 一致);
- 记录 24 小时没更新就自动不再占名额(workerTtlMs),不需要手动清理;
- 阻塞式 dsh_task 不计入名额,只登记。
为什么不是「每个会话 4 个」:MCP 端点是共享的,请求里没有会话或线程身份(Codex 的 CODEX_THREAD_ID 只存在于 shell 环境)。cwd 是唯一由调用方稳定提供、且语义上对应「一个项目」的维度。
跨重启
worker 注册表(task_name / sessionId / 终态结果)和每轮的时间基线都落在 ~/.dsh/bridge/workers.json:
- 派发、完成、关闭都会更新它;
- 重启后 dsh_list_workers 仍能看到之前的 worker;
- 已经结束的 worker,dsh_wait 直接返回缓存里的最终回答(不必重新打开会话);
- 重启时还在跑的 worker,会话未打开时状态是 offline(结果未知,去 DSH 侧边栏打开那个会话即可查看);
- dsh_followup 会给 worker 开新一轮,同时清掉缓存的旧回答;
- 文件最多保留 200 条,超出时先淘汰最旧的 已关闭 worker。
安全模型
- 只监听 127.0.0.1,不对外暴露。
- 请求必须携带令牌:路径 /mcp/<token>,或 Authorization: Bearer <token>;比较使用定长时间比较。
- 令牌首次启动时生成并持久化(重启后复用),因此能力 URL 稳定。
- 能力等价于「向指定会话投递消息」:本机任意进程只要能读到端点文件就能派活。文件权限 0600、目录 0700;不要把它复制到共享位置。
- DSH 侧的权限策略不受影响:派发进去的消息仍按会话自身的 sandbox / 审批策略执行。
实现
Codex / 任意 MCP 客户端 │ POST /mcp/<token> JSON-RPC(stateless,单次 JSON 响应) ▼ dsh-plugin-subagent-bridge(宿主进程内)
· node:http 监听 127.0.0.1:47821
· initialize / tools/list / tools/call / ping
· sessionController.prompt({sessionId, requestId, mode, content})
· sessions.get(id).snapshotEvents() 读回助手文本
协议实现为 streamable HTTP 的无状态子集:每个 POST 返回一段 application/json,不做服务端推送,因此取结果用长轮询——dsh_read_result 在服务端等,客户端一次调用即可拿到答案;客户端断开时服务端立即停止等待。
配套 skill
skills/ 下有两份可直接安装的 skill,把「什么时候该派活、怎么派、怎么收尾」写成模型能读的规则:
| Skill | 装给谁 | 作用 |
| deepseek-worker | Codex | 让 Codex 把任务当 subagent 派给 DSH(dsh_task),一次调用等结果 |
| delegate-to-codex | DSH | 让 DSH 的 agent 在需要独立视角/复核时派给 Codex(codex_dispatch) |
Codex 侧
mkdir -p ~/.codex/skills && cp -R skills/deepseek-worker ~/.codex/skills/
DSH 侧
mkdir -p ~/.dsh/skills && cp -R skills/delegate-to-codex ~/.dsh/skills/
两份都是标准 SKILL.md:YAML frontmatter(name + description)+ 正文。触发靠 description——模型平时只看到名字和描述,判断相关了才读正文,所以描述里写满了中英触发语和「不要用」的边界。改完立刻生效,不用重启:Codex 下一次会话、DSH 下一轮就能看到。
兼容性
- DSH ^0.2.1-0(engines.dsh)。
- MCP 协议版本:2025-06-18、2025-03-26、2024-11-05(按客户端请求回显,未知版本回落到最新)。
- 依赖宿主公开服务 sessionController(list / prompt)与 sessions.get();两者不可用时工具会返回明确错误。
开发
node --test "test/*.test.mjs"
58 项:握手与版本协商、通知处理、工具清单、未知方法与未知工具、参数校验、元数据列表不含消息内容、派发调用形状、拒绝与错误透出、结果读取的时间基线、未派发会话的拒绝、长轮询(文本晚到即返回 / 超时 / 调用方取消)、真实 HTTP 往返(含 404/405/202 与 bearer 分支)、codex exec 事件解析、二进制解析、成功/失败/超时三种运行结果、resume 的参数分叉、工具结果的 lossless JSON 约束、只回最终回答(多步叙述被丢弃)、dsh_wait 的任一完成 / 超时 / 错误 / 未派发四种状态、dsh_spawn 立即返回与注册、fork_turns=all 走 fork、并发上限与 dsh_close 释放名额、dsh_followup 的重基线与最终回答切换、注册表落盘与重启后复原、冷会话下的缓存回答与 offline 状态、注册表 200 条上限的淘汰顺序、maxHops 拒绝回派而放行首层、在飞链路阻塞嵌套派发、速率突发的拒绝与窗口过期、followup 计入同一预算、握手版本号取自 package.json(不再硬编码)、新建的 worker 会按 cwd 自动归入对应工作区(不再落到「未分组」)、阻塞式 dsh_task 不占 spawn 名额(重启后也不占)、按 cwd 分桶的每项目预算与全局上限、过期记录到期释放名额、超时返回 running: true 与续等指引、阻塞时长被夹到 240 秒以内。
test/persistence.test.mjs 单独覆盖持久化:文件权限 0600、缺失/损坏/畸形记录、spawn 返回时文件已落盘、完成即缓存、followup 清缓存、close 后重启仍为 closed、冷会话走缓存或 offline、并发写不串。
相关插件
| 插件 | 说明 |
| dsh-plugin-composer-predict | 预测下一条指令,显示为占位文字,按 Tab 采纳 |
| dsh-plugin-composer-history | 输入框中按 ↑ / ↓ 回填历史消息 |
| dsh-plugin-subagent-bridge(本仓库) | 让 Codex 通过本机 MCP 把 DSH 当子代理用(spawn / wait / followup),反向也能把任务派给 Codex |
| dsh-plugin-usage-panel | 在模型选择器旁显示服务商套餐额度余量(目前支持 GLM Coding Plan),点开是明细浮层 |
| dsh-plugin-provider-icons | 在模型名旁显示服务商品牌 logo(24 个厂商,支持前缀匹配) |
许可
MIT © Dogtiti预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Dogtiti/dsh-plugin-subagent-bridge
在 DeepSeek Harness 宿主内部提供本机回环 MCP 端点,让另一个智能体如 Codex把任务派给…
相关插件 · 工具 / 效率
破甲管控台kingcharleslzy-ai/dsh-purge
dsh-purge Community · DeepSeek Harness 社区维护版:宿主兼容、状态诊断、提示词管理、更新与本机备份回滚。基于小杨 / YuJunZhiXue 的 dsh-purge。
★ 3,801已汉化DeepSeek 客户端
74.5
网文长卷lingfengQAQ/webnovel-writer
基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200…
★ 7,636已汉化DSH
72.2
多智能体协作HKUDS/AutoSwarm
AutoSwarm: Unify Your Agents. Unify Your Context (Codex · Claude Code · DeepSeek Harness · Muse · Grok · WorkBuddy· nanobot · and more)
★ 2,082已汉化DSH
71.7
Vox 拼贴视频生成Alisa0808/vox-director
🎬 Vox Director拼贴动效导演
★ 2,129已汉化DSH
71.4
Agent 演化引擎Q00/ouroboros
智能体 OS:智能体自己变聪明,我们只守住底线:面试准入、分阶段评估、带预算的进化循环。MCP 服务器,14 种运行时:Claude Code、Codex CLI、Gemini CLI、OpenCode、Copilot、Kiro 等。
★ 6,292已汉化DSH
71.3
智能体运行框架路由HarnessRouter/harnessrouter
智能体运行框架的统一接口。
★ 3,800已汉化DSH
71.2