DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

tkaiz0406 /

tkaiz0406/dsh-subagent-route-pin

Verified

DSH plugin: pin a separate LLM route for delegated subagents (Agency experts, Agent Teams members) while the main agent keeps its own model. Settings page included.

★ 2 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@8deb002e

dsh-subagent-route-pin

给被委派的子代理(专家团专家、Agent Teams 成员、单发子代理)单独指定 LLM 路由,主 agent 不受影响。

解决的问题:DSH 默认让子 agent 继承主 agent 的模型路由,于是「大脑 + 4 路子代理」挤在同一个 provider 账号额度里,summon_experts 看起来卡死。装上本插件后,主 agent 可以跑免费车道,子代理跑另一个账号/模型,两条额度队列互不阻塞。

适用面:按 provider 生效,不按专家名单。agency 里 331 个专家、你新建的自定义专家、以后升级新增的专家,只要还读 config.provider,都自动命中同一条路由。

它做什么

  • 注册一个包装 provider pinned-account,委托内置 spawn,在创建子 agent 前填入 agentOptions
  • 单发子代理走 provider.start():包装 provider 直接生效
  • 团队模式成员不经过 provider.start():在 subagents.startActivation()(当前契约)或 startContinuable()(旧名)上挂一层钩子,把路由填进 request.agentOptions(可用 teamInjection: false 关闭)
  • 覆盖团队成员自带路由(overrideMemberRoute,默认开):Agent Teams 会按自己的 memberLlmProvider / memberModel 先填好 agentOptions,只填「空槽」等于一个成员也钉不上;开着时钉住的路由优先,关掉则尊重调用方已选的路由(只补空槽)
  • 能力标志:钩子探测结果会发布成 { teamInjection: 'installed' | 'unavailable', enabled, seams, reason },调用方能读到「团队注入此刻可不可用、挂在哪条缝上」,而不是只靠日志猜
  • 零配置可用:没配路由、或路由指向一个当前不存在的 provider/model 时,子 agent 继承主 agent 的模型,召唤不会失败
  • 失败必提示(onPinFailure,默认 fail):你在设置页选过模型、它却跑不起来时,召唤直接报错并在错误里写明「哪个路由失败、为什么、去哪里改」,绝不静默换成别的模型;设成 inherit 才允许回退
  • 自动接线(autoWireAgency,默认开):挂载时把 profile 里 agency-agents 行的 provider 补成 pinned-account(改前留 .bak-autowire-* 备份,已接线则不动),装完不需要手改 YAML
  • 每次委派的结果写进 ~/.dsh/subagent-route-pin.last-run.json(pinned / failed + 原因),排障不用翻日志
  • 设置 → 专家模型 页面:提供商 / 模型 / 推理强度下拉 + 团队模式注入开关 + 专家团引擎提示,保存写回 profile 补丁,下一次委派生效
  • 逐专家覆盖:~/.dsh/subagent-route-pin.json 的 experts 字段(可选,优先级高于页面)

安装

# 从 tarball
dsh plugin --profile desktop add "./dsh-subagent-route-pin-0.8.2.tgz"

# 从 npm(发布后)
dsh plugin --profile desktop add "dsh-subagent-route-pin"

# 从本地目录(开发调试,link 安装)
dsh plugin --profile desktop add "D:\\path\\to\\dsh-subagent-route-pin"

dsh plugin 要写 profile 目录,通常需要提权(关闭沙箱或以同一用户直接运行终端)。

装完后 profile 的 cordis.patch.yml 里新增一行(包内 cordis.patch.yml 已自带,无需手写)。provider 留空即「不钉路由」,子 agent 继承主 agent 的模型:

- id: subagent-route-pin
  name: "dsh-subagent-route-pin"
  config:
    providerName: pinned-account
    baseProvider: spawn
    provider: deepseek-account
    model: deepseek-flash
    reasoningEffort: ''
    strict: false
    teamInjection: true
    overrideMemberRoute: true
    fallback: true

装完不配也能用:路由没填、或填的 provider/model 在当前账号里不存在时,插件只打一条警告,子 agent 照旧继承主 agent 的模型——不会让召唤失败。strict: true 才会把它变成硬错误。

