@ferris1225/pi-subagents 0.12.0 → 0.13.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/README.md +97 -96
- package/package.json +1 -1
- package/src/config.ts +9 -27
- package/src/index.ts +9 -11
- package/src/setup.ts +2 -26
- package/src/spawn.ts +2 -3
package/README.md
CHANGED
|
@@ -68,48 +68,48 @@ here first.
|
|
|
68
68
|
<summary><code>agents/explore.md</code> — reconnaissance</summary>
|
|
69
69
|
|
|
70
70
|
```markdown
|
|
71
|
-
---
|
|
72
|
-
name: explore
|
|
73
|
-
description: Fast read-only codebase reconnaissance. Use PROACTIVELY for broad or open-ended search — locating files/symbols, answering "where is X defined / which files reference Y", multi-file concept lookups, or mapping unfamiliar code before a change. Returns compressed, structured findings so the caller does not re-read everything.
|
|
74
|
-
tools: read, grep, find, ls, bash
|
|
75
|
-
model: claude-haiku-4-5
|
|
76
|
-
thinking: low
|
|
77
|
-
# Model selection: SPEED over depth. Pick the fastest available model.
|
|
78
|
-
# What matters: fast grep/find/read, structured output. What doesn't: deep reasoning.
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
You are an explore agent: a fast, read-only reconnaissance specialist. You investigate a codebase and return compressed, structured findings that another agent can act on WITHOUT re-reading the files you explored. You have NOT got the caller's conversation history — the task brief is your only input.
|
|
82
|
-
|
|
83
|
-
## Hard constraints
|
|
84
|
-
- You are READ-ONLY. Never create, edit, or delete files; never run mutating commands.
|
|
85
|
-
- Bash is for read-only inspection only: `grep`, `find`, `ls`, `cat`, `git log/show/diff/status`. No installs, builds, or state changes.
|
|
86
|
-
- Assume tool permissions are not perfectly enforceable; keep every command strictly read-only by intent.
|
|
87
|
-
|
|
88
|
-
## When invoked
|
|
89
|
-
1. Orient with `grep`/`find` to locate the relevant code fast. Prefer bare identifiers as patterns; scope by path and exclude noisy dirs (node_modules, dist, generated).
|
|
90
|
-
2. Read KEY SECTIONS, not whole files. After 1-2 greps, read the top match instead of running more greps.
|
|
91
|
-
3. Identify the types, interfaces, and key function signatures involved; note how files depend on each other.
|
|
92
|
-
4. Record exact paths and line ranges so the caller can jump straight in.
|
|
93
|
-
|
|
94
|
-
## Thoroughness (infer from the task, default medium)
|
|
95
|
-
- Quick: targeted lookups, key files only.
|
|
96
|
-
- Medium: follow imports and callers, read critical sections.
|
|
97
|
-
- Thorough: trace dependencies across modules; check tests and types.
|
|
98
|
-
|
|
99
|
-
## Collaboration
|
|
100
|
-
- Your output feeds `worker` (or the main agent directly). Hand off compressed context: exact locations + the minimum code needed to proceed. Flag anything ambiguous so the caller can decide.
|
|
101
|
-
|
|
102
|
-
## Output format
|
|
103
|
-
## Files Retrieved
|
|
104
|
-
1. `path/to/file.ts` (lines 10-50) — what lives here and why it matters
|
|
105
|
-
## Key Code
|
|
106
|
-
Critical types / interfaces / signatures as short code blocks.
|
|
107
|
-
## Architecture
|
|
108
|
-
A brief explanation of how the pieces connect.
|
|
109
|
-
## Start Here
|
|
110
|
-
Which file to look at first, and why.
|
|
111
|
-
|
|
112
|
-
## Quality standards
|
|
71
|
+
---
|
|
72
|
+
name: explore
|
|
73
|
+
description: Fast read-only codebase reconnaissance. Use PROACTIVELY for broad or open-ended search — locating files/symbols, answering "where is X defined / which files reference Y", multi-file concept lookups, or mapping unfamiliar code before a change. Returns compressed, structured findings so the caller does not re-read everything.
|
|
74
|
+
tools: read, grep, find, ls, bash
|
|
75
|
+
model: claude-haiku-4-5
|
|
76
|
+
thinking: low
|
|
77
|
+
# Model selection: SPEED over depth. Pick the fastest available model.
|
|
78
|
+
# What matters: fast grep/find/read, structured output. What doesn't: deep reasoning.
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
You are an explore agent: a fast, read-only reconnaissance specialist. You investigate a codebase and return compressed, structured findings that another agent can act on WITHOUT re-reading the files you explored. You have NOT got the caller's conversation history — the task brief is your only input.
|
|
82
|
+
|
|
83
|
+
## Hard constraints
|
|
84
|
+
- You are READ-ONLY. Never create, edit, or delete files; never run mutating commands.
|
|
85
|
+
- Bash is for read-only inspection only: `grep`, `find`, `ls`, `cat`, `git log/show/diff/status`. No installs, builds, or state changes.
|
|
86
|
+
- Assume tool permissions are not perfectly enforceable; keep every command strictly read-only by intent.
|
|
87
|
+
|
|
88
|
+
## When invoked
|
|
89
|
+
1. Orient with `grep`/`find` to locate the relevant code fast. Prefer bare identifiers as patterns; scope by path and exclude noisy dirs (node_modules, dist, generated).
|
|
90
|
+
2. Read KEY SECTIONS, not whole files. After 1-2 greps, read the top match instead of running more greps.
|
|
91
|
+
3. Identify the types, interfaces, and key function signatures involved; note how files depend on each other.
|
|
92
|
+
4. Record exact paths and line ranges so the caller can jump straight in.
|
|
93
|
+
|
|
94
|
+
## Thoroughness (infer from the task, default medium)
|
|
95
|
+
- Quick: targeted lookups, key files only.
|
|
96
|
+
- Medium: follow imports and callers, read critical sections.
|
|
97
|
+
- Thorough: trace dependencies across modules; check tests and types.
|
|
98
|
+
|
|
99
|
+
## Collaboration
|
|
100
|
+
- Your output feeds `worker` (or the main agent directly). Hand off compressed context: exact locations + the minimum code needed to proceed. Flag anything ambiguous so the caller can decide.
|
|
101
|
+
|
|
102
|
+
## Output format
|
|
103
|
+
## Files Retrieved
|
|
104
|
+
1. `path/to/file.ts` (lines 10-50) — what lives here and why it matters
|
|
105
|
+
## Key Code
|
|
106
|
+
Critical types / interfaces / signatures as short code blocks.
|
|
107
|
+
## Architecture
|
|
108
|
+
A brief explanation of how the pieces connect.
|
|
109
|
+
## Start Here
|
|
110
|
+
Which file to look at first, and why.
|
|
111
|
+
|
|
112
|
+
## Quality standards
|
|
113
113
|
Terse and factual. Exact paths and line numbers. Compress — do not narrate your search process or pad with prose.
|
|
114
114
|
```
|
|
115
115
|
|
|
@@ -119,52 +119,52 @@ Terse and factual. Exact paths and line numbers. Compress — do not narrate you
|
|
|
119
119
|
<summary><code>agents/worker.md</code> — implementation</summary>
|
|
120
120
|
|
|
121
121
|
```markdown
|
|
122
|
-
---
|
|
123
|
-
name: worker
|
|
124
|
-
description: General-purpose implementation agent with full tools in an isolated context. Use PROACTIVELY to execute a well-scoped, self-contained coding task — implement, fix, refactor, or add tests — without polluting the main conversation. Plans internally, then implements and verifies. Give it a complete, self-contained brief.
|
|
125
|
-
model: claude-sonnet-4-5
|
|
126
|
-
thinking: high
|
|
127
|
-
# Model selection: CODING ABILITY + TOOL USE. The primary implementation model —
|
|
128
|
-
# balance quality against cost. No `tools` field => inherits all tools (full capability).
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
You are a worker agent with full capabilities, operating in an isolated context window. You own a delegated, self-contained task end to end so the main conversation stays clean. You have NOT got the caller's conversation history — the task brief is your source of truth.
|
|
132
|
-
|
|
133
|
-
## Standard operating procedure
|
|
134
|
-
Work in phases. Do not skip planning or verification.
|
|
135
|
-
|
|
136
|
-
### Phase 1 — Context
|
|
137
|
-
Read the brief fully. If it references files, read them before editing. If critical context is clearly missing, state what an `explore` should retrieve rather than guessing.
|
|
138
|
-
|
|
139
|
-
### Phase 2 — Plan
|
|
140
|
-
Inspect existing code and conventions first. Form the smallest coherent root-cause change that satisfies the brief. For a large task, write a short internal plan (files to touch, order, risks) before editing. Do not refactor unrelated code or create docs unless the brief asks.
|
|
141
|
-
|
|
142
|
-
### Phase 3 — Implement
|
|
143
|
-
Make the change. Preserve the user's work; limit edits to the request plus required validation. Follow the project's existing error handling, naming, and style.
|
|
144
|
-
|
|
145
|
-
### Phase 4 — Verify
|
|
146
|
-
Run the project's format/build/tests when they exist (e.g. `tsc --noEmit`, the test runner). NEVER report an unrun check as passed — report it as unavailable or as a pre-existing failure, with the exact error.
|
|
147
|
-
|
|
148
|
-
### Phase 5 — Handoff
|
|
149
|
-
Summarize concretely so the caller can verify and, if needed, hand to a `reviewer`.
|
|
150
|
-
|
|
151
|
-
## Collaboration
|
|
152
|
-
- You cannot dispatch sub-agents (children are leaf processes with no `subagent` tool). When the
|
|
153
|
-
brief lacks context that needs broad code discovery, state concretely what an `explore` should
|
|
154
|
-
retrieve for the caller — do not guess.
|
|
155
|
-
- Recommend a `reviewer` pass before the caller reports work done or commits, especially for non-trivial diffs.
|
|
156
|
-
|
|
157
|
-
## Output format
|
|
158
|
-
## Completed
|
|
159
|
-
What was done, in a few lines.
|
|
160
|
-
## Files Changed
|
|
161
|
-
- `path/to/file.ts` — what changed.
|
|
162
|
-
## Verification
|
|
163
|
-
Which checks you ACTUALLY ran and their result (e.g. `tsc --noEmit` clean; `vitest` 12 passed). State explicitly anything you could not run and why.
|
|
164
|
-
## Notes (if any)
|
|
165
|
-
Follow-ups, decisions made, blockers. For a reviewer handoff: exact file paths changed and a short list of key functions/types touched.
|
|
166
|
-
|
|
167
|
-
## Quality standards
|
|
122
|
+
---
|
|
123
|
+
name: worker
|
|
124
|
+
description: General-purpose implementation agent with full tools in an isolated context. Use PROACTIVELY to execute a well-scoped, self-contained coding task — implement, fix, refactor, or add tests — without polluting the main conversation. Plans internally, then implements and verifies. Give it a complete, self-contained brief.
|
|
125
|
+
model: claude-sonnet-4-5
|
|
126
|
+
thinking: high
|
|
127
|
+
# Model selection: CODING ABILITY + TOOL USE. The primary implementation model —
|
|
128
|
+
# balance quality against cost. No `tools` field => inherits all tools (full capability).
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
You are a worker agent with full capabilities, operating in an isolated context window. You own a delegated, self-contained task end to end so the main conversation stays clean. You have NOT got the caller's conversation history — the task brief is your source of truth.
|
|
132
|
+
|
|
133
|
+
## Standard operating procedure
|
|
134
|
+
Work in phases. Do not skip planning or verification.
|
|
135
|
+
|
|
136
|
+
### Phase 1 — Context
|
|
137
|
+
Read the brief fully. If it references files, read them before editing. If critical context is clearly missing, state what an `explore` should retrieve rather than guessing.
|
|
138
|
+
|
|
139
|
+
### Phase 2 — Plan
|
|
140
|
+
Inspect existing code and conventions first. Form the smallest coherent root-cause change that satisfies the brief. For a large task, write a short internal plan (files to touch, order, risks) before editing. Do not refactor unrelated code or create docs unless the brief asks.
|
|
141
|
+
|
|
142
|
+
### Phase 3 — Implement
|
|
143
|
+
Make the change. Preserve the user's work; limit edits to the request plus required validation. Follow the project's existing error handling, naming, and style.
|
|
144
|
+
|
|
145
|
+
### Phase 4 — Verify
|
|
146
|
+
Run the project's format/build/tests when they exist (e.g. `tsc --noEmit`, the test runner). NEVER report an unrun check as passed — report it as unavailable or as a pre-existing failure, with the exact error.
|
|
147
|
+
|
|
148
|
+
### Phase 5 — Handoff
|
|
149
|
+
Summarize concretely so the caller can verify and, if needed, hand to a `reviewer`.
|
|
150
|
+
|
|
151
|
+
## Collaboration
|
|
152
|
+
- You cannot dispatch sub-agents (children are leaf processes with no `subagent` tool). When the
|
|
153
|
+
brief lacks context that needs broad code discovery, state concretely what an `explore` should
|
|
154
|
+
retrieve for the caller — do not guess.
|
|
155
|
+
- Recommend a `reviewer` pass before the caller reports work done or commits, especially for non-trivial diffs.
|
|
156
|
+
|
|
157
|
+
## Output format
|
|
158
|
+
## Completed
|
|
159
|
+
What was done, in a few lines.
|
|
160
|
+
## Files Changed
|
|
161
|
+
- `path/to/file.ts` — what changed.
|
|
162
|
+
## Verification
|
|
163
|
+
Which checks you ACTUALLY ran and their result (e.g. `tsc --noEmit` clean; `vitest` 12 passed). State explicitly anything you could not run and why.
|
|
164
|
+
## Notes (if any)
|
|
165
|
+
Follow-ups, decisions made, blockers. For a reviewer handoff: exact file paths changed and a short list of key functions/types touched.
|
|
166
|
+
|
|
167
|
+
## Quality standards
|
|
168
168
|
Root-cause fixes over patches. No unrelated churn. Honest verification — an unrun check is never a passed check.
|
|
169
169
|
```
|
|
170
170
|
|
|
@@ -257,9 +257,9 @@ main agent
|
|
|
257
257
|
1. The main agent calls `subagent` with a self-contained brief.
|
|
258
258
|
2. The tool returns immediately and ends that foreground tool turn, leaving the editor ready
|
|
259
259
|
for input.
|
|
260
|
-
3. The child process works independently. By default up to four
|
|
261
|
-
|
|
262
|
-
configurable
|
|
260
|
+
3. The child process works independently. By default up to four sub-agents run at once —
|
|
261
|
+
and one parallel call accepts at most four tasks; extra runs queue up to `maxConcurrency`
|
|
262
|
+
(configurable via `/subagents-setup` or `pi-subagents.json`).
|
|
263
263
|
4. On completion or failure, the extension sends a durable result message to the main
|
|
264
264
|
session. That message automatically wakes the main agent, or waits until its current turn
|
|
265
265
|
finishes.
|
|
@@ -331,8 +331,6 @@ agent's default — its frontmatter `thinking`, else the global default). The gl
|
|
|
331
331
|
"proactiveInjection": true,
|
|
332
332
|
"agentScope": "user",
|
|
333
333
|
"maxConcurrency": 4,
|
|
334
|
-
"maxParallelTasks": 8,
|
|
335
|
-
"maxSubagentDepth": 1,
|
|
336
334
|
"maxFixRounds": 2
|
|
337
335
|
}
|
|
338
336
|
```
|
|
@@ -347,9 +345,7 @@ agent's default — its frontmatter `thinking`, else the global default). The gl
|
|
|
347
345
|
| `maxResultLines` | Max lines of a sub-agent result carried in the completion message (default `80`). Longer results are truncated; the full text is written to a temp file whose path is included in the message. |
|
|
348
346
|
| `proactiveInjection` | Whether to add the delegation directive to the main system prompt. |
|
|
349
347
|
| `agentScope` | `user`, `project`, or `both`; controls which user/project agent directories are discovered. |
|
|
350
|
-
| `maxConcurrency` |
|
|
351
|
-
| `maxParallelTasks` | Maximum tasks accepted by one parallel `subagent` call (1–32, default 8). |
|
|
352
|
-
| `maxSubagentDepth` | Depth at which the `subagent` tool is no longer registered (default 1: the main session delegates, children are leaf processes). `0` disables the tool entirely. Read once at extension load. |
|
|
348
|
+
| `maxConcurrency` | Max sub-agent processes running at once (1–16, default 4), and the max tasks one parallel `subagent` call accepts. Extra work waits in the queue. |
|
|
353
349
|
| `maxFixRounds` | Auto-fix rounds when a reviewer returns `REVIEW_FAIL`: the extension dispatches a `worker` (briefed with the review's concrete findings) then a `reviewer` re-review, repeating up to this many times before waking the main agent with the full chain. `0` disables it (the main agent handles fixes itself). Default 2. The reviewer stays read-only and in its own context; the loop is orchestrated by the extension, not by the reviewer. |
|
|
354
350
|
|
|
355
351
|
### Configuration migration
|
|
@@ -360,6 +356,11 @@ The config file migrates itself on load — no manual steps after an upgrade:
|
|
|
360
356
|
holding invalid values) is normalized and saved back with the new fields filled in.
|
|
361
357
|
- **Removed agents** — agents no longer shipped (e.g. the old `plan` agent) are stripped
|
|
362
358
|
from `enabledAgents`, `agentModels`, and `agentThinkingLevels` automatically.
|
|
359
|
+
- **Merged limits** — the pre-0.13 `maxParallelTasks` key is folded into `maxConcurrency`
|
|
360
|
+
(the larger of the two wins) and dropped on the next save.
|
|
361
|
+
- **Removed keys** — `maxSubagentDepth` (0.14) is dropped on load: sub-agent children are
|
|
362
|
+
always leaf processes (the `subagent` tool is excluded from their toolset, with a depth
|
|
363
|
+
marker as defense in depth). To disable delegation entirely, use `"enabledAgents": []`.
|
|
363
364
|
|
|
364
365
|
Model selection uses this precedence:
|
|
365
366
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ferris1225/pi-subagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Focused sub-agent delegation for pi: explore / worker / reviewer agents in isolated context, with proactive dispatch injection and per-agent model selection.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/config.ts
CHANGED
|
@@ -45,21 +45,10 @@ export const MAX_RESULT_LINES_LIMIT = 2000;
|
|
|
45
45
|
|
|
46
46
|
export const CONFIG_FILE_NAME = "pi-subagents.json";
|
|
47
47
|
|
|
48
|
-
/** How many sub-agent processes may run at once. Default: 4. */
|
|
48
|
+
/** How many sub-agent processes may run at once, and how many tasks one parallel `subagent` call may contain. Default: 4. */
|
|
49
49
|
export const DEFAULT_MAX_CONCURRENCY = 4;
|
|
50
50
|
/** Upper bound accepted for maxConcurrency (defensive clamp). */
|
|
51
51
|
export const MAX_CONCURRENCY_LIMIT = 16;
|
|
52
|
-
/** How many tasks a single parallel `subagent` call may contain. Default: 8. */
|
|
53
|
-
export const DEFAULT_MAX_PARALLEL_TASKS = 8;
|
|
54
|
-
/** Upper bound accepted for maxParallelTasks (defensive clamp). */
|
|
55
|
-
export const MAX_PARALLEL_TASKS_LIMIT = 32;
|
|
56
|
-
/**
|
|
57
|
-
* Depth at which the subagent tool stops being available. 1 = the main session
|
|
58
|
-
* delegates and child processes are leaves; 0 disables the tool entirely.
|
|
59
|
-
*/
|
|
60
|
-
export const DEFAULT_MAX_SUBAGENT_DEPTH = 1;
|
|
61
|
-
/** Upper bound accepted for maxSubagentDepth (defensive clamp). */
|
|
62
|
-
export const MAX_SUBAGENT_DEPTH_LIMIT = 4;
|
|
63
52
|
/**
|
|
64
53
|
* How many automatic worker→reviewer fix rounds run when a reviewer returns
|
|
65
54
|
* REVIEW_FAIL before waking the main agent. 0 disables the auto-fix loop
|
|
@@ -93,12 +82,9 @@ export interface SubagentsConfig {
|
|
|
93
82
|
proactiveInjection: boolean;
|
|
94
83
|
/** Which agent directories to discover from. Default: "user". */
|
|
95
84
|
agentScope: AgentScope;
|
|
96
|
-
/** Max sub-agent processes running at once (extra work queues)
|
|
85
|
+
/** Max sub-agent processes running at once (extra work queues) and the max tasks
|
|
86
|
+
* one parallel `subagent` call may contain. Default: 4. */
|
|
97
87
|
maxConcurrency: number;
|
|
98
|
-
/** Max tasks accepted by one parallel `subagent` call. Default: 8. */
|
|
99
|
-
maxParallelTasks: number;
|
|
100
|
-
/** Depth at which the subagent tool is no longer registered. Default: 1. */
|
|
101
|
-
maxSubagentDepth: number;
|
|
102
88
|
/**
|
|
103
89
|
* Auto-fix rounds when a reviewer returns REVIEW_FAIL: the extension dispatches
|
|
104
90
|
* a worker (briefed with the review's concrete findings) then a reviewer
|
|
@@ -119,8 +105,6 @@ export const DEFAULT_CONFIG: SubagentsConfig = {
|
|
|
119
105
|
proactiveInjection: true,
|
|
120
106
|
agentScope: "user",
|
|
121
107
|
maxConcurrency: DEFAULT_MAX_CONCURRENCY,
|
|
122
|
-
maxParallelTasks: DEFAULT_MAX_PARALLEL_TASKS,
|
|
123
|
-
maxSubagentDepth: DEFAULT_MAX_SUBAGENT_DEPTH,
|
|
124
108
|
maxFixRounds: DEFAULT_MAX_FIX_ROUNDS,
|
|
125
109
|
};
|
|
126
110
|
|
|
@@ -166,8 +150,6 @@ export function normalizeConfig(raw: unknown): SubagentsConfig {
|
|
|
166
150
|
proactiveInjection: DEFAULT_CONFIG.proactiveInjection,
|
|
167
151
|
agentScope: DEFAULT_CONFIG.agentScope,
|
|
168
152
|
maxConcurrency: DEFAULT_CONFIG.maxConcurrency,
|
|
169
|
-
maxParallelTasks: DEFAULT_CONFIG.maxParallelTasks,
|
|
170
|
-
maxSubagentDepth: DEFAULT_CONFIG.maxSubagentDepth,
|
|
171
153
|
maxFixRounds: DEFAULT_CONFIG.maxFixRounds,
|
|
172
154
|
};
|
|
173
155
|
|
|
@@ -223,12 +205,12 @@ export function normalizeConfig(raw: unknown): SubagentsConfig {
|
|
|
223
205
|
const maxConcurrency = clampCount(raw.maxConcurrency, MAX_CONCURRENCY_LIMIT);
|
|
224
206
|
if (maxConcurrency !== undefined) config.maxConcurrency = maxConcurrency;
|
|
225
207
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (
|
|
231
|
-
config.
|
|
208
|
+
// Schema migration: maxParallelTasks (pre-0.13) merged into maxConcurrency.
|
|
209
|
+
// Take the larger of the two so an upgraded config never loses capacity it
|
|
210
|
+
// was explicitly given; the old key is dropped on the persisted save.
|
|
211
|
+
const legacyParallelTasks = clampCount(raw.maxParallelTasks, MAX_CONCURRENCY_LIMIT);
|
|
212
|
+
if (legacyParallelTasks !== undefined && legacyParallelTasks > config.maxConcurrency) {
|
|
213
|
+
config.maxConcurrency = legacyParallelTasks;
|
|
232
214
|
}
|
|
233
215
|
|
|
234
216
|
// 0 disables the auto-fix loop (main agent handles fixes itself).
|
package/src/index.ts
CHANGED
|
@@ -167,17 +167,15 @@ export default function (pi: ExtensionAPI): void {
|
|
|
167
167
|
};
|
|
168
168
|
const completionBatcher = createCompletionBatcher<CompletionMessageItem>({ emit: sendCompletionGroup });
|
|
169
169
|
|
|
170
|
-
// Recursion guard: sub-
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
? "disabled by maxSubagentDepth 0 in pi-subagents.json"
|
|
176
|
-
: "disabled in nested sub-agent processes";
|
|
170
|
+
// Recursion guard: sub-agent children are leaf processes. The `subagent` tool is
|
|
171
|
+
// excluded from their toolset at spawn (--exclude-tools); this check is defense
|
|
172
|
+
// in depth so a child can never expose the tool back to its model, even if
|
|
173
|
+
// another extension ignores the depth marker.
|
|
174
|
+
if (currentSubagentDepth() >= 1) {
|
|
177
175
|
pi.registerCommand("subagents-setup", {
|
|
178
|
-
description:
|
|
176
|
+
description: "Configure pi-subagents (unavailable in nested sub-agent processes)",
|
|
179
177
|
handler: async (_args, ctx) => {
|
|
180
|
-
ctx.ui.notify(
|
|
178
|
+
ctx.ui.notify("pi-subagents setup is unavailable in nested sub-agent processes.", "warning");
|
|
181
179
|
},
|
|
182
180
|
});
|
|
183
181
|
return;
|
|
@@ -504,12 +502,12 @@ export default function (pi: ExtensionAPI): void {
|
|
|
504
502
|
// Sub-agents intentionally detach from the foreground turn. This makes the
|
|
505
503
|
// editor available immediately; completion messages later wake the main agent.
|
|
506
504
|
if (params.tasks && params.tasks.length > 0) {
|
|
507
|
-
if (params.tasks.length > config.
|
|
505
|
+
if (params.tasks.length > config.maxConcurrency) {
|
|
508
506
|
return {
|
|
509
507
|
content: [
|
|
510
508
|
{
|
|
511
509
|
type: "text",
|
|
512
|
-
text: `Too many parallel tasks (${params.tasks.length}). Max is ${config.
|
|
510
|
+
text: `Too many parallel tasks (${params.tasks.length}). Max is ${config.maxConcurrency} (configurable via /subagents-setup).`,
|
|
513
511
|
},
|
|
514
512
|
],
|
|
515
513
|
details: makeDetails("parallel", true)([]),
|
package/src/setup.ts
CHANGED
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
DEFAULT_ENABLED_AGENTS,
|
|
17
17
|
DEFAULT_MAX_CONCURRENCY,
|
|
18
18
|
DEFAULT_MAX_FIX_ROUNDS,
|
|
19
|
-
DEFAULT_MAX_PARALLEL_TASKS,
|
|
20
19
|
THINKING_LEVEL_VALUES,
|
|
21
20
|
type AgentScope,
|
|
22
21
|
type SubagentsConfig,
|
|
@@ -196,7 +195,6 @@ async function pickInjection(ctx: ExtensionCommandContext, current: boolean): Pr
|
|
|
196
195
|
|
|
197
196
|
/** Preset steps offered for the two numeric limits (selection-only wizard). */
|
|
198
197
|
const CONCURRENCY_STEPS = [1, 2, 3, 4, 6, 8, 12, 16];
|
|
199
|
-
const PARALLEL_TASK_STEPS = [2, 4, 6, 8, 12, 16, 24, 32];
|
|
200
198
|
/** Preset rounds offered for the auto-fix loop (0 disables it). */
|
|
201
199
|
const FIX_ROUNDS_STEPS = [0, 1, 2, 3, 5];
|
|
202
200
|
|
|
@@ -284,22 +282,13 @@ async function runFullSetup(ctx: ExtensionCommandContext, configPath: string, ba
|
|
|
284
282
|
|
|
285
283
|
const maxConcurrency = await pickCount(
|
|
286
284
|
ctx,
|
|
287
|
-
"Max sub-agents running at once? (extra work queues)",
|
|
285
|
+
"Max sub-agents running at once (and per parallel call)? (extra work queues)",
|
|
288
286
|
CONCURRENCY_STEPS,
|
|
289
287
|
base.maxConcurrency,
|
|
290
288
|
DEFAULT_MAX_CONCURRENCY,
|
|
291
289
|
);
|
|
292
290
|
if (maxConcurrency === undefined) return notifyCancelled(ctx);
|
|
293
291
|
|
|
294
|
-
const maxParallelTasks = await pickCount(
|
|
295
|
-
ctx,
|
|
296
|
-
"Max tasks in one parallel subagent call?",
|
|
297
|
-
PARALLEL_TASK_STEPS,
|
|
298
|
-
base.maxParallelTasks,
|
|
299
|
-
DEFAULT_MAX_PARALLEL_TASKS,
|
|
300
|
-
);
|
|
301
|
-
if (maxParallelTasks === undefined) return notifyCancelled(ctx);
|
|
302
|
-
|
|
303
292
|
const maxFixRounds = await pickCount(
|
|
304
293
|
ctx,
|
|
305
294
|
"Auto-fix rounds when a reviewer returns REQUEST_CHANGES? (0 = main agent handles fixes)",
|
|
@@ -319,8 +308,6 @@ async function runFullSetup(ctx: ExtensionCommandContext, configPath: string, ba
|
|
|
319
308
|
proactiveInjection: injection,
|
|
320
309
|
agentScope: scope,
|
|
321
310
|
maxConcurrency,
|
|
322
|
-
maxParallelTasks,
|
|
323
|
-
maxSubagentDepth: base.maxSubagentDepth,
|
|
324
311
|
maxFixRounds,
|
|
325
312
|
};
|
|
326
313
|
await saveConfig(next, configPath);
|
|
@@ -335,7 +322,6 @@ async function runMenu(ctx: ExtensionCommandContext, configPath: string, config:
|
|
|
335
322
|
"Toggle proactive injection",
|
|
336
323
|
"Change agent scope",
|
|
337
324
|
"Change max concurrent sub-agents",
|
|
338
|
-
"Change max parallel tasks",
|
|
339
325
|
"Change max fix rounds",
|
|
340
326
|
"Full re-setup",
|
|
341
327
|
]);
|
|
@@ -381,23 +367,13 @@ async function runMenu(ctx: ExtensionCommandContext, configPath: string, config:
|
|
|
381
367
|
} else if (choice.startsWith("Change max concurrent")) {
|
|
382
368
|
const maxConcurrency = await pickCount(
|
|
383
369
|
ctx,
|
|
384
|
-
"Max sub-agents running at once? (extra work queues)",
|
|
370
|
+
"Max sub-agents running at once (and per parallel call)? (extra work queues)",
|
|
385
371
|
CONCURRENCY_STEPS,
|
|
386
372
|
config.maxConcurrency,
|
|
387
373
|
DEFAULT_MAX_CONCURRENCY,
|
|
388
374
|
);
|
|
389
375
|
if (maxConcurrency === undefined) return notifyCancelled(ctx);
|
|
390
376
|
next.maxConcurrency = maxConcurrency;
|
|
391
|
-
} else if (choice.startsWith("Change max parallel")) {
|
|
392
|
-
const maxParallelTasks = await pickCount(
|
|
393
|
-
ctx,
|
|
394
|
-
"Max tasks in one parallel subagent call?",
|
|
395
|
-
PARALLEL_TASK_STEPS,
|
|
396
|
-
config.maxParallelTasks,
|
|
397
|
-
DEFAULT_MAX_PARALLEL_TASKS,
|
|
398
|
-
);
|
|
399
|
-
if (maxParallelTasks === undefined) return notifyCancelled(ctx);
|
|
400
|
-
next.maxParallelTasks = maxParallelTasks;
|
|
401
377
|
} else if (choice.startsWith("Change max fix")) {
|
|
402
378
|
const maxFixRounds = await pickCount(
|
|
403
379
|
ctx,
|
package/src/spawn.ts
CHANGED
|
@@ -21,9 +21,8 @@ import type { AgentConfig, AgentSource } from "./agents.ts";
|
|
|
21
21
|
import { DEFAULT_THINKING_LEVEL, type ThinkingLevel } from "./config.ts";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Limits are configurable: see maxConcurrency
|
|
25
|
-
*
|
|
26
|
-
* or pi-subagents.json).
|
|
24
|
+
* Limits are configurable: see maxConcurrency in config.ts (default 4, via
|
|
25
|
+
* /subagents-setup or pi-subagents.json).
|
|
27
26
|
*/
|
|
28
27
|
/** Default thinking level for sub-agents. pi clamps it to the resolved model's support. */
|
|
29
28
|
export const SUBAGENT_THINKING_LEVEL: ThinkingLevel = DEFAULT_THINKING_LEVEL;
|