dsh-subagent-hub 0.10.1 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -17
- package/lib/guard.js +40 -2
- package/lib/index.js +40 -7
- package/lib/prompt.js +25 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/ccsert/dsh-subagent-hub/v0.10.
|
|
2
|
+
<img src="https://raw.githubusercontent.com/ccsert/dsh-subagent-hub/v0.10.2/docs/assets/hero.webp" alt="Subagent Hub — Named roles. Clear routes. Visible models." width="100%">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
6
|
-
<a href="https://github.com/ccsert/dsh-subagent-hub/releases/tag/v0.10.
|
|
7
|
-
<a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
8
|
-
<a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
9
|
-
<a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
6
|
+
<a href="https://github.com/ccsert/dsh-subagent-hub/releases/tag/v0.10.2"><img src="https://img.shields.io/badge/version-0.10.2-66c8ab" alt="Version 0.10.2"></a>
|
|
7
|
+
<a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT license"></a>
|
|
8
|
+
<a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/install.md"><img src="https://img.shields.io/badge/DSH_Desktop-0.12.1-7087ad" alt="Tested with DSH Desktop 0.12.1"></a>
|
|
9
|
+
<a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/CONTRIBUTING.md"><img src="https://img.shields.io/badge/verified-102_unit_%2B_31_runtime-66c8ab" alt="102 unit tests and 31 runtime assertions verified"></a>
|
|
10
10
|
</p>
|
|
11
11
|
|
|
12
|
-
<p align="center"><a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
12
|
+
<p align="center"><a href="https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/README.md">简体中文</a> · <b>English</b></p>
|
|
13
13
|
|
|
14
14
|
# Subagent Hub
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
Uses official `subagent` / `subagent_fork` dispatch, Agent Presets, and conversation UI. Keep your existing main-agent preset.
|
|
19
19
|
|
|
20
|
-
[Install](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
20
|
+
[Install](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/install.md) · [Download a release](https://github.com/ccsert/dsh-subagent-hub/releases/latest) · [Configuration example](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/examples/subagent-hub.yml) · [Changelog](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/CHANGELOG.md) · [Contribute](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/CONTRIBUTING.md)
|
|
21
21
|
|
|
22
22
|
## Features
|
|
23
23
|
|
|
@@ -25,7 +25,7 @@ Uses official `subagent` / `subagent_fork` dispatch, Agent Presets, and conversa
|
|
|
25
25
|
|---|---|
|
|
26
26
|
| **Named roles** | Register official `hub-agent-<id>` presets and dispatch with `agent_preset` |
|
|
27
27
|
| **Model selection catalog** | Provide configured routes, capabilities, purposes, and role instructions to the main agent |
|
|
28
|
-
| **Route guard** |
|
|
28
|
+
| **Route guard** | Check the global child routes before subagent, fork, and Team creation; named roles can narrow that range further |
|
|
29
29
|
| **Per-session concurrency** | Limit child agents in each parent session, alongside DSH's global capacity |
|
|
30
30
|
| **Native settings form** | Edit models, roles, tags, and management options in **Settings → Subagent Hub** |
|
|
31
31
|
| **Request model visibility** | Read the latest provider/model from the child header; expand for full IDs and recorded reasoning effort |
|
|
@@ -34,29 +34,29 @@ Uses official `subagent` / `subagent_fork` dispatch, Agent Presets, and conversa
|
|
|
34
34
|
|
|
35
35
|
**Models and named agents**
|
|
36
36
|
|
|
37
|
-

|
|
38
38
|
|
|
39
39
|
**The latest child request**
|
|
40
40
|
|
|
41
|
-

|
|
42
42
|
|
|
43
|
-
These are the actual plugin components rendered with demo data. They contain no user profile, private conversation, or credentials. See [screenshot provenance](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
43
|
+
These are the actual plugin components rendered with demo data. They contain no user profile, private conversation, or credentials. See [screenshot provenance](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/screenshots.md) for full-size and narrow views. The Hero was generated with [dsh-image-gen](https://github.com/shanliuling/dsh-image-gen).
|
|
44
44
|
|
|
45
45
|
## Quick start
|
|
46
46
|
|
|
47
47
|
Tested with **DSH Desktop 0.12.1 / `@deepseek-ai/dsh` 0.2.1-rc.2**. Configure a working model provider in DSH first.
|
|
48
48
|
|
|
49
|
-
1. Download `dsh-subagent-hub-0.10.
|
|
49
|
+
1. Download `dsh-subagent-hub-0.10.2.tgz` from [Releases](https://github.com/ccsert/dsh-subagent-hub/releases/latest).
|
|
50
50
|
2. Install it from the target profile directory:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
pnpm add /absolute/path/to/dsh-subagent-hub-0.10.
|
|
53
|
+
pnpm add /absolute/path/to/dsh-subagent-hub-0.10.2.tgz
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
3. **Append** `"dsh-subagent-hub"` to `dsh.profile.bundles` in that profile's package manifest. Preserve existing bundles and restart DSH to load the plugin code.
|
|
57
57
|
4. Open **Settings → Subagent Hub**, select models already available in your DSH, and add a role. Enable **Manage the official delegation settings** if you want Hub to synchronize the official allowlists. Save, then start a new conversation.
|
|
58
58
|
|
|
59
|
-
Git checkout installation, profile locations, upgrades, and removal are covered in the [installation guide](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
59
|
+
Git checkout installation, profile locations, upgrades, and removal are covered in the [installation guide](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/install.md). The package is published as [dsh-subagent-hub](https://www.npmjs.com/package/dsh-subagent-hub); fixed GitHub release archives are also available. The Team/inheritance guard requires 0.10.2 or newer.
|
|
60
60
|
|
|
61
61
|
## Minimal configuration
|
|
62
62
|
|
|
@@ -85,6 +85,8 @@ The main agent selects a role based on the task and catalog. When the official t
|
|
|
85
85
|
|
|
86
86
|
## Behavior to keep in mind
|
|
87
87
|
|
|
88
|
+
- **Team context selects history.** In the supported runtime, fresh and fork both inherit the Lead model and have no model-selection input. For a specific child model, use a `subagent` tool whose actual schema exposes model selection. See [Team model routing](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/team-model-routing.md).
|
|
89
|
+
- **Global routes also guard inheritance.** A nonempty `routes` list bounds all three creation tools; out-of-list or unconfirmed models are refused. An empty list retains native inheritance. Existing members and later request rewrites are outside this creation check.
|
|
88
90
|
- **Tags guide decisions.** Tags such as `fast`, `reasoning`, or `free` are maintained by you. Use a role's `routes` for a hard route boundary. Tags do not verify pricing or implement automatic fallback.
|
|
89
91
|
- **The guard runs before dispatch.** Model rewrites performed by other plugins during a later child request are outside this guard. Check those plugins when combining route policies.
|
|
90
92
|
- **Fork follows official capabilities.** The target fork provider does not support an independent `agent_preset`; named roles use `subagent`.
|
|
@@ -102,8 +104,8 @@ bash test.sh # real DSH integration in a temporary DSH_HOME
|
|
|
102
104
|
npm run pack:check # inspect the distributable archive
|
|
103
105
|
```
|
|
104
106
|
|
|
105
|
-
This release is verified by **87 unit tests and 23 real-runtime assertions**. Integration uses scripted model streams and makes no external model calls. CI runs unit, documentation, and package checks. See the [settings acceptance record](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
107
|
+
This release is verified by **87 unit tests and 23 real-runtime assertions**. Integration uses scripted model streams and makes no external model calls. CI runs unit, documentation, and package checks. See the [settings acceptance record](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/ui-acceptance.md) and [model badge acceptance record](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/model-badge-acceptance.md) for scope and limitations. [Team routing verification](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/team-model-routing.md) covers the new creation checks.
|
|
106
108
|
|
|
107
|
-
Issues and PRs are welcome. Read [CONTRIBUTING](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
109
|
+
Issues and PRs are welcome. Read [CONTRIBUTING](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/CONTRIBUTING.md), the [design notes](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/design.md), and the [release guide](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/docs/releasing.md). The previous v0.3.0 architecture remains available at its tag.
|
|
108
110
|
|
|
109
|
-
[MIT License](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.
|
|
111
|
+
[MIT License](https://github.com/ccsert/dsh-subagent-hub/blob/v0.10.2/LICENSE) · Maintained by [ccsert](https://github.com/ccsert)
|
package/lib/guard.js
CHANGED
|
@@ -57,12 +57,47 @@ export function concurrencyVerdict({ toolName, delegationTools, limit, running }
|
|
|
57
57
|
return `${GUARD_PREFIX} 这个会话已有 ${running} 个子 agent 正在运行(上限 ${limit})。等其中一个结束后再派发,或者自己把剩下的工作做完。`
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export const CREATION_TOOLS = ['subagent', 'subagent_fork', 'spawn_teammate']
|
|
61
|
+
|
|
62
|
+
export function modelSelectionAvailable(parameters) {
|
|
63
|
+
const properties = parameters?.properties ?? {}
|
|
64
|
+
return Object.hasOwn(properties, 'provider') && Object.hasOwn(properties, 'model')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check the actual route of every supported creation tool against the configured
|
|
69
|
+
* child allowlist. Tool capabilities decide whether model arguments are effective;
|
|
70
|
+
* extra arguments on a model-less fork/Team tool cannot disguise inheritance.
|
|
71
|
+
*/
|
|
72
|
+
export function creationRouteVerdict({ toolName, arguments: args, parent, catalog, parameters, configured = catalog.routes.size > 0 }) {
|
|
73
|
+
if (!CREATION_TOOLS.includes(toolName) || !configured) return undefined
|
|
74
|
+
const allowed = [...catalog.routes.values()]
|
|
75
|
+
if (allowed.length === 0) return `${GUARD_PREFIX} ${toolName} cannot verify its child model: the configured child route list has no valid routes. Fix the Hub route configuration before delegating.`
|
|
76
|
+
const canSelectModel = modelSelectionAvailable(parameters)
|
|
77
|
+
if (canSelectModel) {
|
|
78
|
+
const provider = typeof args?.provider === 'string' && args.provider !== ''
|
|
79
|
+
const model = typeof args?.model === 'string' && args.model !== ''
|
|
80
|
+
if (provider !== model) return undefined // the native tool reports its pairing error
|
|
81
|
+
}
|
|
82
|
+
const route = effectiveRoute(canSelectModel ? args ?? {} : {}, parent)
|
|
83
|
+
const labels = allowed.map(routeLabel).join(', ')
|
|
84
|
+
if (route !== undefined && allowed.some(allowed => allowed.provider === route.provider && allowed.model === route.model)) return undefined
|
|
85
|
+
const actual = route === undefined ? 'an unconfirmed model' : `${route.provider}/${route.model}`
|
|
86
|
+
const mode = toolName === 'spawn_teammate' ? ` (${args?.context === 'fork' ? 'fork' : 'fresh'})` : ''
|
|
87
|
+
const alternative = canSelectModel
|
|
88
|
+
? 'Choose provider and model from the allowed routes.'
|
|
89
|
+
: toolName === 'spawn_teammate'
|
|
90
|
+
? 'This spawn_teammate schema has no provider/model selector. Both fresh and fork inherit the Lead model; changing context does not choose a different model. Use a delegation tool only if its actual schema exposes model selection, or select an allowed Lead model before using Teams.'
|
|
91
|
+
: `This ${toolName} schema has no provider/model selector and inherits the parent model. Use a delegation tool only if its actual schema exposes model selection, or select an allowed parent model first.`
|
|
92
|
+
return `${GUARD_PREFIX} ${toolName}${mode} would use ${actual}, outside the configured child routes: ${labels}. No child was started. ${alternative}`
|
|
93
|
+
}
|
|
94
|
+
|
|
60
95
|
/**
|
|
61
96
|
* Whether one official delegation call must be rejected.
|
|
62
97
|
* @param {{ arguments?: GuardArguments, parent?: any, catalog: GuardCatalog }} input
|
|
63
98
|
* @returns {string | undefined} a model-readable rejection reason, or undefined to allow.
|
|
64
99
|
*/
|
|
65
|
-
export function guardVerdict({ arguments: args, parent, catalog }) {
|
|
100
|
+
export function guardVerdict({ arguments: args, parent, catalog, canSelectModel = true }) {
|
|
66
101
|
const presetId = args?.agent_preset
|
|
67
102
|
if (typeof presetId !== 'string') return undefined
|
|
68
103
|
const agent = catalog.byPreset.get(presetId)
|
|
@@ -87,7 +122,10 @@ export function guardVerdict({ arguments: args, parent, catalog }) {
|
|
|
87
122
|
const labels = allowed.map(routeLabel).join(', ')
|
|
88
123
|
const explicit = allowed.map(route => route.id).join(', ')
|
|
89
124
|
if (requested.source === 'inherited parent') {
|
|
90
|
-
|
|
125
|
+
const guidance = canSelectModel
|
|
126
|
+
? `Pass \`provider\` and \`model\` together, choosing one of: ${labels} (route ids: ${explicit}).`
|
|
127
|
+
: 'This tool has no provider/model selector. Use a tool whose actual schema supports model selection, or an allowed parent model; do not pass unsupported model arguments.'
|
|
128
|
+
return `${GUARD_PREFIX} named agent "${agent.id}" is limited to routes ${labels}, but the child would inherit the parent route ${requested.provider}/${requested.model}. ${guidance}`
|
|
91
129
|
}
|
|
92
130
|
return `${GUARD_PREFIX} named agent "${agent.id}" is limited to routes ${labels}; requested ${requested.provider}/${requested.model} is not allowed. Choose \`provider\` and \`model\` from: ${labels} (route ids: ${explicit}).`
|
|
93
131
|
}
|
package/lib/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { Service } from '@deepseek-ai/cordis'
|
|
|
17
17
|
import z from '@deepseek-ai/schemastery'
|
|
18
18
|
import { AGENT_PRESET_PREFIX, buildCatalog } from './catalog.js'
|
|
19
19
|
import { deriveAgentPreset } from './presets.js'
|
|
20
|
-
import { GUARD_PREFIX, concurrencyVerdict, guardVerdict } from './guard.js'
|
|
20
|
+
import { CREATION_TOOLS, GUARD_PREFIX, concurrencyVerdict, creationRouteVerdict, guardVerdict, modelSelectionAvailable } from './guard.js'
|
|
21
21
|
import { promptSection } from './prompt.js'
|
|
22
22
|
import { MODEL_SETTINGS_ID, PRESET_PLUGIN, modelSettingsFor, officialSettingsPlan, patchPresetRows, sameAllowedModels } from './official-settings.js'
|
|
23
23
|
|
|
@@ -287,22 +287,34 @@ export default class SubagentHub extends Service {
|
|
|
287
287
|
exposedParameters(scope) {
|
|
288
288
|
const tools = this.ctx.get('tools')
|
|
289
289
|
if (tools === undefined) return undefined
|
|
290
|
+
const independent = []
|
|
290
291
|
for (const name of ['subagent', 'subagent_fork']) {
|
|
291
292
|
const tool = tools.get(name, scope)
|
|
292
293
|
if (tool === undefined) continue
|
|
293
294
|
const properties = tool.parameters?.properties ?? {}
|
|
294
|
-
|
|
295
|
+
independent.push({
|
|
296
|
+
name,
|
|
295
297
|
agentPreset: Object.hasOwn(properties, 'agent_preset'),
|
|
296
298
|
model: Object.hasOwn(properties, 'provider') && Object.hasOwn(properties, 'model'),
|
|
297
|
-
}
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
const teamTool = tools.get('spawn_teammate', scope)
|
|
302
|
+
if (independent.length === 0 && teamTool === undefined) return undefined
|
|
303
|
+
const properties = teamTool?.parameters?.properties ?? {}
|
|
304
|
+
return {
|
|
305
|
+
agentPreset: independent[0]?.agentPreset ?? false,
|
|
306
|
+
model: independent[0]?.model ?? false,
|
|
307
|
+
independent,
|
|
308
|
+
team: teamTool === undefined ? undefined : {
|
|
309
|
+
model: Object.hasOwn(properties, 'provider') && Object.hasOwn(properties, 'model'),
|
|
310
|
+
},
|
|
298
311
|
}
|
|
299
|
-
return undefined
|
|
300
312
|
}
|
|
301
313
|
|
|
302
314
|
sectionText(scope) {
|
|
303
315
|
const params = this.exposedParameters(scope)
|
|
304
316
|
if (params === undefined) return ''
|
|
305
|
-
return promptSection({ catalog: this.catalog, params, limit: read(this.config.maxConcurrent) ?? 0 })
|
|
317
|
+
return promptSection({ catalog: this.catalog, params, limit: read(this.config.maxConcurrent) ?? 0, limitTools: read(this.config.delegationTools) ?? [] })
|
|
306
318
|
}
|
|
307
319
|
|
|
308
320
|
/** Child agents of one Session that are still running, from the start/end ledger. */
|
|
@@ -348,9 +360,30 @@ export default class SubagentHub extends Service {
|
|
|
348
360
|
running: this.runningChildren(exec.agent),
|
|
349
361
|
})
|
|
350
362
|
if (busy !== undefined) return Promise.resolve({ kind: 'deny', reason: busy })
|
|
351
|
-
|
|
352
|
-
|
|
363
|
+
let args = exec.arguments
|
|
364
|
+
let canSelectModel = true
|
|
365
|
+
if (CREATION_TOOLS.includes(exec.name)) {
|
|
366
|
+
const tool = this.ctx.get('tools')?.get(exec.name, exec.agent)
|
|
367
|
+
const reason = creationRouteVerdict({
|
|
368
|
+
toolName: exec.name,
|
|
369
|
+
arguments: args,
|
|
370
|
+
parent: exec.agent,
|
|
371
|
+
catalog: this.catalog,
|
|
372
|
+
parameters: tool?.parameters,
|
|
373
|
+
configured: (read(this.config.routes) ?? []).length > 0,
|
|
374
|
+
})
|
|
375
|
+
if (reason !== undefined) return Promise.resolve({ kind: 'deny', reason })
|
|
376
|
+
canSelectModel = modelSelectionAvailable(tool?.parameters)
|
|
377
|
+
if (!canSelectModel) args = { ...args, provider: undefined, model: undefined }
|
|
378
|
+
}
|
|
379
|
+
if (exec.name !== 'spawn_teammate') {
|
|
380
|
+
const reason = guardVerdict({ arguments: args, parent: exec.agent, catalog: this.catalog, canSelectModel })
|
|
381
|
+
if (reason !== undefined) return Promise.resolve({ kind: 'deny', reason })
|
|
382
|
+
}
|
|
353
383
|
} catch (error) {
|
|
384
|
+
if (CREATION_TOOLS.includes(exec.name)) {
|
|
385
|
+
return Promise.resolve({ kind: 'deny', reason: `${GUARD_PREFIX} ${exec.name} could not verify its model against the Hub child routes. No child was started; check the route configuration and tool availability.` })
|
|
386
|
+
}
|
|
354
387
|
this.ctx.logger?.warn?.(`${PACKAGE}: route guard skipped one call: ${String(error?.message ?? error)}`)
|
|
355
388
|
}
|
|
356
389
|
return next()
|
package/lib/prompt.js
CHANGED
|
@@ -7,7 +7,8 @@ import { allowedModels, routeLabel, routeSummary } from './router.js'
|
|
|
7
7
|
* @typedef {import('./router.js').Route} Route
|
|
8
8
|
* @typedef {import('./guard.js').GuardAgent & { description: string, needs?: string[] }} PromptAgent
|
|
9
9
|
* @typedef {{ routes: Map<string, Route>, agents: PromptAgent[], tags: string[], problems: string[] }} PromptCatalog
|
|
10
|
-
* @typedef {{ agentPreset: boolean, model: boolean }}
|
|
10
|
+
* @typedef {{ name: string, agentPreset: boolean, model: boolean }} DelegationInputs
|
|
11
|
+
* @typedef {{ agentPreset: boolean, model: boolean, independent?: DelegationInputs[], team?: { model: boolean } }} PromptParameters
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -16,11 +17,25 @@ import { allowedModels, routeLabel, routeSummary } from './router.js'
|
|
|
16
17
|
* @param {{ catalog: PromptCatalog, params: PromptParameters, limit?: number }} input
|
|
17
18
|
* @returns {string} section markdown, or '' when there is nothing to say.
|
|
18
19
|
*/
|
|
19
|
-
export function promptSection({ catalog, params, limit = 0 }) {
|
|
20
|
+
export function promptSection({ catalog, params, limit = 0, limitTools = ['subagent', 'subagent_fork'] }) {
|
|
20
21
|
const { agents, routes, tags, problems } = catalog
|
|
21
22
|
if (agents.length === 0 && routes.size === 0) return ''
|
|
22
23
|
const lines = ['## Choosing a subagent']
|
|
23
|
-
|
|
24
|
+
if (params.team !== undefined && params.independent?.length === 0) {
|
|
25
|
+
lines.push('This session exposes Agent Teams without an independent subagent creation tool. The named-agent catalog is informational here; use only the inputs present on the visible tool.')
|
|
26
|
+
} else {
|
|
27
|
+
lines.push(guidance(params))
|
|
28
|
+
}
|
|
29
|
+
if (params.team !== undefined) {
|
|
30
|
+
if (params.team.model) {
|
|
31
|
+
lines.push('`spawn_teammate` exposes model selection in this composition; choose provider and model from the configured child routes.')
|
|
32
|
+
} else {
|
|
33
|
+
lines.push('`spawn_teammate` has no `provider`, `model`, or `agent_preset` input in this runtime. Both `context=fresh` and `context=fork` inherit the Lead model; context selects history, not a different model. The Hub rejects a teammate whose inherited model is outside the configured child routes.')
|
|
34
|
+
const alternatives = (params.independent ?? []).filter(tool => tool.model).map(tool => `\`${tool.name}\``)
|
|
35
|
+
if (alternatives.length > 0) lines.push(`For an explicit child model requirement, use ${alternatives.join(' or ')} with the provider/model inputs its schema exposes.`)
|
|
36
|
+
else lines.push('No visible independent delegation tool exposes model selection. If the inherited model cannot satisfy the requested model requirement, explain this limitation before delegating; do not start a different model and apologize afterwards.')
|
|
37
|
+
}
|
|
38
|
+
}
|
|
24
39
|
if (agents.length > 0) {
|
|
25
40
|
lines.push('', 'Named agents:')
|
|
26
41
|
for (const agent of agents) {
|
|
@@ -39,11 +54,17 @@ export function promptSection({ catalog, params, limit = 0 }) {
|
|
|
39
54
|
lines.push(`- \`${routeLabel(route)}\`${tagsPart}${notePart}`)
|
|
40
55
|
}
|
|
41
56
|
if (tags.length > 0) lines.push(`Capability tags: ${tags.map(tag => `\`${tag}\``).join(', ')}.`)
|
|
57
|
+
lines.push('The configured child route list applies to `subagent`, `subagent_fork`, and `spawn_teammate`, including inherited models. If the parent model is not listed, use a tool that actually exposes provider/model to select an allowed child route.')
|
|
42
58
|
const restricted = agents.some(agent => (agent.routes?.length ?? 0) > 0)
|
|
43
59
|
if (restricted) lines.push('When a named agent lists routes, the child `provider`/`model` must be one of that agent\'s routes; any other route is rejected before the child starts.')
|
|
44
60
|
}
|
|
45
61
|
if (limit > 0) {
|
|
46
|
-
|
|
62
|
+
if (params.team !== undefined) {
|
|
63
|
+
const covered = (params.independent ?? []).filter(tool => limitTools.includes(tool.name)).map(tool => `\`${tool.name}\``)
|
|
64
|
+
if (covered.length > 0) lines.push('', `The Hub per-session concurrency cap is ${limit}, enforced on ${covered.join(', ')}. Team creation follows the native Team capacity setting.`)
|
|
65
|
+
} else {
|
|
66
|
+
lines.push('', `At most ${limit} child agents may run at the same time in one Session; a delegation beyond that is refused, so wait for one to finish instead of queueing more.`)
|
|
67
|
+
}
|
|
47
68
|
}
|
|
48
69
|
if (problems.length > 0) lines.push('', `Ignored configuration problems: ${problems.join('; ')}`)
|
|
49
70
|
return lines.join('\n')
|
package/package.json
CHANGED