DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins

dsh-subagent-model

Subagent Model

DeepSeek Harness 插件会在每次委派启动子代理前询问应使用的提供商和模型,使子代理可以选择低成本或本地路径,而不是使用父代理的路径。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add dsh-subagent-model@0.1.1
README兼容性版本

兼容性与来源证明

Subagent Model 以 dsh-subagent-model 发布,当前版本为 0.1.1。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
any
发布来源
npm
Registry 更新时间
2026/11/4

版本

0.1.1stable
2026/9/18
0.1.0stable
2026/8/27

相关插件

正在加载相关插件…

最新版
0.1.1
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
156.9 kB
文件数
14
Surface
any
许可证
MIT
发布源
npm
GitHub
★ 0
周下载
22
最近提交
2026/9/18
查看源码 ↗项目主页 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 models-usage 分类下经过校验的插件。

Experimental Cot Translation Bundle@deepseek-ai/dsh-experimental-cot-translation-bundle扩展推理的实验性机器翻译Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Our Free Model@ebony-vinyl/dsh-our-free-modelOur Free Model — 在 dsh 里装上这个插件即可,无需登录、注册或填 API Key,就能使用包括 DeepSeek V4.1 Flash、Kimi K3 在内的前沿模型,桌面端另有 EAC 协付渠道;2.0 起接入 LobsterAI、Qoder、TRAE、Cline、Loomy、Raccoon、MiniMax、ZCode、Gemini 十个账号渠道(原有匿名免费通道保留)(登录、账号池、积分领取、本地 OpenAI 网关与局域网转发、数据看板与运行日志),六页毛玻璃界面统一呈现。Usage@linxin666/dsh-usage用于 dsh Web GUI 的使用统计插件:检测各提供商的余额和编程套餐配额,并实时记录令牌使用情况;侧边栏 Settings 行上方显示紧凑的价格概览卡片

README

🧭 dsh-subagent-model

Host-layer DeepSeek Harness (DSH) plugin that asks which provider and model should run each delegation before the child starts, so a subagent can go to a cheap or local route instead of inheriting the parent's.

📋 Table of Contents
  • What It Fixes
  • How It Works
  • What the Dialog Offers
  • The Model Picker Contract
  • Guarantees
  • Installation
  • Configuration
  • Verification & Testing
  • Known Limitations
  • 🤝 Contributing
  • 🔗 Links
  • License

The question, answered in a running session — the task, the routes this plugin configures, and the models the session's own directory offers, with prices and context windows:

The delegation dialog: the task dossier, three quick choices with their descriptions, the DeepSeek provider group with prices and context windows, and the footer's keep and auto answers

A model picker (dsh-model-chooser) draws that list; without one, the harness's own question card renders the same question as a plain option list.

What It Fixes

A subagent inherits the parent's provider and model unless the request overrides them (resolveChildAgentOptions in dsh-subagent). The delegation tool passes no model, so a child's route is a config-time decision — while the moment you actually know what the task is (its label, its prompt size, whether it is a durable background child) is the moment the delegation starts.

That is where this plugin asks. A research delegation that reads a directory does not need the parent's frontier model, and a local gateway can serve it for nothing; a hard refactor may still want the expensive route. The plugin turns that from a guess into one question per delegation, answerable on information.

It costs nothing when it is not used: no tool, no prompt section, no instruction text, no added tokens.

How It Works

One thing is installed, scoped to the plugin's own fiber: wrappers around ctx.subagents.start and ctx.subagents.startContinuable, filtered to one provider name (default spawn). They ask, then hand the answer to the real method as the child's agentOptions.

Three facts explain why the wrap happens there and nowhere else:

  • Both entry points carry a child's model by different paths. start hands the child to a provider that composes it; startContinuable composes the child itself and reads request.agentOptions directly. A provider-level hook would miss every durable background child.
  • The registry is a host singleton, the tools are not. The delegation tools (tool-subagent, and every copy of it in a preset) live in the AGENT PRESET's composition — for studio-style deployments a generated file in the harness home — while the subagents registry they resolve is owned by the host composition. Wrapping the registry therefore reaches every preset, including one generated outside this repository, and needs no composition surgery. Patching a tool row instead would miss every preset the profile layer cannot see.
  • The chosen lane wins by construction. resolveChildAgentOptions applies the request's agentOptions over the parent's route, so the child's model is the one you picked.

The wrapper is keyed by provider name, so a delegation to any other provider — fork, a remote backend — is forwarded untouched.

What it asks about

scope defaults to labelled, which means a start carrying a task label. The delegation tool is the one caller that sends one, and that label is what makes the dialog answerable ("Task: …"). The workflow engine's children and Ralph's rounds start on the same provider without a label, so they keep the route their caller chose instead of raising a dialog per phase. Set scope: any to be asked about those too.