真正要改的只有两处

想把子 agent 分到另一条车道,只需要两处:

  1. 这条路由 —— provider / model,指向你账号里真实存在的组合。不用手改文件:打开 设置 → 专家模型,点选后保存即可(写回同一行)。
  2. 专家团那行的 provider —— 改成 pinned-account,否则专家根本不经过本插件。

除此之外没有第三处。团队模式(Agent Teams)不走这条路径,见下文。

让专家团用上它

专家团(@michengai/dsh-agency-agents)默认走 spawn,需要把它的 provider 指过来:

- id: agency-agents
  name: "@michengai/dsh-agency-agents"
  config:
    provider: pinned-account
    # 不要写 maxDepth —— 写了会强制单发阻塞引擎,召唤要等全部跑完

注意:profile 的 patch 行是整行替换 config,改这一行时要把 enabled / customExperts / enabledTeams 等原字段一起重述,否则会被清空。

Agent Teams(@nanmicoder/dsh-agent-teams)有自己的一套 memberModel / memberLlmProvider,插件不会覆盖它——两条路由各管各的,避免互相打架。

看团队跑到哪了(本地面板)

Agent Teams 自己是条件渲染的:会话标题栏那个入口只在「当前会话确实持有一个开跑的团队」时才出现,计划还在暂存(等你批准)、或者你换了会话、想看别的项目里的团队,界面上就什么都看不到。

插件带了一个只读的状态面板,直接读磁盘上的 .agent-teams/<team>/team.json:

# 起一个本地面板,浏览器打开它给的地址,2 秒自动刷新
npm run teams -- --scan "D:/你的工作区父目录"

# 只想在终端看一眼
npm run teams:once -- --dir "D:/你的项目"

# 装了 npm 包的话,也可以直接用 bin
dsh-team-status --serve --port 7800

参数:

参数 作用
--dir <path> 指定工作区根目录(其下有 .agent-teams/),可重复
--scan <root> 把 root 自身和它的直接子目录里带 .agent-teams 的都扫进来
--serve 起 HTTP 面板(默认 127.0.0.1:7788)
--port <n> 换端口

面板显示:团队阶段、计划是否待批准、成员(角色/状态/模型)、任务表(ID/状态/负责人/依赖/尝试次数)、完成进度条。暂存态会直接提示「计划还没批准:去 Web 的计划卡点 Approve & Run,否则成员不会启动」——这就是最常见的「看不到团队」原因。

它只读状态文件,不连 DSH、不改任何东西,所以任何会话、任何项目都能看。

验证

重启 DSH 后:

  1. 设置 → 专家模型 页面出现,底部显示「专家团引擎」
  2. 日志出现 subagent-route-pin: provider "pinned-account" delegates to "spawn"
  3. 日志出现 subagent-route-pin: team-mode hook installed on ctx.subagents.startActivation
  4. 日志出现 subagent-route-pin: capabilities {"teamInjection":"installed","enabled":true,"seams":["startActivation"]}
  5. 委派时出现 subagent-route-pin: team member label="…" -> provider/model

这五行是接口契约,不是装饰:第 2 行说明 provider 包装还挂得上,第 3、4 行说明创建子代理的那条缝还在(seams 会写出实际包住的方法名),第 5 行说明注入实际生效。升级 DSH 后少任何一行,都说明上游接口变了,先别怪额度。

这些行在哪看:ctx.logger.info 只进 DSH 进程控制台(GUI 的开发者控制台 / 终端 stdout),不落盘。~/.dsh/logs/ 下只有启动失败时的诊断 dump,正常启动不写日志文件——所以别去那里找。

插件为此每次启动落一条就绪记录,升级后一条命令就能验:

npm run verify        # = node test/run.mjs && node test/logs.mjs --strict
npm run ready         # 只看盘上的就绪记录,不跑测试

就绪记录:~/.dsh/subagent-route-pin.ready.json

