dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Subagent-shaped bridge between Codex and DeepSeek Harness: Codex spawns DSH workers over a loopback MCP endpoint and gets final answers back; DSH agents can dispatch to Codex in return.
在 DeepSeek Harness 宿主内部提供本机回环 MCP 端点,让另一个智能体(如 Codex)把任务派给 DSH 会话并取回结果。
插件运行在宿主进程内,直接使用公开的 sessionController 服务 —— 不需要读取 ~/.dsh/.credentials.yaml,也不需要伪造 cookie。
工具 · 作用 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、标题、工作目录、是否运行、最后活动时间)
插件同时给本部署的 Agent 注册了一个工具:
工具 · 参数 · 返回 codex_dispatch · prompt(必填)、cwd、resume(线程 id)、sandbox · { ok, text, threadId, exitCode, durationMs, error? }
它执行 codex exec [resume ] --json -o ,从事件流取 thread.started、从 -o 文件取最终消息;工具结果里会带 [codex thread · 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-bridgePlugins → 添加 → 选该目录。
启动后插件在 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 mcp add dsh-bridge --url "$(node -p "require(process.env.HOME+'/.dsh/bridge/endpoint.json').url")"验证:
codex mcp list
codex mcp get dsh-bridgeCodex 的桌面 App 与 CLI 共用 ~/.codex/config.toml,所以两端都会看到这条。
token 存在 URL 路径里(能力 URL),因此不需要在 Codex 侧配置环境变量 —— 桌面 App 从 Finder 启动时拿不到自定义环境变量。若你更想用 bearer,也可以--bearer-token-env-var指向环境变量,插件同时支持Authorization: Bearer。
移除:
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 …。
两个 agent 都接了同一个桥时,存在真实的环路:DSH worker → codex_dispatch → 那次 Codex 运行也能看到 dsh-bridge → 又 dsh_spawn → …。两边各自进程内的深度规则都管不到这条链(Codex 的 agent_max_depth 只数自己的 spawn_agent,DSH 的 maxDepth 只看 delegationDepth,而桥建的 worker 是顶层会话,深度恒为 0)。
所以桥自带两道:
① 深度(`maxHops`,默认 1)
max(当前在飞的链路深度, 调用方深度) + 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 23sworker 名额按工作目录分桶,调用方不用传任何 owner:
cwd 默认 4 个(maxWorkersPerRoot);maxWorkers),跨项目兜底;workerTtlMs),不需要手动清理;dsh_task 不计入名额,只登记。为什么不是"每个会话 4 个":MCP 端点是共享的,请求里没有会话或线程身份(Codex 的 CODEX_THREAD_ID 只存在于 shell 环境)。cwd 是唯一由调用方稳定提供、且语义上对应"一个项目"的维度。
worker 注册表(task_name / sessionId / 终态结果)和每轮的时间基线都落在 ~/.dsh/bridge/workers.json:
dsh_wait 直接返回缓存里的最终回答(不必重新打开会话);offline(结果未知,去 DSH 侧边栏打开那个会话即可查看);dsh_followup 会给 worker 开新一轮,同时清掉缓存的旧回答;127.0.0.1,不对外暴露。/mcp/,或 Authorization: Bearer ;比较使用定长时间比较。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 在服务端等,客户端一次调用即可拿到答案;客户端断开时服务端立即停止等待。
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 下一轮就能看到。
^0.2.1-0(engines.dsh)。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 当 subagent 用(spawn / wait / followup),反向也能把任务派给 Codex dsh-plugin-usage-panel · 在模型选择器旁显示供应商套餐额度余量(目前 GLM Coding Plan),点开是明细浮层 dsh-plugin-provider-icons · 在模型名旁显示供应商品牌 logo(24 个厂商,支持前缀匹配)
MIT © Dogtiti