What the Dialog Offers

What the human sees depends on the UI that answers it. The harness's own question card renders the options as a list:

Subagent model
  Which model should run this delegation?
  Task: Check the flaky test
  Prompt: 8 characters (~2 tokens at 4 characters per token — an estimate, not provider-reported)
  Child: durable background child (continuable; later turns go through send_message)
  Route without this choice: requesty/deepseek-v4.1-flash
  [ PX13 local (fast) ] [ PX13 local (deep) ] [ Cloud small (haiku) ]
  [ Keep the parent model (requesty::deepseek/deepseek-v4.1-flash) ] [ Auto for this session ]

With a model picker that recognises this question (see the picker contract), the same question is answered by a searchable list of every configured model instead, and the lanes list becomes optional — it stays available as a quick-choice group, with its configured descriptions.

The parent option's label carries the inherited route in the parenthesised provider::model form, so a picker can mark that row as the current one; the router matches it by prefix. A lane label may therefore not start with the parent answer.

Complexity is deliberately not estimated: the prompt size is a measurement, a difficulty score would be invented.

The dossier the dialog shows is exactly that: the task label, the prompt size as an estimate, the child kind, the route it would inherit, and the route the tool configuration already requests.

The Model Picker Contract

A UI may answer this question with a route label — provider::model — because a picker's list is the live catalog rather than this dialog's options. It arrives as the answer's free text (custom): the host refuses a selected label that is not among the question's own options, with bad-response (matchesQuestions in packages/host/apiproxy), and a single-choice question requires custom instead of a selection. A route label sent as a selection is accepted as well, for a UI whose options carry them; the router reads either.

