feat(ui): configure maxParallelToolCalls for factory-created agents
The acp and stdio-agent plugins only forwarded `model` into their created agents, so every factory/ACP deployment was pinned to the agent-loop default parallel cap with no cordis.yml override. Add a `maxParallelToolCalls` config field (positive-integer validated) to both, threaded through the existing per-agent options path — symmetric with `model`.
This commit is contained in:
@@ -15,6 +15,7 @@ It is a **client-driver / UI plugin**, the structured analogue of the readline `
|
||||
| Key | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `model` | — | Model name for created agents (must have a registered adapter). |
|
||||
| `maxParallelToolCalls` | (agent-loop default) | Positive integer cap on tool calls each created agent runs concurrently within one assistant step; `1` is fully serial. |
|
||||
|
||||
(No persona key: `dsh-system-prompt`'s own `persona` config supplies the global default section, so ACP-created agents render it without the bridge carrying prompt text. An agent-scoped same-name section may still shadow that default.)
|
||||
|
||||
|
||||
@@ -248,6 +248,12 @@ function stringArrayContent(
|
||||
export interface AcpConfig {
|
||||
/** Model name for created agents (must have a registered adapter). */
|
||||
model?: string
|
||||
/**
|
||||
* Maximum tool calls each created agent runs concurrently within one assistant
|
||||
* step (a positive integer; the agent loop defaults it when omitted). `1`
|
||||
* preserves fully serial execution.
|
||||
*/
|
||||
maxParallelToolCalls?: number
|
||||
/**
|
||||
* Transport stream override. Production omits this (the plugin wires
|
||||
* `process.stdin`/`process.stdout` via `ndJsonStream`). Tests inject an
|
||||
@@ -260,6 +266,9 @@ export interface AcpConfig {
|
||||
|
||||
export const Config: Schema<AcpConfig> = Schema.object({
|
||||
model: Schema.string(),
|
||||
// A positive integer; a bad value (0, negative, fractional) fails config
|
||||
// validation here rather than being silently dropped from cordis.yml.
|
||||
maxParallelToolCalls: Schema.number().step(1).min(1),
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -1010,12 +1019,13 @@ export function apply(ctx: Context, config: AcpConfig): void {
|
||||
* Build per-agent options from the plugin config, omitting absent fields
|
||||
* (exactOptionalPropertyTypes: never assign `undefined` to an optional key).
|
||||
* Exported for unit coverage of both the present and absent branches.
|
||||
* @param config - the plugin config carrying the optional model name.
|
||||
* @returns the per-agent options, with `model` present only when configured.
|
||||
* @param config - the plugin config carrying the optional model name and parallel cap.
|
||||
* @returns the per-agent options, with each field present only when configured.
|
||||
*/
|
||||
export function agentOptions(config: AcpConfig): { model?: string } {
|
||||
export function agentOptions(config: AcpConfig): { model?: string; maxParallelToolCalls?: number } {
|
||||
return {
|
||||
...config.model !== undefined ? { model: config.model } : {},
|
||||
...config.maxParallelToolCalls !== undefined ? { maxParallelToolCalls: config.maxParallelToolCalls } : {},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -818,5 +818,7 @@ describe('agentOptions', () => {
|
||||
it('includes only the fields present in config', () => {
|
||||
expect(agentOptions({})).toEqual({})
|
||||
expect(agentOptions({ model: 'm' })).toEqual({ model: 'm' })
|
||||
expect(agentOptions({ maxParallelToolCalls: 3 })).toEqual({ maxParallelToolCalls: 3 })
|
||||
expect(agentOptions({ model: 'm', maxParallelToolCalls: 1 })).toEqual({ model: 'm', maxParallelToolCalls: 1 })
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user