@ferris1225/pi-subagents 4.2.5 → 4.2.8
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 +375 -346
- package/agents/executor.md +53 -53
- package/package.json +3 -5
- package/src/agents.ts +237 -237
- package/src/announcements.ts +81 -78
- package/src/dispatch.ts +615 -541
- package/src/durable.ts +517 -510
- package/src/format.ts +181 -165
- package/src/index.ts +102 -100
- package/src/monitor.ts +1 -1
- package/src/prompt.ts +69 -69
- package/src/rpc-run.ts +987 -993
- package/src/runtime.ts +348 -312
- package/src/status.ts +66 -0
- package/src/thread-lifecycle.ts +1341 -1324
- package/src/tools.ts +384 -384
- package/src/widget.ts +268 -266
- package/src/worktree.ts +974 -943
package/README.md
CHANGED
|
@@ -1,346 +1,375 @@
|
|
|
1
|
-
# pi-subagents
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
4
|
-
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
5
|
-
[](./LICENSE)
|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
A managed engineering team for [pi](https://github.com/earendil-works/pi): two
|
|
10
|
-
focused sub-agents, durable threads, and Git worktree
|
|
11
|
-
isolation. You install it once and your main agent delegates on its own.
|
|
12
|
-
|
|
13
|
-
## Why
|
|
14
|
-
|
|
15
|
-
Delegation is supposed to remove coordination work. Most sub-agent launchers stop
|
|
16
|
-
at "spawn a child with a prompt" and leave the hard parts — when to delegate, how
|
|
17
|
-
wide to fan out, what happens when a model dies, how results come
|
|
18
|
-
back — with you. This extension owns them:
|
|
19
|
-
|
|
20
|
-
- The main model delegates without being asked, because a delegation directive is
|
|
21
|
-
always in its system prompt.
|
|
22
|
-
- Dispatching never blocks or ends the main turn, so it can start several runs and
|
|
23
|
-
keep working while they execute.
|
|
24
|
-
- Results deliver themselves. There is no status tool to poll and no lookup step.
|
|
25
|
-
- Parallel writers get their own Git worktrees, so concurrent edits do not collide
|
|
26
|
-
and your index is never touched.
|
|
27
|
-
- Threads keep their context across resume, stop, reload, and crash; a dead model
|
|
28
|
-
hands its session to the current main model instead of losing progress.
|
|
29
|
-
- Crashes, partial starts, and integration failures come back as results with
|
|
30
|
-
recovery records — never as silent hangs.
|
|
31
|
-
|
|
32
|
-
## Install
|
|
33
|
-
|
|
34
|
-
Requires **pi >= 0.84.4** and **Node.js >= 22.19.0**.
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
pi install npm:@ferris1225/pi-subagents
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Open pi and run `/subagents-setup` to choose agents, models, and thinking
|
|
41
|
-
strengths. A fresh install enables every agent on the current main model, and each
|
|
42
|
-
session start points you at the wizard until a config file exists. Then just ask
|
|
43
|
-
for work:
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
Map how authentication works, fix the refresh race, run the tests, and review the diff.
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
The main agent decides when delegation pays off. You can also call the tools
|
|
50
|
-
directly when you want exact control.
|
|
51
|
-
|
|
52
|
-
## The team
|
|
53
|
-
|
|
54
|
-
| Agent | Access | Best for |
|
|
55
|
-
| ------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
-
| `explorer` | Read-only | Broad search, unfamiliar-area mapping, symbol and dependency tracing. Returns a retrieval index — never proof. A single artifact the main agent must fully absorb (one issue, one spec) stays an inline read. |
|
|
57
|
-
| `executor` | Full |
|
|
58
|
-
|
|
59
|
-
Custom roles join them with a Markdown file (see [Custom agents](#custom-agents)).
|
|
60
|
-
|
|
61
|
-
Every child is an isolated leaf pi process with its own context window and no
|
|
62
|
-
memory of your conversation, so the brief is its only input. A good brief carries
|
|
63
|
-
the goal, exact paths, constraints, and expected output — which is what the
|
|
64
|
-
injected delegation guidance produces when the main agent dispatches for you.
|
|
65
|
-
|
|
66
|
-
```text
|
|
67
|
-
You
|
|
68
|
-
└─ pi main agent
|
|
69
|
-
├─ explorer ─── parallel recon, retrieval leads only
|
|
70
|
-
└─ executor ─── one deliverable per child: implement, fix, clean up,
|
|
71
|
-
sync docs, or merge fan-out results → verify → deliver
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Dispatching work
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
// One task
|
|
78
|
-
subagent({
|
|
79
|
-
agent: "executor",
|
|
80
|
-
task: "Fix the cache invalidation bug in src/cache, add regression tests, run the checks.",
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Parallel: as many genuinely independent units as the work has
|
|
84
|
-
subagent({
|
|
85
|
-
tasks: [
|
|
86
|
-
{ agent: "explorer", task: "Trace model fallback from dispatch to completion." },
|
|
87
|
-
{ agent: "executor", task: "Add edge-case tests for config migration." },
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
and
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
● #
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
is
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
1
|
+
# pi-subagents
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
4
|
+
[](https://www.npmjs.com/package/@ferris1225/pi-subagents)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
A managed engineering team for [pi](https://github.com/earendil-works/pi): two
|
|
10
|
+
focused sub-agents, durable threads, and Git worktree
|
|
11
|
+
isolation. You install it once and your main agent delegates on its own.
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
Delegation is supposed to remove coordination work. Most sub-agent launchers stop
|
|
16
|
+
at "spawn a child with a prompt" and leave the hard parts — when to delegate, how
|
|
17
|
+
wide to fan out, what happens when a model dies, how results come
|
|
18
|
+
back — with you. This extension owns them:
|
|
19
|
+
|
|
20
|
+
- The main model delegates without being asked, because a delegation directive is
|
|
21
|
+
always in its system prompt.
|
|
22
|
+
- Dispatching never blocks or ends the main turn, so it can start several runs and
|
|
23
|
+
keep working while they execute.
|
|
24
|
+
- Results deliver themselves. There is no status tool to poll and no lookup step.
|
|
25
|
+
- Parallel writers get their own Git worktrees, so concurrent edits do not collide
|
|
26
|
+
and your index is never touched.
|
|
27
|
+
- Threads keep their context across resume, stop, reload, and crash; a dead model
|
|
28
|
+
hands its session to the current main model instead of losing progress.
|
|
29
|
+
- Crashes, partial starts, and integration failures come back as results with
|
|
30
|
+
recovery records — never as silent hangs.
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
Requires **pi >= 0.84.4** and **Node.js >= 22.19.0**.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pi install npm:@ferris1225/pi-subagents
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Open pi and run `/subagents-setup` to choose agents, models, and thinking
|
|
41
|
+
strengths. A fresh install enables every agent on the current main model, and each
|
|
42
|
+
session start points you at the wizard until a config file exists. Then just ask
|
|
43
|
+
for work:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
Map how authentication works, fix the refresh race, run the tests, and review the diff.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The main agent decides when delegation pays off. You can also call the tools
|
|
50
|
+
directly when you want exact control.
|
|
51
|
+
|
|
52
|
+
## The team
|
|
53
|
+
|
|
54
|
+
| Agent | Access | Best for |
|
|
55
|
+
| ------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `explorer` | Read-only | Broad search, unfamiliar-area mapping, symbol and dependency tracing. Returns a retrieval index — never proof. A single artifact the main agent must fully absorb (one issue, one spec) stays an inline read. |
|
|
57
|
+
| `executor` | Full | A self-contained unit that changes the repository or condenses inputs: implementation, fixes, refactors, tests, evidence-first cleanup, docs/comment sync, or merging a fan-out's results into one brief — carried through verification and a result-only handoff. |
|
|
58
|
+
|
|
59
|
+
Custom roles join them with a Markdown file (see [Custom agents](#custom-agents)).
|
|
60
|
+
|
|
61
|
+
Every child is an isolated leaf pi process with its own context window and no
|
|
62
|
+
memory of your conversation, so the brief is its only input. A good brief carries
|
|
63
|
+
the goal, exact paths, constraints, and expected output — which is what the
|
|
64
|
+
injected delegation guidance produces when the main agent dispatches for you.
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
You
|
|
68
|
+
└─ pi main agent
|
|
69
|
+
├─ explorer ─── parallel recon, retrieval leads only
|
|
70
|
+
└─ executor ─── one deliverable per child: implement, fix, clean up,
|
|
71
|
+
sync docs, or merge fan-out results → verify → deliver
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Dispatching work
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
// One task
|
|
78
|
+
subagent({
|
|
79
|
+
agent: "executor",
|
|
80
|
+
task: "Fix the cache invalidation bug in src/cache, add regression tests, run the checks.",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Parallel: as many genuinely independent units as the work has
|
|
84
|
+
subagent({
|
|
85
|
+
tasks: [
|
|
86
|
+
{ agent: "explorer", task: "Trace model fallback from dispatch to completion." },
|
|
87
|
+
{ agent: "executor", task: "Add edge-case tests for config migration." },
|
|
88
|
+
// Optional per-call reasoning strength for a task that needs less of it
|
|
89
|
+
{ agent: "executor", task: "Run the suite and report failures.", thinking: "low" },
|
|
90
|
+
],
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Breadth is the main agent's call, not a configured limit. There is no per-call
|
|
95
|
+
task cap: put every genuinely independent unit in one `tasks` array. The runtime
|
|
96
|
+
paces execution instead, running a pool of child processes that scales with the
|
|
97
|
+
machine (half its cores, bounded to 4–16) and starting queued runs automatically
|
|
98
|
+
as slots free.
|
|
99
|
+
|
|
100
|
+
Because queueing is pacing rather than refusal, it is always reported as such.
|
|
101
|
+
Dispatch confirmations name each waiting run's real reason — waiting for a free
|
|
102
|
+
process slot, serialized behind the shared-checkout write lane, or already
|
|
103
|
+
starting its child — alongside the slot capacity. A run that waits for the write
|
|
104
|
+
lane releases its slot first, so serialized writers never starve new dispatches.
|
|
105
|
+
|
|
106
|
+
One child owns one coherent deliverable and its files. Dependent work starts only
|
|
107
|
+
after its prerequisite delivers. Verification belongs to whoever did the work:
|
|
108
|
+
every child runs the checks it can and reports exactly which ones ran, and the
|
|
109
|
+
main agent inspects the actual changes before calling anything done.
|
|
110
|
+
|
|
111
|
+
## Parallel edits
|
|
112
|
+
|
|
113
|
+
- Single tasks use your checkout. Every parallel write-capable agent (`executor`
|
|
114
|
+
and custom writers) defaults to a detached Git worktree, so
|
|
115
|
+
parallel writers run at the same time. Worktree mode needs a committed `HEAD`,
|
|
116
|
+
and read-only agents reject it.
|
|
117
|
+
- A role file can pin its own default with `isolation: worktree` or
|
|
118
|
+
`isolation: shared` in the frontmatter. Precedence is an explicit per-dispatch
|
|
119
|
+
`isolation`, then the role's declaration, then the parallel write default.
|
|
120
|
+
- An isolated run's tracked, deleted, untracked, and binary changes integrate
|
|
121
|
+
back exactly once, after the child settles. Nothing is staged and your index is
|
|
122
|
+
untouched.
|
|
123
|
+
- Integration is a three-way merge, so parallel workers that touched disjoint
|
|
124
|
+
files or regions land cleanly even when earlier patches moved the checkout
|
|
125
|
+
underneath them. A genuine overlap leaves conflict markers in the checkout and
|
|
126
|
+
keeps the worktree and patch for you to resolve.
|
|
127
|
+
- Shared-checkout writers serialize through
|
|
128
|
+
one repository lane, so two of them never race. A run waiting there is reported
|
|
129
|
+
as a lane wait, not as slot queueing, and its process slot is already released.
|
|
130
|
+
- Setup and integration failures keep the useful patch and worktree, and record
|
|
131
|
+
where they are in `~/.pi/agent/pi-subagents-recovery.json`. Every later session
|
|
132
|
+
start repeats that notice until you remove the artifacts. When the changes had
|
|
133
|
+
already been applied and only the cleanup failed, the next session start
|
|
134
|
+
removes the retained copy itself and clears the notice.
|
|
135
|
+
|
|
136
|
+
## Threads: resume, stop
|
|
137
|
+
|
|
138
|
+
Every dispatch returns a stable `#id`, which is the handle for the thread tools:
|
|
139
|
+
|
|
140
|
+
| Tool | What it does |
|
|
141
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
142
|
+
| `subagent_control` | `resume` a parked or settled thread with its full retained context, optionally appending a new `objective`. |
|
|
143
|
+
| `subagent_stop` | Destructively cancel, deliver the partial output, and retire the thread. Steering and follow-up messages still queued in the child are dropped so nothing can revive it later. |
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
subagent_control({ action: "resume", id: 7, objective: "Finish the tests." });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
There is deliberately no status, polling, or wait tool. Every result delivers
|
|
150
|
+
itself as a completion that wakes the main model, so a turn never blocks on a
|
|
151
|
+
running subagent — keep working or end the turn, and the completion continues
|
|
152
|
+
it. The one in-turn block is `wait: true` on a dispatch, which holds that call
|
|
153
|
+
until the runs it started settle: the escape hatch for one-shot `pi -p`
|
|
154
|
+
parents, which exit at end of turn and would otherwise never see them. That
|
|
155
|
+
wait runs on no timer and no timeout the model picks: it resolves the instant
|
|
156
|
+
its run settles, a parked run answers immediately with its resume handle, and
|
|
157
|
+
aborting the turn is the escape hatch. Control operations are all bounded, so
|
|
158
|
+
they never hang on a generation that is still settling.
|
|
159
|
+
|
|
160
|
+
A thread stays durable while its work is unfinished. Parked sessions, worktree
|
|
161
|
+
checkpoints, and result excerpts are recorded in a manifest beside your config, so
|
|
162
|
+
a pi reload, restart, or crash interrupts a run into a resumable checkpoint
|
|
163
|
+
instead of losing it, and an isolated thread resumes in the worktree it was
|
|
164
|
+
already working in. Restore happens at load, and everything that answers for a run
|
|
165
|
+
waits for it — `subagent_control`, `subagent_stop`, and a new dispatch before it
|
|
166
|
+
takes an id — so the first call after a reload can never report parked work as
|
|
167
|
+
missing or hand its id to something else.
|
|
168
|
+
|
|
169
|
+
Only interrupted work needs a record, so a thread that completes or fails cleanly
|
|
170
|
+
drops its own. That also means a reload keeps interrupted threads resumable, while
|
|
171
|
+
threads that had already finished keep only their delivered result.
|
|
172
|
+
|
|
173
|
+
## Live status and results
|
|
174
|
+
|
|
175
|
+
The TUI widget renders one line per active run in fixed identity columns —
|
|
176
|
+
status icon, right-aligned `#id`, padded agent name, then the task label — so
|
|
177
|
+
every label starts at the same column, with the live activity dimmed after
|
|
178
|
+
`↳` on its own line and the rest of the telemetry flowing inline after ` · `: the
|
|
179
|
+
worktree badge, the token flow in the footer vocabulary (`↑` input, `↓` output,
|
|
180
|
+
`R`/`W` cache read/write), cost, the full `provider/model` ref, the
|
|
181
|
+
wait state, and an elapsed time that always carries seconds. A live run renders
|
|
182
|
+
two lines: what it is — agent, task, token flow, cost, provider/model, elapsed —
|
|
183
|
+
and, dim under the label column, what it is doing right now:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
● #12 executor src/cache.ts · worktree:a91f3c · ↑5.2k ↓41.0k R210.0k W6.1k $1.9400 · 12m06s
|
|
187
|
+
↳ edit src/auth.ts
|
|
188
|
+
● #15 explorer src/models.ts · ↑1.2k ↓8.4k R31.0k W1.1k $0.0900 · openai/gpt-5-mini · 3m07s
|
|
189
|
+
↳ grep fallback
|
|
190
|
+
○ #23 executor src/config.ts · repo lane
|
|
191
|
+
○ #24 executor ↻ tests/config.test.ts · queued · 5m02s
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Telemetry drops leftmost-first when a row runs out of width (badge, wait
|
|
195
|
+
state, usage, model) while the elapsed survives every width. Queued rows state
|
|
196
|
+
what they actually wait for — `queued` for a free process slot, `repo lane`
|
|
197
|
+
for shared-checkout write serialization, or `starting` — and a resumed thread
|
|
198
|
+
carries a dim `↻` in its agent column with its cumulative time. The widget is
|
|
199
|
+
capped at ten lines: when many runs are live, extra runs collapse into a
|
|
200
|
+
`… +N more` marker so the editor keeps its space.
|
|
201
|
+
|
|
202
|
+
The widget is the detailed surface, but it only pays off while you are looking
|
|
203
|
+
at it. A one-line roll-up in the always-visible footer answers "is anything
|
|
204
|
+
still working?" without opening the widget or asking:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
subagents 2 running · 1 repo lane · 3 done
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
It is count-only, keeps the same wait vocabulary as the widget, disappears when
|
|
211
|
+
nothing is active, and works in RPC hosts as well as the TUI.
|
|
212
|
+
|
|
213
|
+
Completions resume the main agent on their own, with a compact block of at most 40
|
|
214
|
+
lines by default; longer output lands unchanged in a Markdown artifact whose path
|
|
215
|
+
comes with the message, stated as how much was actually cut (`40 of 137 lines
|
|
216
|
+
shown`) and conditioned on the shown lines being insufficient, so the same
|
|
217
|
+
content does not enter the main context twice. Roles write result-only handoffs — outcome, paths,
|
|
218
|
+
verification, unresolved blockers — and the main agent is told to add its
|
|
219
|
+
conclusion rather than restate what you already read. A failed run adds its
|
|
220
|
+
failed-tool diagnostics.
|
|
221
|
+
|
|
222
|
+
Delivery is held while a context compaction is in flight and released once it
|
|
223
|
+
settles — on failure and abort too — so a result a child spent minutes producing
|
|
224
|
+
is never swallowed by the summary that replaces the history.
|
|
225
|
+
|
|
226
|
+
A `wait: true` dispatch streams its progress onto the tool card while it waits,
|
|
227
|
+
and reports the awaited children's token spend as the tool call's own usage, so
|
|
228
|
+
sub-agent cost lands in the footer, `/session`, and RPC session totals. A
|
|
229
|
+
background dispatch returns before its children finish, so it reports no usage
|
|
230
|
+
rather than a fabricated number.
|
|
231
|
+
|
|
232
|
+
## Models, thinking, and tools
|
|
233
|
+
|
|
234
|
+
Each agent runs on the current main model or on one you pick in
|
|
235
|
+
`/subagents-setup`, which labels vision and text-only models. If a selected model
|
|
236
|
+
is missing, rate-limited, or fails at the provider level, the **same retained
|
|
237
|
+
session** continues on the main model, so finished searches, reads, and edits
|
|
238
|
+
survive. Ordinary task failures do not trigger a handoff.
|
|
239
|
+
|
|
240
|
+
Thinking defaults to **Auto**: the role's own preference, clamped to what the
|
|
241
|
+
effective model supports. `/subagents-setup` → _Configure an agent_ also offers a
|
|
242
|
+
manual strength, listing only the levels that model supports. A dispatch can also
|
|
243
|
+
ask for a strength per call with `thinking`, so a quick check and a deep refactor
|
|
244
|
+
do not have to share one static level. Precedence: your manual
|
|
245
|
+
`/subagents-setup` choice > the per-call `thinking` > the role's frontmatter >
|
|
246
|
+
the default, and the winner is still clamped to the effective model. There is no separate
|
|
247
|
+
vision mode — assign a multimodal model and name the image paths in the task.
|
|
248
|
+
|
|
249
|
+
Every dispatch, resume, retry, and fallback snapshots the parent's
|
|
250
|
+
currently active tools. A role with no explicit list inherits the full set. An
|
|
251
|
+
explicit list keeps its pi built-in boundary and gains active extension tools,
|
|
252
|
+
while its shell slot follows the parent: a role file naming `bash` runs
|
|
253
|
+
`powershell` when that is the shell you enabled. When you run both, the child gets
|
|
254
|
+
the one that fits the host — PowerShell on Windows, Bash elsewhere — rather than
|
|
255
|
+
two terminals to choose between. A child never receives a shell you disabled,
|
|
256
|
+
since pi's `--tools` allowlist overrides its own `defaultTools`. Read-only roles
|
|
257
|
+
never gain `edit` or `write`, and all `subagent*` tools are stripped so children
|
|
258
|
+
stay leaves. An empty snapshot starts the child with `--no-tools`.
|
|
259
|
+
|
|
260
|
+
Shell guidance in the shipped roles is portable for the same reason: they reach
|
|
261
|
+
for pi's own `read`/`grep`/`find`/`ls` tools, which behave identically everywhere,
|
|
262
|
+
and keep shell examples to `git` queries instead of POSIX binaries a PowerShell
|
|
263
|
+
child cannot run.
|
|
264
|
+
|
|
265
|
+
## Configuration
|
|
266
|
+
|
|
267
|
+
`/subagents-setup` stays one level deep: enabled agents, plus a model and thinking
|
|
268
|
+
strength per agent. Everything else is config-file only, stored at
|
|
269
|
+
`~/.pi/agent/pi-subagents.json` (following `PI_CODING_AGENT_DIR`):
|
|
270
|
+
|
|
271
|
+
```json
|
|
272
|
+
{
|
|
273
|
+
"enabledAgents": ["explorer", "executor"],
|
|
274
|
+
"knownAgents": ["explorer", "executor"],
|
|
275
|
+
"agentModels": { "explorer": "anthropic/claude-haiku-4-5" },
|
|
276
|
+
"agentThinkingLevels": { "executor": "high" },
|
|
277
|
+
"maxResultLines": 40,
|
|
278
|
+
"agentScope": "user",
|
|
279
|
+
"idleTimeoutSec": 90
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
| Field | Meaning |
|
|
284
|
+
| --------------------- | --------------------------------------------------------------------------------- |
|
|
285
|
+
| `enabledAgents` | Agents available for discovery and delegation. `[]` disables all. |
|
|
286
|
+
| `knownAgents` | Built-ins this config has seen; automatic bookkeeping — never edit it. |
|
|
287
|
+
| `agentModels` | Optional `provider/model-id` per agent; missing = current main model. |
|
|
288
|
+
| `agentThinkingLevels` | Optional manual level per agent; missing = Auto. |
|
|
289
|
+
| `maxResultLines` | Lines kept in a completion message before the artifact takes over. Default `40`. |
|
|
290
|
+
| `agentScope` | Discover `user`, `project`, or `both` agent directories. Default `user`. |
|
|
291
|
+
| `idleTimeoutSec` | Seconds without child RPC output before termination; `0` disables. Default `90`. |
|
|
292
|
+
|
|
293
|
+
The delegation directive is always injected; there is no toggle. Invalid values
|
|
294
|
+
fall back safely, and stale keys — including the former `proactiveInjection`,
|
|
295
|
+
`maxConcurrency`, `maxFixRounds`, and `notifyOnReviewPass` knobs — are dropped
|
|
296
|
+
automatically. Built-in roles a newer package no longer ships (such as the
|
|
297
|
+
retired `worker`/`cleaner`/`documenter`/`synthesizer`/`reviewer` set) are pruned
|
|
298
|
+
from `enabledAgents`, `knownAgents`, and the model/thinking tables at first
|
|
299
|
+
load, so the setup wizard never mixes old and new roles; custom agents are
|
|
300
|
+
untouched. At session
|
|
301
|
+
start, model overrides pi no longer reports are removed with a one-time notice. If
|
|
302
|
+
pi's own session compaction fails mid-thread, a notice surfaces the error and the
|
|
303
|
+
automatic retry instead of failing quietly.
|
|
304
|
+
|
|
305
|
+
Agents shipped by a newer package version turn themselves on at the next
|
|
306
|
+
session: a built-in the config has never seen is adopted into `enabledAgents`
|
|
307
|
+
and follows explorer's configured model and thinking level — the fast lane
|
|
308
|
+
these light roles need — while an agent you disabled stays disabled
|
|
309
|
+
(`knownAgents` is what tells the two cases apart). Enabling a role in
|
|
310
|
+
`/subagents-setup` adopts the same explorer route.
|
|
311
|
+
|
|
312
|
+
## Custom agents
|
|
313
|
+
|
|
314
|
+
Built-ins ship with the package. Add or replace them with Markdown files:
|
|
315
|
+
|
|
316
|
+
- User agents: `~/.pi/agent/agents/`
|
|
317
|
+
- Project agents: the nearest `.pi/agents/` in a trusted project
|
|
318
|
+
- Precedence: project > user > built-in, where the same `name` wins
|
|
319
|
+
|
|
320
|
+
```yaml
|
|
321
|
+
---
|
|
322
|
+
name: explorer
|
|
323
|
+
description: Fast read-only codebase reconnaissance
|
|
324
|
+
thinking: low
|
|
325
|
+
isolation: shared
|
|
326
|
+
tools: read, bash
|
|
327
|
+
---
|
|
328
|
+
…additional system prompt…
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
`description` is the routing line the main model reads, and `thinking` is the
|
|
332
|
+
role's Auto preference, which a wizard choice overrides. `isolation` pins the
|
|
333
|
+
role's default boundary as described under [Parallel edits](#parallel-edits).
|
|
334
|
+
Models come only from `/subagents-setup`; an agent file cannot pin one. An
|
|
335
|
+
explicit `tools` list is the capability boundary, and omitting it inherits the
|
|
336
|
+
parent's complete active set.
|
|
337
|
+
|
|
338
|
+
## Storage and cleanup
|
|
339
|
+
|
|
340
|
+
Everything lives under your pi agent directory, grouped per project. Nothing
|
|
341
|
+
long-lived is written to the OS temp directory, and every class of file has a rule
|
|
342
|
+
that removes it, so this directory does not grow without bound:
|
|
343
|
+
|
|
344
|
+
| Path | Holds | Removed |
|
|
345
|
+
| ------------------------------------------ | ---------------------------------------------------- | ---------------------------------------------------------------- |
|
|
346
|
+
| `pi-subagents.json` | Your configuration | Never — it is yours |
|
|
347
|
+
| `pi-subagents-recovery.json` | Worktree integration and cleanup failures | When the retained patch or worktree it points at is gone |
|
|
348
|
+
| `ferris-pi-subagents/<project>/pi-subagents-threads.json` | One record per interrupted thread | When the thread settles, or after 30 days |
|
|
349
|
+
| `ferris-pi-subagents/<project>/sessions/` | Retained child sessions that a resume continues from | When the pi session that produced it ends, or its owner is gone |
|
|
350
|
+
| `ferris-pi-subagents/<project>/worktrees/` | Isolated checkouts for parallel writers | On integration, or when its owning process is gone |
|
|
351
|
+
| `ferris-pi-subagents/<project>/results/` | Full text of truncated results | After 7 days, or beyond 50 per project |
|
|
352
|
+
| `ferris-pi-subagents/<project>/tmp/` | Child prompt copies and the no-retry policy shim | When its owning process exits |
|
|
353
|
+
| `ferris-pi-subagents/<project>/` | All of the above for one checkout | When the whole directory has been idle for 3 days |
|
|
354
|
+
|
|
355
|
+
Cleanup runs at extension load and is deliberately conservative. A directory goes
|
|
356
|
+
away only when the process that created it is gone and no manifest record still
|
|
357
|
+
claims it, so a live sibling pi instance never loses state and parked work
|
|
358
|
+
outlives its own process by design — a reference from the threads manifest always
|
|
359
|
+
beats an age rule.
|
|
360
|
+
|
|
361
|
+
## Development
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
npm install
|
|
365
|
+
npm run check
|
|
366
|
+
npm test
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
There are no bundled runtime dependencies; pi and TypeBox are peers. The source is
|
|
370
|
+
split by responsibility: dispatch policy, thread lifecycle, RPC
|
|
371
|
+
transport, worktree integration, completion delivery, tools, and TUI status.
|
|
372
|
+
|
|
373
|
+
## License
|
|
374
|
+
|
|
375
|
+
MIT
|