The separator is :: and not / because a model id may itself contain a slash (this deployment's requesty route serves anthropic/claude-haiku-4-5), so a provider/model label could not be split back apart. The same separator is the key format of the picker's own catalog, which is where the contract comes from.

Offering every catalog route as a dialog option would legalize a selection, but it would also push hundreds of entries into the question — and into the native question card that answers it when no picker is mounted. The free-text field is the protocol's own way to answer with something the asker did not offer.

The router then checks the route against the mounted llm service before using it:

VerdictWhenResult
acceptedthe provider is listed and the model is in a readable model list, or nothing readable could contradict the pairthe child runs on that route
refusedthe provider is missing from the provider list, or the model is missing from a readable model listthe configured default, one warning
unjudgeableno llm service, an unreadable provider list, or an empty model listaccepted — an enumeration that does not answer is not a route that does not exist

Model lists are cached per provider for five minutes, so a burst of delegations does not enumerate per child, and a list refreshed by the picker becomes visible within that window.

The plugin that implements this contract today is dsh-model-chooser, whose picker also answers the composer's model seat.

Guarantees

The router never blocks a delegation. Every failure path returns the request it was given, with a warning: no lane configured, no userQuestions service, a question that throws, an answer that names nothing. A router bug may send a delegation to the wrong route; it may never strand a session. The one exception is caller cancellation, which the caller's own signal owns — the signal is handed to the dialog, so a cancelled delegation does not leave a question waiting.

SituationResult
ask: false, or the session already answered "Auto"the configured default route, no dialog
A start without a task label, and scope: labelledthe request as built, silently
No userQuestions provider (headless profile)the configured default, one warning
A nested delegation (the parent is not a live runtime root)the configured default, one info line — the harness refuses human interaction there
Any other question failurethe configured default, one warning
The answer names no configured lane and is not a route labelthe request as built, one warning
The answer is a route the llm service contradictsthe configured default, one warning
A bug in the plugin itselfthe request as built, one warning

Nothing model-visible is added. No tool, no prompt section, no instruction text: the plugin is host-side only. A session's request prefix is byte-identical with and without it, and the parent's own prefix cache is untouched — only the child's requests change.

Misconfiguration fails at load. A lane without label, provider, or model, a duplicate label, a label equal to (or starting with) one of the router's own answers, an unknown default, and an unknown scope all fail when the plugin mounts.

Installation

dsh plugin --profile <profile> add dsh-subagent-model

The package carries a dsh.bundle.patch layer, so the CLI appends it to the profile's bundle stack and the router row mounts. No other row is touched — no tool row is repointed, which is the point of wrapping the registry.

Give the router its lanes in the profile's own patch layer (~/.dsh/profiles/<profile>/cordis.patch.yml). A patch replaces the targeted row's config, so this is the whole config for the router row:

- id: subagent-model
  config:
    provider: spawn          # the provider whose starts are routed
    scope: labelled          # 'any' asks about workflow phases and Ralph rounds too
    ask: true                # false = never ask, always use `default`
    default: parent          # or a lane label, for the no-dialog paths
    lanes:
      - label: PX13 local
        provider: px13
        model: qwen36
        description: Local 27B on the PX13 gateway. Free; slower first token.
      - label: DeepSeek flash
        provider: deepseek-official
        model: deepseek-v4-flash
        description: Cheapest cloud route.

Then restart the DSH server and hard-refresh the browser.

Updating an installed copy

The profile installs this package from npm (dsh-subagent-model@^0.1.x). To ship a change: run npm test, bump the version, npm publish (whose prepublishOnly runs the tests), then dsh plugin --profile <profile> install and restart the server.

A file: install behaves differently, and the difference bites: pnpm hard-links the package directory, and an editor that replaces a file breaks that link, so the profile silently keeps the previous content while your working tree moves on. If you develop against a file: install, delete profiles/<profile>/node_modules/dsh-subagent-model and re-run the install after every edit.

Configuration

KeyDefaultMeaning
providerspawnThe provider whose starts are routed. Every other provider is untouched.
scopelabelledlabelled asks only about starts carrying a task label (the delegation tool's marker); any asks about every start on that provider.
asktrueWhether to ask before a delegation.
defaultparentWhat the no-dialog paths use: parent, or a lane label.
lanes[]—Optional quick choices offered above the picker's list. Empty is the normal configuration when a model picker answers this question.
lanes[].label—The dialog option, and the exact string an answer is matched on.
lanes[].provider—Provider route for the child.
lanes[].model—Model id for the child.
lanes[].description—Optional line under the option in the dialog.
lanes[].maxTokens—Optional per-child output cap, carried into agentOptions.

Verification & Testing

npm run link:harness   # once: link this machine's harness for the integration tests
npm run test:unit      # decision logic; no harness packages
npm run test:integration  # real dsh-subagent, real Loader, real bundle layers
npm test               # both, under a second

The integration lane is the one that matters for the claims this plugin makes. It mounts the shipped dsh-subagent service and drives it from a different context than the installer (a delegation tool resolves the registry from its own realm, so a same-context test would prove nothing), rewrites the continuable spec, replaces the provider, and disposes the fiber. A second file composes the REAL dsh-base and dsh-web-app patch layers and fails if this package's layer changes any row.

To see it work: dsh --profile <profile> --dump-config shows the row and its lanes and grep -i garden shows nothing. Then delegate something and read the child's own session log — its request/context event names the route the child actually ran on, which is the only claim that counts.

Model, Token, and KV-Cache Effects

  • Nothing is added to any prompt. No tool, no prompt section, no instruction text: the router is host-side only. A session's request prefix is byte-identical with and without it.
  • The parent's prefix cache is untouched. Routing a child changes the child's own requests; the parent's next request reuses its prefix as before.
  • The cost change is the point. A delegation sent to a local route costs nothing at the provider; the same delegation on a cloud route costs what that model charges.
  • The dialog blocks the delegation call. A foreground delegation waits for its child anyway, so nothing is lost there; a continuable/background delegation normally returns a durable child id immediately and now waits until the question is answered.

Known Limitations

  1. Nested delegations cannot ask. A child agent spawning a grandchild is not a runtime root, and ctx.userQuestions.ask refuses human interaction for an agent owned by another live agent. Those delegations take default, reported as one info line — choose a default you are happy for depth ≥ 1.
  2. Scope is a caller's marker, not a caller identity. scope: labelled recognises the delegation tool by the task label it always sends; the workflow engine's children and Ralph's rounds are excluded by the label's absence, which is an observable property of those callers rather than a guarantee about them. scope: any drops the distinction — and then replaces a workflow phase's explicit provider/model with the dialog answer.
  3. One routed provider per mount. provider names one provider; a second routed provider needs a second mount.
  4. "Auto for this session" is process-local. It lives in memory and disappears with the server; a durable record would need a session event type an out-of-repo plugin cannot add.
  5. A lane's route is checked, not proven. The providers are compared against llm.listProviders() once, before the first dialog, and a mismatch is warned about — it does not remove the lane, because a provider list can legitimately be incomplete. A wrong model id inside a valid provider route is not detected at all; the child fails at its first model call.
  6. The continuable path is verified at the spec boundary. The integration test records the spec handed to subagents.startContinuable, because materializing a durable child needs the whole agent spine. What is proven is that the rewrite reaches the method that composes the child.
  7. The prompt-size number is an estimate (4 characters per token). Provider-reported usage exists only after the child ran.

🤝 Contributing

See CONTRIBUTING.md for the five hard rules this plugin is built on, the layout, and how to run the two lanes.

🔗 Links

  • dsh-model-chooser — the model picker that answers this question with a live catalog
  • dsh-cache-guard — the sibling plugin that prices automatic context rewrites
  • dsh-pathfix — the sibling plugin that repairs whitespace-broken path arguments
  • DeepSeek Harness — the harness this plugin extends

License

MIT © loonylabs-dev