{
  "schema": 1,
  "plugin": "subagent-route-pin",
  "version": "0.8.2",
  "at": "2026-10-20T12:04:11.208Z",
  "mounted": true,
  "providerName": "pinned-account",
  "baseProvider": "spawn",
  "fallback": true,
  "teamInjection": true,
  "capabilities": { "teamInjection": "installed", "enabled": true, "seams": ["startActivation"] }
}

test/logs.mjs 校验:插件身份、版本与本地 package.json 一致、是否挂载、能力标志、实际挂住的接缝(seams 里没有 startActivation 会 WARN:那说明这个构建可能根本不调被包住的方法)、回退开关、providerName -> baseProvider、记录龄(超过 7 天提示重启 DSH)。--strict 时 teamInjection: 'unavailable' 直接判失败——发版前该用这个。

有控制台输出时还能一起验那五行:

node test/logs.mjs --log captured-console.txt

默认 provider delegates / hook installed / capabilities published 三条必需,team member label= 在还没委派过时记为 none。

失败回退

fallback: true(默认)时,钉住的这条路由起不来不会直接砸掉委派:

场景 行为 日志
单发子代理,pinned-account 的 start() 报错 去掉注入的路由,用调用方本来的路由重试一次 pinned route … failed to start (…); retrying on the inherited route …
团队成员,创建调用报错 把 request.agentOptions 还原成调用方原本要的那份(Agent Teams 自己的成员路由),重试一次 team member … failed to start on …; retrying on the requested route …
团队成员本来没带路由(被插件填的) 删掉注入的 agentOptions,用继承路由重试一次 …; retrying on the inherited route
重试后仍然失败 抛出原始错误,不吞 —
注入的路由和继承路由本来就一样 不重试(重试等于再撞一次同一额度) —

边界要说清楚:只在启动阶段可观测。子代理跑起来之后,流式请求中途的 429/额度错误发生在 start() 返回之后,插件抓不到——那种情况要看 DSH 自己的重试与错误上报。所以 fallback 兜的是「开局就撞墙」,不是「跑到一半断粮」。

兼容性

兼容矩阵

DSH / @deepseek-ai/dsh-tool-subagent 状态 说明
0.2.0-rc.1 ≤ 版本 < 0.4.0 ✅ 覆盖范围 当前 peerDependencies 写的范围,0.2.1-rc.2、0.2.1-rc.3 实测 107 项断言全绿;本机构建只有 startActivation(无 startContinuable),插件按 startActivation 注入
0.2.1-rc.3 ✅ 已验证 桌面端 0.2.1-rc.3 上 readiness 记录显示 seams: ["startActivation"]、teamInjection: installed,配置行路由生效
0.2.0-rc.x ❓ 未验证 接口面看起来一致(旧版走 startContinuable),但没跑过;装了会看到 peer 警告
>= 0.4.0 ⚠️ 未验证 超出 peer 范围,DSH 插件管理器会标「异常」并拒绝启动;上游一旦改动 provider 或创建子代理的接缝,日志会先缺,插件按能力标志降级

peerDependencies 从「钉死单个 0.2.1-rc.2」放宽到 >=0.2.0-rc.1 <0.4.0:DSH 每次发 rc 都不再让这个插件被判不兼容、也不会因此被插件管理器拦下。范围上限留在 0.4.0,是因为 provider 和创建子代理的接缝属于内部契约,跨 minor 需要重新验证——发版前请跑 npm test(107 项断言)与 npm run ready(真实宿主上的 readiness)。

接口依赖

依赖 说明
ctx.subagents.registerProvider 缺失时置能力标志 teamInjection: 'unavailable' 并告警,不阻断 profile 启动
ctx.subagents.startActivation / startContinuable 至少一条存在且可被定义 own property;两条都在时优先 startActivation(当前构建的原生委派与 Agent Teams 都走它),两条都不在则置 unavailable 并退化为「仅单发子代理可控」
@deepseek-ai/dsh-tool-subagent 的 provider 接口 能力表必须声明 agentOptions;内置 spawn 自带
浏览器侧 configForms / slots / locale / remote.session.modelCatalog 页面用;缺失时卡片显示「不可用」状态
设置行 patch 语义 整行替换 config,不是合并

