前言¶
DSH 里给子代理选模型,原本只有三档:工具实例的静态 agentOptions、会话级的 subagent-model-selection 白名单、具名子代理库的逐条目配置。这三档都表达不了一件事:你在哪个项目目录里干活,子代理就用那个项目配好的模型。结果是每次派活都要手动挑一遍,或者干脆将就。
dsh-subagent-routes 就是补这一档的插件。它由 zdt3476 维护,仓库为 zdt3476/dsh-subagent-routes,社区目录分类归在「模型推理」。插件按工作区的目录做最长前缀匹配,把匹配到的 provider / model / 思考等级注入子代理的 agentOptions,并提供可视化设置页。下面介绍它的能力与用法。
这是什么¶
一句话定位:一个 DSH 插件,根据子代理派活时父会话所在的工作区目录,为子代理指定 provider、模型与思考等级。
它解决的痛点是「项目级路由」。前端项目想找强模型、长文档研究想固定最大思考等级、临时脚本想用便宜模型、一个仓库里不同子目录用不同策略——这些都无法用现有三档配置表达。插件用一张最长前缀匹配的路由表覆盖这些场景,同时提供一个设置页,避免手写 YAML。
社区目录页的分类是「模型推理」,仓库当前为 1 stars,属于小体量个人项目。
核心功能¶
路由只作用于新派活的子代理,对已经在跑的会话不做任何改动。
插件介入的位置很单一:所有创建子代理的入口(subagent、subagent_fork、workflow、agent-team、具名子代理库的 delegate)最终都会调用 ctx.subagents.startActivation,插件只在这一处拦截。因此它天然覆盖全部派活路径,不需要改 DSH 本体。
处理流程是:
- 读父会话的当前工作目录(
workingDirectory投影优先,回落到会话头cwd); - 在路由表里做最长前缀匹配;
- 把匹配到的 provider / model / reasoningEffort 合并进
request.agentOptions; - 按需调用
llm.resolveCallConfig()预检,路由非法时在派活处直接失败。
派活时不写会话事件、不改 profile;只有用户保存基础配置时,才通过宿主 configEditor.edit 持久化到当前 profile,并校验、重载插件。
设置页提供三级联动选择:Provider、Model、思考等级全部从宿主已探测的列表里选,不用背 ID。私有通道支持「手动输入」。未选 Provider 时 Model 下拉按厂商分组列出全部模型,选项内部同时编码 provider + model,不同厂商的同名模型不会互相覆盖。思考等级跟随所选模型的真实元数据:模型不支持推理时选项置灰并清空;支持时只列出该模型的专属档位;手动输入的未知模型 ID 会保留已选等级,插件不擅自改写。
项目规则里的「项目根目录」默认从宿主已登记的工作区里挑(显示为「标题 — 路径」),需要 ~/... 或更细的子目录时可切「手动输入」。偏好直接编辑时,右上角可切「原始 YAML 模式」,可视化表单与 YAML 双向同步,保存时校验结构。
此外,会话页面输入区有一个状态药丸(子 provider / model ▾),点击可就地临时切换本会话的 provider / model,用于临时拔高或降配,而不必改规则。右侧栏仍保留一个更接近配置表单形态的「子代理」tab,两处共用同一份优先级判定与数据面。
安装与启用¶
安装命令来自仓库 README:
# 从本地目录安装
dsh plugin --profile desktop add /path/to/dsh-subagent-routes
# 或从 npm 安装(发布后)
dsh plugin --profile desktop add @zdt3476/dsh-subagent-routes
首次安装、或从没有 client 的旧实现升级后,需重载插件或重启 DSH,确保宿主加载新的 client 能力;仅打开旧设置页不会补载新入口。若重载后仍无设置入口,请重启 DSH。
安装后设置入口出现在「插件管理 → 本插件 → 设置」,bundle 卡片与 patch 插件行均提供入口。会话页右侧栏 tab 与输入区药丸由同一份 client 产物注册;若右侧栏没出现「子代理」,同样先重载插件,仍不行再重启 DSH(客户端插件的 Slot 注册只在插件加载时进行)。
典型用法¶
三步即可跑起来,全程不需要手写 YAML:
- 打开设置页:插件管理 → 本插件 → 设置。
- (可选)设全局默认模型:没匹配到任何项目时用它兜底,留空则继承父会话模型。
- 添加项目规则:点「+ 添加项目规则」→ 从工作区下拉选项目 → 从模型下拉选模型 → 思考等级自动跟着模型联动 → 「确认保存规则」→ 底部「保存所有更改」。
保存后下一次新派活立即生效,不需要重启 DSH。
也可以直接手写路由表。默认位置是 $DSH_HOME/subagent-routes.yaml(通常是 ~/.dsh/subagent-routes.yaml),可视化设置页就是它的编辑器:
default:
provider: openai
model: gpt-4.1
reasoningEffort: medium
routes:
- path: ~/Code/frontend-app
provider: anthropic
model: claude-sonnet-4
reasoningEffort: high
- path: ~/Code/frontend-app/legacy # 更长前缀优先
provider: deepseek
model: deepseek-chat
- path: ~/Code/research
reasoningEffort: max # 只改等级,provider/model 继承父会话
字段规则:path 必填,绝对路径或以 ~ 开头,尾部分隔符会被规范化掉;provider 与 model 必须同时出现或同时省略;reasoningEffort 使用适配器自有的等级 id(low / medium / high / max 等,取决于模型);三者至少要有一个。
改路由表后,下一次新派活即生效,每次派活都会重读文件,不需要重启。
优先级规则¶
从高到低:
调用方显式指定 > 本会话选择 > 项目规则 > 全局兜底 > 全局默认策略
具体行为:
- 调用方显式给了
provider+model→ 插件完全让位,连思考等级也不追加(这是给工作区模型配的等级,套到另一个模型上可能不被支持)。 - 调用方只给了
reasoningEffort→ 插件补 provider / model,保留其等级。 - 本会话选了「继承主代理」→ 直接让位,项目规则与全局策略都不介入。
- 本会话选了「指定一套」→ 覆盖项目规则。
- 本会话未做选择(界面默认态,存储层记为
follow)→ 继续按上述层次判定。 - 全局策略是「继承主代理」→ 让位,不查路由表。
- 全局策略是「使用路由规则」→ 按目录匹配项目规则,未命中时用全局兜底。
- 所有层都没有内容 → 插件不注入任何字段,子代理保持 DSH 原生的继承行为。
会话级切换存在 $DSH_HOME/subagent-routes.overrides.json,与路由表同目录,原子写入、保留最近 100 个会话。注意「继承主代理」没有可写入路由表的 provider / model,该状态下「固化为项目规则」按钮会置灰;固化到某目录时该目录已有条目会被替换,不会追加成第二条。
插件配置项¶
在 profile 的 cordis.patch.yml 里按 id 覆盖。同 id 的 override 会替换整个 config,三个字段要写全:
- id: subagent-routes
config:
routesFile: ~/.dsh/subagent-routes.yaml
enabled: true
preflight: true
fallbackPolicy: rules
| 字段 | 默认 | 说明 |
|---|---|---|
routesFile |
$DSH_HOME/subagent-routes.yaml |
路由表路径,留空用默认位置 |
enabled |
true |
路由注入开关,false 时停止注入,设置入口仍保留 |
preflight |
true |
注入前用 llm.resolveCallConfig 校验路由,关掉则把错误留到子会话首轮 |
fallbackPolicy |
rules |
inherit = 没有更具体来源时继承主代理模型;rules = 按路由表注入 |
这四项在设置页里分别对应「已启用 / 已暂停」开关、「全局默认策略」卡片与折叠的「高级选项」,改完点底部「保存所有更改」即可,无需手工编辑 profile。fallbackPolicy 写了未知值时按 rules 处理,并在日志里保持可解释。
适用场景与注意¶
适合需要项目级模型路由的 DSH 用户,尤其是一个 profile 下同时维护多个项目、对成本与能力档位有差异化要求的开发者,或想按目录固定思考等级的长文档研究场景。
使用时要清楚几点:
- 插件只影响新派活,正在运行中的子代理不会被重新路由。
fork同样适用,但 fork 会继承父会话的对话前缀,换模型会让这段前缀的 provider 侧缓存失效,属于预期代价。- 前缀匹配是纯字符串的,不做 realpath,符号链接和
..不会自动归一。 - 工作区与模型列表来自宿主;宿主没提供对应服务或该 profile 尚未登记工作区时,设置页会自动退回手动输入。
- 会话指定必须成对给模型,只指定 provider 或只指定思考等级会被拒绝。
- 路由表写错时日志会给出行号级说明,该次派活按「无路由」继续,不会阻塞工作。
还需要说明的是,插件以当前 dsh 进程的权限运行,安装前应检查源码与许可证。仓库声明为 MIT 许可(见 package.json 的 license),要求 Node ^22.19.0 || >=24.0.0、DSH >=0.2.1-0。
结尾¶
dsh-subagent-routes 做的事情很窄:把子代理的模型路由从「全局一个选择」细化到「按工作区目录一条路由」。它的价值在于不需要改 DSH 本体、原生覆盖全部派活入口,并提供可视化设置页降低维护成本。项目当前星标不多,功能边界写在「已知边界」一节,是否有自己需要的行为,建议对照后再看是否采用。
目录页:https://www.skillhub.cn/plugins/zdt3476/dsh-subagent-routes
GitHub:https://github.com/zdt3476/dsh-subagent-routes