pi-subagents 0.31.0 → 0.32.0
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/CHANGELOG.md +48 -0
- package/README.md +170 -8
- package/package.json +1 -1
- package/skills/pi-subagents/SKILL.md +6 -1
- package/src/agents/agent-management.ts +6 -1
- package/src/agents/agents.ts +55 -11
- package/src/extension/companion-suggestions.ts +359 -0
- package/src/extension/config.ts +27 -4
- package/src/extension/doctor.ts +2 -0
- package/src/extension/fanout-child.ts +1 -0
- package/src/extension/index.ts +69 -4
- package/src/extension/schemas.ts +2 -2
- package/src/intercom/intercom-bridge.ts +25 -1
- package/src/profiles/profiles.ts +637 -0
- package/src/runs/background/async-execution.ts +138 -33
- package/src/runs/background/async-job-tracker.ts +77 -1
- package/src/runs/background/async-resume.ts +11 -13
- package/src/runs/background/async-status.ts +41 -9
- package/src/runs/background/chain-root-attachment.ts +34 -4
- package/src/runs/background/control-channel.ts +227 -0
- package/src/runs/background/run-status.ts +1 -0
- package/src/runs/background/stale-run-reconciler.ts +28 -1
- package/src/runs/background/subagent-runner.ts +459 -113
- package/src/runs/foreground/chain-execution.ts +29 -7
- package/src/runs/foreground/execution.ts +24 -6
- package/src/runs/foreground/subagent-executor.ts +240 -44
- package/src/runs/shared/acceptance.ts +45 -22
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/model-fallback.ts +4 -0
- package/src/runs/shared/nested-events.ts +58 -0
- package/src/runs/shared/parallel-utils.ts +49 -1
- package/src/runs/shared/pi-args.ts +5 -3
- package/src/runs/shared/pi-spawn.ts +52 -20
- package/src/runs/shared/single-output.ts +2 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +3 -2
- package/src/runs/shared/worktree.ts +28 -5
- package/src/shared/artifacts.ts +15 -1
- package/src/shared/fork-context.ts +133 -22
- package/src/shared/types.ts +82 -3
- package/src/shared/utils.ts +99 -14
- package/src/slash/slash-commands.ts +726 -40
- package/src/tui/render.ts +16 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
## [0.32.0] - 2026-07-01
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- Added `subagents.defaultModel` so subagents can have a global default model separate from the parent session model. Thanks to Artem Timofeev (@atimofeev) for #339.
|
|
13
|
+
- Added `/subagent-cost` and `totalChildUsage` run details so parent sessions can inspect aggregate subagent child usage and cost. Thanks to Aaron Ky-Riesenbach (@aaronkyriesenbach) for #343.
|
|
14
|
+
- Added configurable companion package recommendations for `pi-intercom` and `pi-prompt-template-model`, surfaced in session-start transcript messages, `subagent({ action: "list" })`, and `/subagents-doctor`, with `/subagents-companions` hide/show/status controls.
|
|
15
|
+
- Added detached async runner stdout and stderr log files. Thanks to Daniel Mateos Carballares (@danim47c) for #358.
|
|
16
|
+
- Added `totalCost` rollups to foreground single, parallel, and chain run details, including nested foreground subagent costs and compact progress display. Thanks to Clark Everson (@gr3enarr0w) for #345.
|
|
17
|
+
- Added `globalConcurrencyLimit` to cap simultaneously running subagent tasks across parallel groups in a single run. Thanks to Clark Everson (@gr3enarr0w) for #349.
|
|
18
|
+
- Added stable v1 async lifecycle artifact metadata in `status.json`, `events.jsonl`, and result JSON so observability and workflow gates can correlate subagent runs without scraping terminal output. Thanks to Clark Everson (@gr3enarr0w) for #350.
|
|
19
|
+
- Added `PI_SUBAGENT_PI_BINARY` to let wrappers launch child agents through an explicit Pi binary instead of resolving `pi` from `PATH`. Thanks to David Barroso (@dbarrosop) for #341.
|
|
20
|
+
- Added `worktreeBaseDir` and `PI_SUBAGENTS_WORKTREE_DIR` so worktree isolation can use a stable trusted base directory. Thanks to Matt Robenolt (@mattrobenolt) for #185.
|
|
21
|
+
- Added `singleRunOutputBaseDir` so single-agent relative outputs can be routed to a configured artifact directory. Thanks to Oleksii Nikiforov (@NikiforovAll) for #173.
|
|
22
|
+
- Added `maxSubagentSpawnsPerSession` and `PI_SUBAGENT_MAX_SPAWNS_PER_SESSION` to cap total subagent launches in one session. Thanks to @eightHundreds for #239.
|
|
23
|
+
- Enforce `timeoutMs` and `maxRuntimeMs` on async and background subagent runs. The per-launch deadline drives an AbortController that cancels acceptance verification, imported async roots, and fallback retries; direct children get SIGTERM with SIGKILL escalation on a bounded timer; nested descendants get timeout requests distinct from manual interrupt. `timedOut`, `deadlineAt`, and `error` propagate across status, results, and nested summaries. Thanks to @pkese for #361.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Keep generated subagent markdown outputs, progress files, and run artifacts under the project-local `.pi-subagents/` directory by default. Thanks to Carolina (@carolitascl) for #326.
|
|
27
|
+
- Detach foreground subagent runs immediately when a child starts a blocking `contact_supervisor` or `intercom.ask` call, avoiding parent/child intercom deadlocks. Thanks to huarkiou (@huarkiou) for #335.
|
|
28
|
+
- Made child boundary prompt editing instructions tool-agnostic so Codex-style adapters are not told to call unavailable `edit`/`write` tools. Thanks to Artem Timofeev (@atimofeev) for #338.
|
|
29
|
+
- Recursively interrupt active async parallel children and nested async descendants when pausing a background run. Thanks to Vicary (@vicary) for #355.
|
|
30
|
+
- Avoid runtime peer imports from detached async runners while still forwarding the Pi package root when available. Thanks to @aurbina83 for #352 and @huangkun3251 for #342.
|
|
31
|
+
- Fall back to PATH `node` for async runners when the current Node executable path is stale or deleted. Thanks to Richard Hao (@0xRichardH) for #347.
|
|
32
|
+
- Retry fallback models when a zero-exit subagent attempt produces no output, including background async runs, preserve structured-output-only completions, and pre-warm forked session files for parallel children. Thanks to Clark Everson (@gr3enarr0w) for #344.
|
|
33
|
+
- Preserve explicit empty companion suggestion surfaces and keep global companion suggestions disabled when writing package dismissal state.
|
|
34
|
+
- Include bounded async runner stderr tails when stale-run reconciliation marks a startup crash failed. Thanks to Salem Sayed (@salemsayed) for #340.
|
|
35
|
+
- Persist forked child session files when Pi returns a branch path before writing it to disk. Thanks to @trisforrestcam for #174.
|
|
36
|
+
- Pass explicit `thinking: off` through to child model arguments as a `:off` suffix. Thanks to Thomas Dietert (@tdietert) for #147.
|
|
37
|
+
- Sanitize Anthropic signed `thinking` / `redacted_thinking` blocks out of forked child sessions and force child thinking off so fork-context subagents survive signed-thinking transcripts after branching or compaction. Thanks to Thomas Dietert (@tdietert) for #147.
|
|
38
|
+
- Restore queued and running detached async jobs into the widget after restarting Pi. Thanks to Vicary (@vicary) for #362.
|
|
39
|
+
- Fix session-start freeze where restoring active async jobs did O(runs × nested-route-dirs) directory scans over stale terminal runs; `listAsyncRuns` now builds a single nested-route index and filters by state before lookup.
|
|
40
|
+
|
|
41
|
+
## [0.31.1] - 2026-06-25
|
|
42
|
+
|
|
43
|
+
### Added
|
|
44
|
+
- Added `/chain` inline parallel groups with per-step metadata, group options, and tab completion. Thanks to loss-and-quick (@loss-and-quick) for #312.
|
|
45
|
+
- Added subagent profile commands and provider model catalog generation for quota and quality model profiles. Thanks to tencnivel (@tencnivel) for #333.
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- Discover `pi-intercom` installations created by `--extension npm:pi-intercom` under Pi's temporary npm extension cache. Thanks to loss-and-quick (@loss-and-quick) for #336.
|
|
49
|
+
- Made async subagent interrupt, steer, and stop requests portable across platforms that do not support Unix signals. Thanks to AeonDave (@AeonDave) for #332.
|
|
50
|
+
- Hardened profile commands by probing models without tools, rejecting unsafe profile/provider path tokens, and resolving short model IDs and thinking suffixes against the current registry.
|
|
51
|
+
- Limited inline `/chain` acceptance values to levels expressible in slash syntax and kept completion disabled inside shared `--` tasks with literal parentheses.
|
|
52
|
+
|
|
5
53
|
## [0.31.0] - 2026-06-24
|
|
6
54
|
|
|
7
55
|
### Added
|
package/README.md
CHANGED
|
@@ -117,7 +117,21 @@ A simple rule of thumb: use `scout` before you understand the code, `researcher`
|
|
|
117
117
|
|
|
118
118
|
## Changing an agent's model
|
|
119
119
|
|
|
120
|
-
Builtin agents inherit your current Pi default model by default. This keeps new installs from depending on a provider you may not have configured. If you want a role to use a specific model, set an override instead of copying the bundled agent file.
|
|
120
|
+
Builtin agents inherit your current Pi default model by default. This keeps new installs from depending on a provider you may not have configured. If you want every subagent without its own model to use a different default, set `subagents.defaultModel`. If you want a role to use a specific model, set an override instead of copying the bundled agent file.
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"defaultModel": "deepseek-v4-pro",
|
|
125
|
+
"subagents": {
|
|
126
|
+
"defaultModel": "deepseek-v4-flash",
|
|
127
|
+
"agentOverrides": {
|
|
128
|
+
"oracle": {
|
|
129
|
+
"model": "deepseek-v4-pro"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
121
135
|
|
|
122
136
|
For one run, put the override in the command:
|
|
123
137
|
|
|
@@ -141,7 +155,7 @@ For a persistent override, edit settings. This example pins the reviewer everywh
|
|
|
141
155
|
}
|
|
142
156
|
```
|
|
143
157
|
|
|
144
|
-
Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
|
|
158
|
+
Use `~/.pi/agent/settings.json` for a user override or the project config settings file (`.pi/settings.json` in standard Pi) for a project override. `subagents.defaultModel` applies to builtin, package, user, and project agents that do not set `model` in frontmatter. Per-run model overrides and `agentOverrides.<name>.model` still win, and explicit agent frontmatter still wins over the global default. The same `agentOverrides` block can change `tools`, `skills`, inherited context, prompt text, or disable a builtin. Matching user and project agents also receive override fields that their frontmatter leaves unset, so a shared project config agent can keep the persona while local settings choose the model.
|
|
145
159
|
|
|
146
160
|
If your provider rejects model IDs with thinking suffixes, set `subagents.disableThinking: true` in user or project settings. That clears bundled builtin thinking defaults in one place; an explicit higher-precedence `agentOverrides.<name>.thinking` value can opt a role back in.
|
|
147
161
|
|
|
@@ -168,6 +182,10 @@ You can also ask naturally:
|
|
|
168
182
|
Show me the current async runs.
|
|
169
183
|
```
|
|
170
184
|
|
|
185
|
+
Async runs also write machine-readable lifecycle artifacts for observability and workflow gates. For a top-level async run, `details.asyncDir` points at a directory containing `status.json`, `events.jsonl`, `output-<index>.log`, and `subagent-log-<runId>.md`; the final summary is written to Pi's subagent results directory as `<runId>.json`. Nested async runs use the same shape under the nested async root and are discoverable through status projections that read the nested-run registry. These files are append/update artifacts only; interactive foreground behavior is unchanged.
|
|
186
|
+
|
|
187
|
+
The stable v1 status/result fields are `lifecycleArtifactVersion`, `runId`/`id`, `sessionId`, `mode`, `state`, `startedAt`, `lastUpdate`, `endedAt`, `durationMs`, `cwd`, `asyncDir`, `sessionFile`, `outputFile`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `model`/`attemptedModels`/`modelAttempts`, `toolCount`, `turnCount`, and nested `children` when a child is allowed to launch subagents. `events.jsonl` records lifecycle transitions such as `subagent.run.started`, `subagent.step.started`, `subagent.step.completed`/`failed`/`paused`, control attention events, nested interrupt failures, and `subagent.run.completed`; run boundary events include the lifecycle artifact version. Consumers should read these JSON files instead of scraping terminal output; unknown fields and event types should be ignored for forward compatibility.
|
|
188
|
+
|
|
171
189
|
If something feels misconfigured, run:
|
|
172
190
|
|
|
173
191
|
```text
|
|
@@ -218,6 +236,8 @@ Add `autofix` to `/parallel-review` or `/parallel-cleanup` to apply only the syn
|
|
|
218
236
|
pi install npm:pi-intercom
|
|
219
237
|
```
|
|
220
238
|
|
|
239
|
+
When `pi-intercom` is not active, `pi-subagents` may recommend it at session start, in `subagent({ action: "list" })`, and in `/subagents-doctor`. The recommendation is visible to the assistant so it can offer to run the install command or hide the recommendation after you approve that action.
|
|
240
|
+
|
|
221
241
|
Most users do not call `intercom` directly. After `pi-intercom` is installed, `pi-subagents` can automatically give child agents a private coordination channel back to the parent session. The bridge recognizes the normal `pi install npm:pi-intercom` package install as well as legacy local extension checkouts.
|
|
222
242
|
|
|
223
243
|
Use it for work where the child might need a decision instead of guessing:
|
|
@@ -329,13 +349,46 @@ Skip this section until you want exact syntax.
|
|
|
329
349
|
|---------|-------------|
|
|
330
350
|
| `/run <agent> [task]` | Run one agent; omit the task for self-contained agents |
|
|
331
351
|
| `/chain agent1 "task1" -> agent2 "task2"` | Run agents in sequence |
|
|
352
|
+
| `/chain scout "scan" -> (reviewer "A" \| reviewer "B") -> writer "fix"` | Run a chain with a static parallel group inline |
|
|
332
353
|
| `/parallel agent1 "task1" -> agent2 "task2"` | Run agents in parallel |
|
|
333
354
|
| `/run-chain <chainName> -- <task>` | Launch a saved `.chain.md` or `.chain.json` workflow |
|
|
355
|
+
| `/subagent-cost` | Show parent plus child subagent token usage and cost for this session |
|
|
334
356
|
| `/subagents-doctor` | Show read-only setup diagnostics |
|
|
335
357
|
| `/subagents-models [agent]` | Show the runtime-loaded builtin model mapping, optionally filtered to one builtin |
|
|
358
|
+
| `/subagents-profiles` | List saved subagent profiles from `~/.pi/agent/profiles/pi-subagents/` |
|
|
359
|
+
| `/subagents-load-profile <name>` | Replace only `settings.subagents` with a saved profile and optionally switch this session to the profile worker model |
|
|
360
|
+
| `/subagents-refresh-provider-models <provider> [--force]` | Create or refresh the cached provider model catalog |
|
|
361
|
+
| `/subagents-generate-profiles <provider>` | Generate `<provider>.quota.json` and `<provider>.quality.json` profiles |
|
|
362
|
+
| `/subagents-check-profile <name>` | Check a saved profile against the current registry and live model probes |
|
|
336
363
|
|
|
337
364
|
Commands validate agent names locally, support tab completion, and send results back into the conversation.
|
|
338
365
|
|
|
366
|
+
### Profiles and provider model catalogs
|
|
367
|
+
|
|
368
|
+
Profiles are stored under:
|
|
369
|
+
|
|
370
|
+
```text
|
|
371
|
+
~/.pi/agent/profiles/pi-subagents/
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Provider model catalogs are cached under:
|
|
375
|
+
|
|
376
|
+
```text
|
|
377
|
+
~/.pi/agent/profiles/pi-subagents/providers/
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Use the profile workflow like this:
|
|
381
|
+
|
|
382
|
+
```text
|
|
383
|
+
/subagents-refresh-provider-models openai-codex
|
|
384
|
+
/subagents-generate-profiles openai-codex
|
|
385
|
+
/subagents-load-profile openai-codex.quota
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
`/subagents-refresh-provider-models` writes a serialized provider model catalog with observed registry data, simple role-oriented classification, and live probe results from tiny one-shot `pi -p --model ... --no-tools` checks. The cache refreshes when missing or stale; use `--force` to ignore freshness and probe again immediately.
|
|
389
|
+
|
|
390
|
+
`/subagents-generate-profiles` uses the provider catalog to produce quota and quality profiles. `/subagents-check-profile` re-checks each assigned model in a saved profile against the current registry and a live probe so you can detect model removals, auth problems, or stale assignments.
|
|
391
|
+
|
|
339
392
|
### Per-step tasks
|
|
340
393
|
|
|
341
394
|
Use `->` to separate steps and give each step its own task:
|
|
@@ -353,6 +406,37 @@ Both double and single quotes work. You can also use `--` as a delimiter:
|
|
|
353
406
|
|
|
354
407
|
Steps without a task inherit behavior from the execution mode. Chain steps get `{previous}`, the prior step’s output. Parallel steps use the first available task as a fallback.
|
|
355
408
|
|
|
409
|
+
### Inline parallel groups in `/chain`
|
|
410
|
+
|
|
411
|
+
Wrap a group of agents in parentheses and separate them with `|` to fan them out within a single chain step. The group runs all of its tasks concurrently, then the next `->` step continues once they finish:
|
|
412
|
+
|
|
413
|
+
```text
|
|
414
|
+
/chain scout "scan" -> (reviewer "review A" | reviewer "review B") -> writer "fix"
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Notes:
|
|
418
|
+
|
|
419
|
+
- Groups must contain at least two tasks separated by ` | `, each with its own task.
|
|
420
|
+
- Group syntax is only valid between ` -> ` separators, and the group must appear as a complete step.
|
|
421
|
+
- Only a step that *opens* with `(` is a group. Parentheses inside a shared `--` task (e.g. `/chain scout -- inspect auth (backend)`) stay literal text and keep the legacy single-agent behavior.
|
|
422
|
+
- A group is treated as the prior step’s output for the next sequential step.
|
|
423
|
+
- Tab completion suggests agents inside groups — after `(`, after `|`, and on each new `->` step.
|
|
424
|
+
|
|
425
|
+
Add a `[...]` suffix right after the closing `)` to set step-level options on the group:
|
|
426
|
+
|
|
427
|
+
```text
|
|
428
|
+
/chain scout "scan" -> (reviewer "A" | reviewer "B")[concurrency=2,failFast,worktree] -> writer "fix"
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
| Group option | Description |
|
|
432
|
+
|--------------|-------------|
|
|
433
|
+
| `concurrency=N` | Max tasks running at once within the group. |
|
|
434
|
+
| `failFast` | Stop the group as soon as one task fails. |
|
|
435
|
+
| `worktree` | Run each group task in its own git worktree. |
|
|
436
|
+
|
|
437
|
+
Dynamic fanout (`expand` / `collect`) is intentionally not available inline — use the
|
|
438
|
+
`subagent({ chain: [...] })` tool API or a saved `.chain.json` for data-driven fan-out.
|
|
439
|
+
|
|
356
440
|
```text
|
|
357
441
|
/chain scout "analyze auth" -> planner -> worker
|
|
358
442
|
# scout gets "analyze auth"; planner gets scout output; worker gets planner output
|
|
@@ -367,7 +451,7 @@ For a shared task, list agents and place one `--` before the task:
|
|
|
367
451
|
|
|
368
452
|
### Inline per-step config
|
|
369
453
|
|
|
370
|
-
Append `[key=value,...]` to an agent name to override defaults
|
|
454
|
+
Append `[key=value,...]` to an agent name to override defaults. `/chain` applies every key below; `/run` and `/parallel` use the execution-behavior keys (`output`, `outputMode`, `reads`, `model`, `skills`, `progress`) and ignore chain-only metadata such as `as`, `label`, `phase`, `count`, `outputSchema`, and `acceptance`.
|
|
371
455
|
|
|
372
456
|
```text
|
|
373
457
|
/chain scout[output=context.md] "scan code" -> planner[reads=context.md] "analyze auth"
|
|
@@ -377,15 +461,24 @@ Append `[key=value,...]` to an agent name to override defaults for that step:
|
|
|
377
461
|
|
|
378
462
|
| Key | Example | Description |
|
|
379
463
|
|-----|---------|-------------|
|
|
380
|
-
| `output` | `output=context.md` | Write results to a file.
|
|
464
|
+
| `output` | `output=context.md` | Write results to a file. Absolute paths are used as-is. Relative paths in `/run` resolve under `singleRunOutputBaseDir` when configured, otherwise under the run's output artifact directory. Relative paths in `/chain` and `/parallel` live under the chain or parallel run directory. |
|
|
381
465
|
| `outputMode` | `outputMode=file-only` | Return only a concise file reference for saved output instead of the full saved content. Requires `output`; default is `inline`. |
|
|
382
466
|
| `reads` | `reads=a.md+b.md` | Read files before executing. `+` separates multiple paths. |
|
|
383
467
|
| `model` | `model=anthropic/claude-sonnet-4` | Override model for this step. |
|
|
384
468
|
| `skills` | `skills=planning+review` | Override available skills. `+` separates multiple skills. |
|
|
385
469
|
| `progress` | `progress` | Enable progress tracking. |
|
|
470
|
+
| `as` | `as=context` | Name this step’s output so later steps can reference it. |
|
|
471
|
+
| `label` | `label=Recon` | Human-readable label for the step. |
|
|
472
|
+
| `phase` | `phase=analysis` | Group steps into a named phase. |
|
|
473
|
+
| `cwd` | `cwd=packages/api` | Run the step in a subdirectory. |
|
|
474
|
+
| `count` | `count=3` | Fan a group task into N copies (only inside a `( ... )` group). |
|
|
475
|
+
| `outputSchema` | `outputSchema=schema.json` | Validate structured output against a JSON Schema file (path resolved against the session cwd, not an inline step `cwd`). |
|
|
476
|
+
| `acceptance` | `acceptance=checked` | Inline acceptance level: `auto`, `attested`, or `checked`. Use the tool API or saved `.chain.json` for object contracts such as `none`, `verified`, or `reviewed`. |
|
|
386
477
|
|
|
387
478
|
Set `output=false`, `reads=false`, or `skills=false` to disable that behavior explicitly. Do not use `output=false` for file-only returns; use `outputMode=file-only` with an `output` path.
|
|
388
479
|
|
|
480
|
+
Inline `[...]` values must not contain spaces or commas — keep `label`/`phase` to single tokens.
|
|
481
|
+
|
|
389
482
|
### Background and forked runs
|
|
390
483
|
|
|
391
484
|
Add `--bg` to run in the background:
|
|
@@ -449,7 +542,7 @@ Agent locations, lowest to highest priority:
|
|
|
449
542
|
|
|
450
543
|
Project discovery also reads legacy `.agents/**/*.md` files. Nested subdirectories are discovered recursively. `.chain.md` files do not define agents. Installed Pi packages can expose agent directories from either `{"pi-subagents":{"agents":["./agents"]}}` or `{"pi":{"subagents":{"agents":["./agents"]}}}` in their package manifest. Package agents load above builtins and below user/project agents. If both `.agents/` and the project config agents directory define the same parsed runtime agent name, the project config directory wins. Use `agentScope: "user" | "project" | "both"` to control discovery; `both` is the default and project definitions win runtime-name collisions.
|
|
451
544
|
|
|
452
|
-
Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them. They do not pin a provider model; they inherit your current Pi default model unless you set `subagents.agentOverrides.<name>.model`. `oracle` is an advisory reviewer that critiques direction and proposes an execution prompt without editing files. `worker` is the implementation agent for normal tasks and approved oracle handoffs.
|
|
545
|
+
Builtin agents load at the lowest priority, so a user or project agent with the same name overrides them. They do not pin a provider model; they inherit your current Pi default model unless you set `subagents.defaultModel` or `subagents.agentOverrides.<name>.model`. `oracle` is an advisory reviewer that critiques direction and proposes an execution prompt without editing files. `worker` is the implementation agent for normal tasks and approved oracle handoffs.
|
|
453
546
|
|
|
454
547
|
The `researcher` builtin uses `web_search`, `fetch_content`, and `get_search_content`; those require [pi-web-access](https://github.com/nicobailon/pi-web-access):
|
|
455
548
|
|
|
@@ -480,6 +573,8 @@ Example:
|
|
|
480
573
|
|
|
481
574
|
Supported override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `defaultContext`, `disabled`, `skills`, `tools`, and `systemPrompt`. Use `defaultContext: false` in builtin overrides to clear an inherited context default. Project overrides beat user overrides.
|
|
482
575
|
|
|
576
|
+
Set `subagents.defaultModel` to give all subagents without an explicit model their own default model, separate from the parent session model. Per-agent model overrides and agent frontmatter still win.
|
|
577
|
+
|
|
483
578
|
Set `disabled: true` to hide a builtin from runtime discovery and agent-facing `subagent({ action: "list" })` output. For bulk control, set `subagents.disableBuiltins: true` in settings.
|
|
484
579
|
|
|
485
580
|
Set `subagents.disableThinking: true` to clear bundled builtin thinking defaults globally for providers that do not support `:low`, `:medium`, `:high`, or similar model suffixes. A higher-precedence per-agent `thinking` override can opt one builtin back in.
|
|
@@ -905,6 +1000,7 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
905
1000
|
| `clarify` | boolean | true for chains | Show TUI preview/edit flow. |
|
|
906
1001
|
| `agentScope` | `user \| project \| both` | `both` | Agent discovery scope. Project wins on collisions. |
|
|
907
1002
|
| `async` | boolean | false | Background execution. For chains, `clarify: true` explicitly keeps the run foreground for the clarify UI. |
|
|
1003
|
+
| `timeoutMs` / `maxRuntimeMs` | number | none | Optional run-level max runtime in milliseconds for foreground and async/background runs. |
|
|
908
1004
|
| `cwd` | string | runtime cwd | Override working directory. |
|
|
909
1005
|
| `maxOutput` | object | 200KB, 5000 lines | Final output truncation limits. |
|
|
910
1006
|
| `artifacts` | boolean | true | Write debug artifacts. |
|
|
@@ -913,7 +1009,7 @@ Agent definitions are not loaded into context by default. Management actions let
|
|
|
913
1009
|
| `sessionDir` | string | derived | Override session log directory. |
|
|
914
1010
|
| `acceptance` | string/object/false | inferred | Override the run's inferred acceptance gates. Use `"auto"`, `"attested"`, `"checked"`, `"verified"`, `"reviewed"`, or `{ level: "none", reason: "..." }`. |
|
|
915
1011
|
|
|
916
|
-
`context: "fork"` fails fast when the parent session is not persisted, the current leaf is missing, or the branched child session cannot be created.
|
|
1012
|
+
`context: "fork"` fails fast when the parent session is not persisted, the current leaf is missing, or the branched child session cannot be created. When the inherited transcript contains signed Anthropic `thinking` / `redacted_thinking` blocks, `pi-subagents` strips those provider-private blocks from the forked child session and forces the child run's thinking level to `off` so Anthropic does not reject modified signatures after branching or compaction. Forking never silently downgrades to `fresh`. In multi-agent runs that omit `context`, each agent/task/step follows its own `defaultContext`, so a fresh-default scout can run fresh beside a fork-default worker. Pass explicit `context: "fork"` or `context: "fresh"` when you intentionally want one context for every child.
|
|
917
1013
|
|
|
918
1014
|
Use `outputMode: "file-only"` when a saved output may be large and the parent only needs a pointer. The returned text is a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` Failed runs and save errors still return normal inline output for debugging. In chains, later `{previous}` steps receive the same compact reference when the prior step used file-only mode.
|
|
919
1015
|
|
|
@@ -968,6 +1064,8 @@ Requirements:
|
|
|
968
1064
|
- task-level `cwd` overrides must be omitted or match the shared cwd
|
|
969
1065
|
- configured `worktreeSetupHook` must return valid JSON before timeout
|
|
970
1066
|
|
|
1067
|
+
By default, worktrees are created under the system temp directory. Set `worktreeBaseDir` in config, or `PI_SUBAGENTS_WORKTREE_DIR` when config is unset, to put them under a stable trusted directory. Missing base directories are created automatically.
|
|
1068
|
+
|
|
971
1069
|
After a worktree parallel step completes, per-agent diff stats are appended to the output and full patch files are written to artifacts. Worktrees and temp branches are cleaned up in `finally` blocks.
|
|
972
1070
|
|
|
973
1071
|
## Configuration
|
|
@@ -990,6 +1088,22 @@ Makes top-level calls use background execution when the request does not explici
|
|
|
990
1088
|
|
|
991
1089
|
Forces depth-0 single, parallel, and chain runs into background mode and bypasses clarify UI by forcing `clarify: false`. Nested calls keep their own inherited settings.
|
|
992
1090
|
|
|
1091
|
+
### `globalConcurrencyLimit`
|
|
1092
|
+
|
|
1093
|
+
```json
|
|
1094
|
+
{ "globalConcurrencyLimit": 20 }
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
Caps simultaneously running subagent tasks within a single run across top-level parallel tasks, inline chain parallel groups, and dynamic fanout groups. The default is `20`; invalid values are clamped to `1`. Per-step `concurrency` and `parallel.concurrency` still apply, so effective concurrency is the lower of the local cap and the available global slots.
|
|
1098
|
+
|
|
1099
|
+
### `maxSubagentSpawnsPerSession`
|
|
1100
|
+
|
|
1101
|
+
```json
|
|
1102
|
+
{ "maxSubagentSpawnsPerSession": 40 }
|
|
1103
|
+
```
|
|
1104
|
+
|
|
1105
|
+
Caps the total number of child subagent launches allowed during one parent session, including single runs, parallel task counts, static chain steps, and bounded dynamic fanout children. Set `PI_SUBAGENT_MAX_SPAWNS_PER_SESSION` to override the config for a process. The default is `40`; `0` blocks new subagent launches for that session.
|
|
1106
|
+
|
|
993
1107
|
### `parallel`
|
|
994
1108
|
|
|
995
1109
|
```json
|
|
@@ -1011,6 +1125,14 @@ Forces depth-0 single, parallel, and chain runs into background mode and bypasse
|
|
|
1011
1125
|
|
|
1012
1126
|
Session directory precedence is: `params.sessionDir`, then `config.defaultSessionDir`, then a directory derived from the parent session. Sessions are always enabled.
|
|
1013
1127
|
|
|
1128
|
+
### `singleRunOutputBaseDir`
|
|
1129
|
+
|
|
1130
|
+
```json
|
|
1131
|
+
{ "singleRunOutputBaseDir": "~/.pi/subagent-outputs" }
|
|
1132
|
+
```
|
|
1133
|
+
|
|
1134
|
+
Routes relative `output` paths for single-agent `/run` calls under this directory. Absolute per-call or agent output paths are still used as-is. When unset, relative single-run outputs go under the run's output artifact directory instead of the project root.
|
|
1135
|
+
|
|
1014
1136
|
### `maxSubagentDepth`
|
|
1015
1137
|
|
|
1016
1138
|
```json
|
|
@@ -1019,6 +1141,14 @@ Session directory precedence is: `params.sessionDir`, then `config.defaultSessio
|
|
|
1019
1141
|
|
|
1020
1142
|
Controls nested delegation when no inherited `PI_SUBAGENT_MAX_DEPTH` is already in effect. Per-agent `maxSubagentDepth` can tighten the limit for that agent’s child runs, but cannot relax an inherited stricter limit. This applies even to children that explicitly declare `tools: subagent`; at the cap, execution fanout is blocked instead of silently hiding nested work.
|
|
1021
1143
|
|
|
1144
|
+
### `PI_SUBAGENT_PI_BINARY`
|
|
1145
|
+
|
|
1146
|
+
```bash
|
|
1147
|
+
export PI_SUBAGENT_PI_BINARY=/path/to/pi-or-wrapper
|
|
1148
|
+
```
|
|
1149
|
+
|
|
1150
|
+
Overrides the command used to launch child Pi processes. Package wrappers can set this to their own `pi`/agent binary so subagents inherit wrapper flags, environment setup, and bundled resources without relying on `PATH` ordering. Empty or whitespace-only values are ignored.
|
|
1151
|
+
|
|
1022
1152
|
### `intercomBridge`
|
|
1023
1153
|
|
|
1024
1154
|
```json
|
|
@@ -1041,6 +1171,36 @@ Bridge activation also requires `pi-intercom` to be installed and enabled throug
|
|
|
1041
1171
|
|
|
1042
1172
|
The default injected guidance tells children to use `contact_supervisor` with `reason: "need_decision"` when blocked or needing a decision, `reason: "progress_update"` only for meaningful blocked/progress updates, generic `intercom` as fallback plumbing, and avoid routine completion handoffs.
|
|
1043
1173
|
|
|
1174
|
+
### `companionSuggestions`
|
|
1175
|
+
|
|
1176
|
+
```json
|
|
1177
|
+
{
|
|
1178
|
+
"companionSuggestions": {
|
|
1179
|
+
"enabled": true,
|
|
1180
|
+
"packages": {
|
|
1181
|
+
"pi-intercom": {
|
|
1182
|
+
"surfaces": ["session_start", "list", "doctor"]
|
|
1183
|
+
},
|
|
1184
|
+
"pi-prompt-template-model": {
|
|
1185
|
+
"surfaces": ["session_start", "list", "doctor"]
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
Controls recommendations for optional companion packages. `pi-intercom` enables live supervisor decisions, progress updates, and grouped result delivery. `pi-prompt-template-model` makes subagent workflows reusable as prompt templates with model/thinking/skill/subagent frontmatter.
|
|
1193
|
+
|
|
1194
|
+
Use `/subagents-companions status` to inspect recommendation status. Use `/subagents-companions hide pi-intercom workspace` or `/subagents-companions hide pi-prompt-template-model user` to hide a recommendation. Use `/subagents-companions show <package>` to show a workspace recommendation again. Set `companionSuggestions` to `false` to disable all companion recommendations.
|
|
1195
|
+
|
|
1196
|
+
### `worktreeBaseDir`
|
|
1197
|
+
|
|
1198
|
+
```json
|
|
1199
|
+
{ "worktreeBaseDir": "/Users/matt/code/.worktrees/pi-subagents" }
|
|
1200
|
+
```
|
|
1201
|
+
|
|
1202
|
+
Sets the base directory for `worktree: true` runs. Relative paths resolve from the repository root, `~/...` expands to your home directory, and `PI_SUBAGENTS_WORKTREE_DIR` is used when config is unset. The default remains the system temp directory.
|
|
1203
|
+
|
|
1044
1204
|
### `worktreeSetupHook`
|
|
1045
1205
|
|
|
1046
1206
|
```json
|
|
@@ -1070,7 +1230,7 @@ Each chain run creates a user-scoped temp directory like:
|
|
|
1070
1230
|
|
|
1071
1231
|
It may contain files such as `context.md`, `plan.md`, `progress.md`, and `parallel-{stepIndex}/.../output.md`. Directories older than 24 hours are cleaned up on extension startup.
|
|
1072
1232
|
|
|
1073
|
-
Debug artifacts live under `{sessionDir}/subagent-artifacts/` or a user-scoped temp artifact directory. Per task you may see:
|
|
1233
|
+
Debug artifacts live under `{sessionDir}/subagent-artifacts/`, `.pi-subagents/artifacts/` for project-scoped runs, or a user-scoped temp artifact directory. Single-run relative `output` files are saved under `{artifactsDir}/outputs/{runId}/` unless `singleRunOutputBaseDir` is configured. Per task you may see:
|
|
1074
1234
|
|
|
1075
1235
|
- `{runId}_{agent}_input.md`
|
|
1076
1236
|
- `{runId}_{agent}_output.md`
|
|
@@ -1127,7 +1287,7 @@ For `attested` or stricter levels, the child prompt includes a standardized acce
|
|
|
1127
1287
|
|
|
1128
1288
|
## Live progress
|
|
1129
1289
|
|
|
1130
|
-
Foreground runs show compact live progress for single, chain, and parallel modes: current tool, recent output, token counts, duration, activity freshness, current-tool duration, and chain graph metadata when available.
|
|
1290
|
+
Foreground runs show compact live progress for single, chain, and parallel modes: current tool, recent output, token counts, aggregate cost, duration, activity freshness, current-tool duration, and chain graph metadata when available.
|
|
1131
1291
|
|
|
1132
1292
|
Press `Ctrl+O` to expand the full streaming view with complete output per step.
|
|
1133
1293
|
|
|
@@ -1197,6 +1357,8 @@ Then `/take-screenshot https://example.com` switches to Sonnet, delegates to `br
|
|
|
1197
1357
|
|
|
1198
1358
|
For more reusable workflows on top of subagents, including `/chain-prompts` and compare-style prompts such as `/best-of-n`, install `pi-prompt-template-model` separately and copy the examples you want into `~/.pi/agent/prompts/`.
|
|
1199
1359
|
|
|
1360
|
+
When `pi-prompt-template-model` is not active, `pi-subagents` may recommend it at session start, in `subagent({ action: "list" })`, and in `/subagents-doctor`. The recommendation is only a prompt; package installation still requires an explicit user-approved command.
|
|
1361
|
+
|
|
1200
1362
|
## Runtime files
|
|
1201
1363
|
|
|
1202
1364
|
The main runtime files are:
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ Use this skill when the parent orchestrator needs to launch a specialized subage
|
|
|
21
21
|
- **Recon and planning**: use `scout` or `context-builder`, then `planner`
|
|
22
22
|
- **Parallel exploration**: run multiple non-conflicting tasks concurrently
|
|
23
23
|
- **Regular skill specialists**: when discovery shows proactive skill subagent suggestions and the current work is broad enough, launch a small fresh-context fanout that asks one subagent per relevant regularly used skill to apply that skill's perspective to the task
|
|
24
|
-
- **Long-running work**: launch async/background runs and inspect them later
|
|
24
|
+
- **Long-running work**: launch async/background runs and inspect them later; use `timeoutMs` or `maxRuntimeMs` when a foreground or async run needs a hard max runtime
|
|
25
25
|
- **Subagent control**: watch needs-attention signals and soft-interrupt only when a delegated run is genuinely blocked
|
|
26
26
|
- **Agent authoring**: create, update, or override agents and chains for a project
|
|
27
27
|
|
|
@@ -632,6 +632,11 @@ If `pi-prompt-template-model` is installed, additional user prompt templates can
|
|
|
632
632
|
`pi-subagents`. This is useful when a slash command should always run through a
|
|
633
633
|
particular agent or with forked context.
|
|
634
634
|
|
|
635
|
+
If `subagent({ action: "list" })`, `/subagents-doctor`, or a startup message recommends
|
|
636
|
+
`pi-intercom` or `pi-prompt-template-model`, offer to run the shown `pi install npm:<package>`
|
|
637
|
+
command only after user approval. To hide future recommendations, use
|
|
638
|
+
`/subagents-companions hide <package> workspace` or `... user`.
|
|
639
|
+
|
|
635
640
|
## Important Constraints
|
|
636
641
|
|
|
637
642
|
- **Forking requires a persisted parent session.** If the current session does not
|
|
@@ -31,7 +31,7 @@ import { getProjectConfigDir } from "../shared/utils.ts";
|
|
|
31
31
|
|
|
32
32
|
type ManagementAction = "list" | "get" | "models" | "create" | "update" | "delete";
|
|
33
33
|
type ManagementScope = "user" | "project";
|
|
34
|
-
type ManagementContext = Pick<ExtensionContext, "cwd" | "modelRegistry"> & { model?: ExtensionContext["model"]; config?: ExtensionConfig };
|
|
34
|
+
type ManagementContext = Pick<ExtensionContext, "cwd" | "modelRegistry"> & { model?: ExtensionContext["model"]; config?: ExtensionConfig; companionSuggestionLines?: () => string[] };
|
|
35
35
|
|
|
36
36
|
interface ManagementParams {
|
|
37
37
|
action?: string;
|
|
@@ -549,6 +549,7 @@ export function handleList(params: ManagementParams, ctx: ManagementContext): Ag
|
|
|
549
549
|
config: ctx.config?.proactiveSkillSubagents,
|
|
550
550
|
discoverAvailableSkills: () => discoverAvailableSkills(ctx.cwd),
|
|
551
551
|
});
|
|
552
|
+
const companionSuggestions = ctx.companionSuggestionLines?.() ?? [];
|
|
552
553
|
const lines = [
|
|
553
554
|
"Executable agents:",
|
|
554
555
|
...(agents.length
|
|
@@ -558,6 +559,7 @@ export function handleList(params: ManagementParams, ctx: ManagementContext): Ag
|
|
|
558
559
|
"Chains:",
|
|
559
560
|
...(chains.length ? chains.map((c) => `- ${c.name} (${c.source}): ${c.description}`) : ["- (none)"]),
|
|
560
561
|
...(proactiveSuggestions.length ? ["", ...proactiveSuggestions] : []),
|
|
562
|
+
...(companionSuggestions.length ? ["", ...companionSuggestions] : []),
|
|
561
563
|
...(diagnostics.length ? ["", "Chain diagnostics:", ...diagnostics.map((entry) => `- ${entry.filePath}: ${entry.error}`)] : []),
|
|
562
564
|
];
|
|
563
565
|
return result(lines.join("\n"));
|
|
@@ -567,6 +569,9 @@ function formatModelSource(agent: AgentConfig, currentModel: ParentModel | undef
|
|
|
567
569
|
if (agent.override && agent.model !== agent.override.base.model) {
|
|
568
570
|
return `${agent.override.scope} override`;
|
|
569
571
|
}
|
|
572
|
+
if (agent.modelSource?.type === "subagents.defaultModel" && agent.model === agent.modelSource.model) {
|
|
573
|
+
return `${agent.modelSource.scope} defaultModel`;
|
|
574
|
+
}
|
|
570
575
|
if (agent.model) return "builtin agent config";
|
|
571
576
|
if (currentModel) return "inherits current session model";
|
|
572
577
|
return "inherit requested, but no current session model is available";
|
package/src/agents/agents.ts
CHANGED
|
@@ -84,6 +84,13 @@ interface BuiltinAgentOverrideInfo {
|
|
|
84
84
|
base: BuiltinAgentOverrideBase;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
export interface AgentModelSourceInfo {
|
|
88
|
+
type: "subagents.defaultModel";
|
|
89
|
+
scope: "user" | "project";
|
|
90
|
+
path: string;
|
|
91
|
+
model: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
87
94
|
export interface AgentConfig {
|
|
88
95
|
name: string;
|
|
89
96
|
localName?: string;
|
|
@@ -113,10 +120,12 @@ export interface AgentConfig {
|
|
|
113
120
|
disabled?: boolean;
|
|
114
121
|
extraFields?: Record<string, string>;
|
|
115
122
|
override?: BuiltinAgentOverrideInfo;
|
|
123
|
+
modelSource?: AgentModelSourceInfo;
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
interface SubagentSettings {
|
|
119
127
|
overrides: Record<string, BuiltinAgentOverrideConfig>;
|
|
128
|
+
defaultModel?: string;
|
|
120
129
|
disableBuiltins?: boolean;
|
|
121
130
|
disableThinking?: boolean;
|
|
122
131
|
}
|
|
@@ -683,17 +692,50 @@ function readSubagentSettings(filePath: string | null): SubagentSettings {
|
|
|
683
692
|
throw new Error(`Subagent settings in '${filePath}' have invalid 'disableThinking'; expected a boolean.`);
|
|
684
693
|
}
|
|
685
694
|
}
|
|
695
|
+
let defaultModel: string | undefined;
|
|
696
|
+
if ("defaultModel" in subagentsObject) {
|
|
697
|
+
if (typeof subagentsObject.defaultModel === "string" && subagentsObject.defaultModel.trim()) {
|
|
698
|
+
defaultModel = subagentsObject.defaultModel.trim();
|
|
699
|
+
} else {
|
|
700
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultModel'; expected a non-empty string.`);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
686
703
|
|
|
687
704
|
const parsed: Record<string, BuiltinAgentOverrideConfig> = {};
|
|
688
705
|
const agentOverrides = subagentsObject.agentOverrides;
|
|
689
706
|
if (!agentOverrides || typeof agentOverrides !== "object" || Array.isArray(agentOverrides)) {
|
|
690
|
-
return { overrides: parsed, disableBuiltins, disableThinking };
|
|
707
|
+
return { overrides: parsed, defaultModel, disableBuiltins, disableThinking };
|
|
691
708
|
}
|
|
692
709
|
for (const [name, value] of Object.entries(agentOverrides)) {
|
|
693
710
|
const override = parseBuiltinOverrideEntry(name, value, filePath);
|
|
694
711
|
if (override) parsed[name] = override;
|
|
695
712
|
}
|
|
696
|
-
return { overrides: parsed, disableBuiltins, disableThinking };
|
|
713
|
+
return { overrides: parsed, defaultModel, disableBuiltins, disableThinking };
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function resolveSubagentDefaultModel(
|
|
717
|
+
userSettings: SubagentSettings,
|
|
718
|
+
projectSettings: SubagentSettings,
|
|
719
|
+
userSettingsPath: string,
|
|
720
|
+
projectSettingsPath: string | null,
|
|
721
|
+
): AgentModelSourceInfo | undefined {
|
|
722
|
+
if (projectSettingsPath && projectSettings.defaultModel !== undefined) {
|
|
723
|
+
return { type: "subagents.defaultModel", scope: "project", path: projectSettingsPath, model: projectSettings.defaultModel };
|
|
724
|
+
}
|
|
725
|
+
return userSettings.defaultModel !== undefined
|
|
726
|
+
? { type: "subagents.defaultModel", scope: "user", path: userSettingsPath, model: userSettings.defaultModel }
|
|
727
|
+
: undefined;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function applySubagentDefaultModel(agents: AgentConfig[], defaultModel: AgentModelSourceInfo | undefined): AgentConfig[] {
|
|
731
|
+
if (!defaultModel) return agents;
|
|
732
|
+
return agents.map((agent) => {
|
|
733
|
+
if (agent.model !== undefined) return agent;
|
|
734
|
+
const next = { ...agent, model: defaultModel.model, modelSource: defaultModel };
|
|
735
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
736
|
+
if (frontmatterFields) agentFrontmatterFields.set(next, frontmatterFields);
|
|
737
|
+
return next;
|
|
738
|
+
});
|
|
697
739
|
}
|
|
698
740
|
|
|
699
741
|
function applyBuiltinOverride(
|
|
@@ -1241,13 +1283,14 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1241
1283
|
const projectSettingsPath = getProjectAgentSettingsPath(cwd);
|
|
1242
1284
|
const userSettings = scope === "project" ? EMPTY_SUBAGENT_SETTINGS : readSubagentSettings(userSettingsPath);
|
|
1243
1285
|
const projectSettings = scope === "user" ? EMPTY_SUBAGENT_SETTINGS : readSubagentSettings(projectSettingsPath);
|
|
1286
|
+
const defaultModel = resolveSubagentDefaultModel(userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
1244
1287
|
const packageSubagentPaths = collectPackageSubagentPaths(cwd, {
|
|
1245
1288
|
includeUser: scope !== "project",
|
|
1246
1289
|
includeProject: scope !== "user",
|
|
1247
1290
|
});
|
|
1248
1291
|
|
|
1249
1292
|
const builtinAgents = applyBuiltinOverrides(
|
|
1250
|
-
loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin"),
|
|
1293
|
+
applySubagentDefaultModel(loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin"), defaultModel),
|
|
1251
1294
|
userSettings,
|
|
1252
1295
|
projectSettings,
|
|
1253
1296
|
userSettingsPath,
|
|
@@ -1258,7 +1301,7 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1258
1301
|
const userAgentsOld = scope === "project" ? [] : loadAgentsFromDir(userDirOld, "user");
|
|
1259
1302
|
const userAgentsNew = scope === "project" ? [] : loadAgentsFromDir(userDirNew, "user");
|
|
1260
1303
|
const userAgents = applyCustomAgentOverrides(
|
|
1261
|
-
[...userAgentsExtra, ...userAgentsOld, ...userAgentsNew],
|
|
1304
|
+
applySubagentDefaultModel([...userAgentsExtra, ...userAgentsOld, ...userAgentsNew], defaultModel),
|
|
1262
1305
|
userSettings,
|
|
1263
1306
|
projectSettings,
|
|
1264
1307
|
userSettingsPath,
|
|
@@ -1266,13 +1309,13 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1266
1309
|
);
|
|
1267
1310
|
|
|
1268
1311
|
const projectAgents = applyCustomAgentOverrides(
|
|
1269
|
-
scope === "user" ? [] : projectAgentDirs.flatMap((dir) => loadAgentsFromDir(dir, "project")),
|
|
1312
|
+
applySubagentDefaultModel(scope === "user" ? [] : projectAgentDirs.flatMap((dir) => loadAgentsFromDir(dir, "project")), defaultModel),
|
|
1270
1313
|
userSettings,
|
|
1271
1314
|
projectSettings,
|
|
1272
1315
|
userSettingsPath,
|
|
1273
1316
|
projectSettingsPath,
|
|
1274
1317
|
);
|
|
1275
|
-
const packageAgents = packageSubagentPaths.agents.flatMap((dir) => loadAgentsFromDir(dir, "package"));
|
|
1318
|
+
const packageAgents = applySubagentDefaultModel(packageSubagentPaths.agents.flatMap((dir) => loadAgentsFromDir(dir, "package")), defaultModel);
|
|
1276
1319
|
const agents = mergeAgentsForScope(scope, userAgents, projectAgents, builtinAgents, packageAgents)
|
|
1277
1320
|
.filter((agent) => agent.disabled !== true);
|
|
1278
1321
|
|
|
@@ -1302,21 +1345,22 @@ export function discoverAgentsAll(cwd: string): {
|
|
|
1302
1345
|
const projectSettingsPath = getProjectAgentSettingsPath(cwd);
|
|
1303
1346
|
const userSettings = readSubagentSettings(userSettingsPath);
|
|
1304
1347
|
const projectSettings = readSubagentSettings(projectSettingsPath);
|
|
1348
|
+
const defaultModel = resolveSubagentDefaultModel(userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
1305
1349
|
const packageSubagentPaths = collectPackageSubagentPaths(cwd);
|
|
1306
1350
|
|
|
1307
1351
|
const builtin = applyBuiltinOverrides(
|
|
1308
|
-
loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin"),
|
|
1352
|
+
applySubagentDefaultModel(loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin"), defaultModel),
|
|
1309
1353
|
userSettings,
|
|
1310
1354
|
projectSettings,
|
|
1311
1355
|
userSettingsPath,
|
|
1312
1356
|
projectSettingsPath,
|
|
1313
1357
|
);
|
|
1314
1358
|
const user = applyCustomAgentOverrides(
|
|
1315
|
-
[
|
|
1359
|
+
applySubagentDefaultModel([
|
|
1316
1360
|
...extraUserAgentDirs().flatMap((dir) => loadAgentsFromDir(dir, "user")),
|
|
1317
1361
|
...loadAgentsFromDir(userDirOld, "user"),
|
|
1318
1362
|
...loadAgentsFromDir(userDirNew, "user"),
|
|
1319
|
-
],
|
|
1363
|
+
], defaultModel),
|
|
1320
1364
|
userSettings,
|
|
1321
1365
|
projectSettings,
|
|
1322
1366
|
userSettingsPath,
|
|
@@ -1328,7 +1372,7 @@ export function discoverAgentsAll(cwd: string): {
|
|
|
1328
1372
|
if (!packageMap.has(agent.name)) packageMap.set(agent.name, agent);
|
|
1329
1373
|
}
|
|
1330
1374
|
}
|
|
1331
|
-
const packageAgents = Array.from(packageMap.values());
|
|
1375
|
+
const packageAgents = applySubagentDefaultModel(Array.from(packageMap.values()), defaultModel);
|
|
1332
1376
|
const projectMap = new Map<string, AgentConfig>();
|
|
1333
1377
|
for (const dir of projectDirs) {
|
|
1334
1378
|
for (const agent of loadAgentsFromDir(dir, "project")) {
|
|
@@ -1336,7 +1380,7 @@ export function discoverAgentsAll(cwd: string): {
|
|
|
1336
1380
|
}
|
|
1337
1381
|
}
|
|
1338
1382
|
const project = applyCustomAgentOverrides(
|
|
1339
|
-
Array.from(projectMap.values()),
|
|
1383
|
+
applySubagentDefaultModel(Array.from(projectMap.values()), defaultModel),
|
|
1340
1384
|
userSettings,
|
|
1341
1385
|
projectSettings,
|
|
1342
1386
|
userSettingsPath,
|