读取能力标志(宿主侧):

import { teamInjectionCapabilities } from 'dsh-subagent-route-pin'

// { teamInjection: 'installed' | 'unavailable', enabled?: boolean, seams: string[], reason?: string }
const capability = teamInjectionCapabilities(ctx.subagents)
if (capability.teamInjection === 'unavailable') {
  // 团队成员会保持父路由 —— 这里决定要不要降级/提示用户
}
// seams 是实际包住的方法名:['startActivation'] 表示当前构建真的会走到它

同一份结果也挂在 ctx.subagents[Symbol.for('dsh-subagent-route-pin.team-hook')].capabilities 上;0.8 之前的 …continuable-hook 符号仍然读写,旧调用方不用改。

teamInjection 依赖接缝方法可被定义 own property;若 DSH 后续冻结该服务对象,插件置 unavailable 并退化为「仅单发子代理可控」。

测试

node test/run.mjs        # 107 项断言,不需要 DSH 在跑
node test/logs.mjs       # 检查真实启动留下的就绪记录
npm run verify           # 两个一起,且 --strict

107 项断言:路由优先级、文件热读、strict 校验、团队注入、覆盖团队成员自带路由(默认覆盖 / overrideMemberRoute: false 时尊重 / 保留调用方其他字段 / 丢弃旧路由的 effort / 覆盖失败退回调用方原路由)、开关关闭、缺路由不阻断、dispose 还原、重复挂载换路由、能力标志(installed / unavailable / 无任何接缝)、多接缝(只有 startActivation / 只有 startContinuable / 两条都在时优先前者且只注入一次)、启动失败回退(单发 / 团队 / 关闭开关 / 重试仍失败 / 同路由不重试)、日志契约、就绪记录(正常挂载 / 缺服务 / 版本一致)。

test/run.mjs 证明的是插件逻辑没坏;test/logs.mjs 证明的是它在这个 DSH 构建里还挂着。两件事会分别失败,上游接口变更先体现在后者。

升级回归

升级 DSH 后按这个顺序走,别跳步:

node test/run.mjs                 # 1. 逻辑层:107 项还绿吗
# 2. 重启 DSH(只改插件不用,改 DSH 本体必须)
npm run ready                     # 3. 挂载层:就绪记录还是这次启动写的吗

第 3 步读到 capabilities.teamInjection: "unavailable" 就是上游把创建子代理的接缝动了——此时单发子代理仍可控,团队模式成员退回父路由。读到 seams 里没有 startActivation,说明钩子包住的方法当前构建不调用,同样是接口变了。把 peerDependencies 和兼容矩阵一起对一遍,再决定是适配还是回滚。

发布

包名是不带 scope 的 dsh-subagent-route-pin(npm 上确认未被占用),因此不需要拥有任何 npm 组织/scope,登录任意账号即可发布:

npm login
npm publish                    # 无 scope,默认为 public
pnpm pack --pack-destination dist

若以后要改到自己的 scope(例如 @yourname/dsh-subagent-route-pin),必须同时改这 4 处,少一处就会出现「装上了但不加载」:

# 位置 作用
1 package.json → name 安装名、依赖解析名
2 cordis.patch.yml → 行的 name profile 加载器按包名找入口
3 client.js → __ModuleLoader__.load({ id }) 浏览器端模块 id
4 client.js → CONFIG_NS_CANDIDATES 设置页绑定配置行的候选名

另需同步 test/client.mjs、test/browser-harness.html 里的 id 断言,以及 README 里的安装示例。

GitHub 仓库名与 npm 包名保持一致(dsh-subagent-route-pin),仓库归属 tkaiz0406 是 GitHub 账号,与 npm scope 无关,repository/homepage/bugs 无需随 npm 改名。

回滚

dsh plugin --profile desktop remove "dsh-subagent-route-pin"

或删掉 profile cordis.patch.yml 里 id: subagent-route-pin 那一行。

License

MIT — 见 LICENSE。

—/ 5

No ratings yet

Verified DSH bundle

Commit 8deb002e2af3

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout