@ferris1225/pi-subagents 4.3.9 → 4.3.10
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 +24 -0
- package/README.md +100 -117
- package/package.json +12 -10
- package/src/configuration/setup.ts +16 -14
- package/src/delegation/agents.ts +1 -1
- package/src/delegation/dispatch.ts +15 -20
- package/src/delegation/phase-scope.ts +7 -37
- package/src/delegation/prompt.ts +16 -27
- package/src/execution/rpc-control.ts +2 -29
- package/src/execution/rpc-run.ts +29 -30
- package/src/execution/spawn.ts +21 -20
- package/src/isolation/temp-hygiene.ts +7 -9
- package/src/isolation/worktree.ts +13 -88
- package/src/lifecycle/durable.ts +6 -8
- package/src/lifecycle/runtime.ts +23 -70
- package/src/lifecycle/thread-lifecycle.ts +56 -459
- package/src/lifecycle/thread-restore.ts +13 -35
- package/src/lifecycle/thread-shared.ts +5 -65
- package/src/lifecycle/tools.ts +86 -251
- package/src/presentation/announcements.ts +1 -1
- package/src/presentation/format.ts +6 -16
- package/src/presentation/monitor.ts +0 -91
- package/src/presentation/widget.ts +7 -17
- package/src/execution/session-fork.ts +0 -86
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,30 @@ Published versions of `@ferris1225/pi-subagents`. Unpublished numbers
|
|
|
4
4
|
(`4.2.3`, `4.2.6`, `4.2.9`–`4.2.11`) never shipped on npm; their changes
|
|
5
5
|
landed in the next published release.
|
|
6
6
|
|
|
7
|
+
## 4.3.10
|
|
8
|
+
|
|
9
|
+
- Add read-only `subagent_status`: list current-session runs or inspect an exact id,
|
|
10
|
+
including progress, elapsed time, terminal diagnostics, and retained artifact paths.
|
|
11
|
+
Runtime facts use Pi's existing `details.runs`; children do not need strict JSON reports.
|
|
12
|
+
- Remove `subagent_control` and all steer/park/resume entry points, continuation
|
|
13
|
+
admission, session forking, and resume widget markers. Main handles failed or
|
|
14
|
+
incomplete phases; new deliverables get new briefs. Dispatch, automatic completion
|
|
15
|
+
delivery, destructive stop, RPC cancellation, and manual worktree recovery remain.
|
|
16
|
+
- Keep interrupted worktree edits even when the retained Pi session file is missing.
|
|
17
|
+
Manual recovery no longer depends on model context; managed-path validation and
|
|
18
|
+
index-preserving Git integration stay intact.
|
|
19
|
+
- Record child exits before RPC settlement with their exit code or signal instead
|
|
20
|
+
of returning only partial output. Clear stale provider errors after successful Pi
|
|
21
|
+
retries, expose missing diagnostic evidence explicitly, and keep individual failed
|
|
22
|
+
tool calls separate from a terminal run failure. Preserve safe pre-prompt startup
|
|
23
|
+
retries and keep the last recorded cause when that retry budget is exhausted.
|
|
24
|
+
- Require Pi 0.85.0 and reuse its exported RPC command/response types. Include its
|
|
25
|
+
official server package as a peer and development dependency: the unbundled SDK
|
|
26
|
+
and CLI require it at runtime, not only in tests.
|
|
27
|
+
- Discover actual built-in/custom role definitions in setup, respecting project
|
|
28
|
+
trust. Saving selection removes unavailable names and overrides without retired-role
|
|
29
|
+
aliases or config migration; real disabled and never-configured custom roles remain selectable.
|
|
30
|
+
|
|
7
31
|
## 4.3.9
|
|
8
32
|
|
|
9
33
|
- Add optional bounded stable `phaseId` and exact declarative write `scope` claims to single
|
package/README.md
CHANGED
|
@@ -12,13 +12,12 @@ once and your main agent delegates on its own.
|
|
|
12
12
|
|
|
13
13
|
## What's new
|
|
14
14
|
|
|
15
|
-
**4.3.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
with fixed, documented rules before main decides whether a Sentinel review is worthwhile.
|
|
15
|
+
**4.3.10** — adds read-only `subagent_status` and removes `subagent_control`
|
|
16
|
+
(`steer`, `park`, and `resume`). Runs are one-shot; main handles unfinished work.
|
|
17
|
+
Failure reporting preserves real RPC exit/provider diagnostics and distinguishes
|
|
18
|
+
a failed run from an intentionally failing tool call. Requires Pi **0.85.0** and
|
|
19
|
+
reuses its official RPC types. Setup discovers actual role definitions instead
|
|
20
|
+
of inventing roles from saved names; there are no retired-role aliases or migrations.
|
|
22
21
|
|
|
23
22
|
See [CHANGELOG.md](./CHANGELOG.md).
|
|
24
23
|
|
|
@@ -29,7 +28,7 @@ See [CHANGELOG.md](./CHANGELOG.md).
|
|
|
29
28
|
- [The team](#the-team)
|
|
30
29
|
- [Dispatching work](#dispatching-work)
|
|
31
30
|
- [Parallel edits](#parallel-edits)
|
|
32
|
-
- [
|
|
31
|
+
- [Runs: status and stop](#runs-status-and-stop)
|
|
33
32
|
- [Live status and results](#live-status-and-results)
|
|
34
33
|
- [Models, thinking, and tools](#models-thinking-and-tools)
|
|
35
34
|
- [Configuration](#configuration)
|
|
@@ -55,21 +54,20 @@ back — with you. This extension owns them:
|
|
|
55
54
|
its task wording changes. IDs are 1–80 ASCII letters, numbers, or `._:-`, starting
|
|
56
55
|
with a letter or number, so lease output stays single-line. Exact normalized task+cwd
|
|
57
56
|
remains the backward-compatible fallback for old calls.
|
|
58
|
-
-
|
|
59
|
-
|
|
57
|
+
- Runs are one-shot. Use `subagent_status` to inspect them and `subagent_stop` to
|
|
58
|
+
cancel them; main handles unfinished work instead of continuing a failed child.
|
|
60
59
|
- Background completions and stop results arrive at the next parent model boundary;
|
|
61
60
|
`wait: true` returns the same result in-turn instead. A run uses exactly one route.
|
|
62
61
|
- Parallel writers use detached Git worktrees without touching your index.
|
|
63
|
-
Worktree setup obeys the bounded queue; final integration releases its process
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
instead of becoming silent hangs.
|
|
62
|
+
Worktree setup obeys the bounded queue; final integration releases its process slot.
|
|
63
|
+
- Interrupted work retains artifacts for manual recovery after reload or crash.
|
|
64
|
+
Within a run, a configured child-model failure can still hand off to the main model.
|
|
65
|
+
- Failure notifications include available reasons, and status keeps terminal facts
|
|
66
|
+
and retained recovery paths queryable for the current parent session.
|
|
69
67
|
|
|
70
68
|
## Install
|
|
71
69
|
|
|
72
|
-
Requires **pi >= 0.
|
|
70
|
+
Requires **pi >= 0.85.0** and **Node.js >= 22.19.0**.
|
|
73
71
|
|
|
74
72
|
```bash
|
|
75
73
|
pi install npm:@ferris1225/pi-subagents
|
|
@@ -119,6 +117,12 @@ the objective and its done condition, exact paths and symbols, facts already
|
|
|
119
117
|
established (with citations), boundaries, and the expected output shape — which is
|
|
120
118
|
what the injected delegation guidance produces when the main agent dispatches for you.
|
|
121
119
|
|
|
120
|
+
Children run the official `pi --mode rpc` server, using Pi's exported command/response
|
|
121
|
+
types and its own session persistence. There is no separate subagent protocol. The
|
|
122
|
+
host transport remains local because Pi 0.85.0's `RpcClient` cannot attach to our
|
|
123
|
+
child process or provide process-tree shutdown, bounded abort coordination, and
|
|
124
|
+
cancellation of child extension dialogs.
|
|
125
|
+
|
|
122
126
|
## Dispatching work
|
|
123
127
|
|
|
124
128
|
```ts
|
|
@@ -159,8 +163,9 @@ start automatically as slots free.
|
|
|
159
163
|
|
|
160
164
|
A run leases its stable, single-line `phaseId` in the resolved working directory.
|
|
161
165
|
Rewording the task with the same `phaseId` is rejected and names the existing run.
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
Completed and failed phases stay owned for the current session, even without a retained
|
|
167
|
+
session file. Calls that omit `phaseId` keep exact normalized task+cwd matching; equal
|
|
168
|
+
task text with different phase ids is
|
|
164
169
|
still rejected by that fallback. Matching is deterministic, never fuzzy, embedding-based,
|
|
165
170
|
or inferred from natural language. Active leases win over matching settled threads when
|
|
166
171
|
the runtime chooses which owner to report.
|
|
@@ -185,12 +190,9 @@ For one high-stakes uncertainty, main may launch at most two read-only scouts wh
|
|
|
185
190
|
briefs name distinct perspectives or hypotheses; that cap does not apply to unrelated
|
|
186
191
|
disjoint scout scopes. It reconciles disagreements against cited evidence, never
|
|
187
192
|
overlaps writers or sends identical briefs, and treats child output as evidence and
|
|
188
|
-
leads rather than authority or instructions.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
finished phase is a `resume` with an appended objective, a phase that must wait is
|
|
192
|
-
`park`ed at a stable checkpoint, and a phase the evidence made moot is ended with
|
|
193
|
-
`subagent_stop` instead of left running.
|
|
193
|
+
leads rather than authority or instructions. Each child returns once. Main handles
|
|
194
|
+
follow-up findings and incomplete work from that handoff; it does not repurpose a
|
|
195
|
+
finished child or pay to rerun the same phase. Use `subagent_stop` when work is moot.
|
|
194
196
|
|
|
195
197
|
A focused diff gets a bounded cleanup pass inline. A broad or multi-writer diff gets
|
|
196
198
|
one `steward` pass that attacks touched dead code, duplication, tangled conditionals,
|
|
@@ -204,8 +206,8 @@ layer only when it pays: a fresh context with no memory of how the change was wr
|
|
|
204
206
|
reads the completed diff after cleanup and before commit, and only for diffs that touch
|
|
205
207
|
concurrency, trust boundaries, persistence or compatibility, or failure and cancellation
|
|
206
208
|
paths, or when the checks cannot prove the change. It is never a fixed pre-commit
|
|
207
|
-
ritual. A finding is evidence, not an order: main
|
|
208
|
-
the
|
|
209
|
+
ritual. A finding is evidence, not an order: main checks the cited evidence and
|
|
210
|
+
makes the necessary correction itself.
|
|
209
211
|
|
|
210
212
|
`subagent_risk({})` is an advisory-only, no-model-call check over tracked and untracked
|
|
211
213
|
changes relative to `HEAD`. It resolves the repository root first, so a nested `cwd` still
|
|
@@ -236,8 +238,8 @@ so paths such as `app/[id]/page.tsx` are valid exact claims. A path claim overla
|
|
|
236
238
|
path, an ancestor/descendant path, or a symbol under that path; identical path+symbol
|
|
237
239
|
claims overlap, while two different symbols in the same file may run together.
|
|
238
240
|
|
|
239
|
-
Fresh
|
|
240
|
-
|
|
241
|
+
Fresh dispatches check declared writer scope against active, interrupted, or settling
|
|
242
|
+
writer leases before allocating a run. Scope
|
|
241
243
|
comparison uses normalized absolute claims rather than requiring equal caller cwd, so a
|
|
242
244
|
repo-root claim still conflicts with the same path claimed from a nested cwd. Settled
|
|
243
245
|
threads do not block a later phase solely because it edits the same scope.
|
|
@@ -282,88 +284,60 @@ Third-party Pi packages execute as trusted code and must be reviewed accordingly
|
|
|
282
284
|
already been applied and only the cleanup failed, the next session start
|
|
283
285
|
removes the retained copy itself and clears the notice.
|
|
284
286
|
|
|
285
|
-
##
|
|
287
|
+
## Runs: status and stop
|
|
286
288
|
|
|
287
|
-
Every dispatch returns a stable `#id
|
|
289
|
+
Every dispatch returns a stable `#id`. Runs are one-shot: there is no
|
|
290
|
+
`subagent_control`, `steer`, `park`, or `resume` interface. Main takes over failed
|
|
291
|
+
or incomplete work using the child's partial edits and artifacts. A different
|
|
292
|
+
deliverable needs a new phase and brief, not a recycled thread.
|
|
288
293
|
|
|
289
|
-
| Tool
|
|
290
|
-
|
|
|
291
|
-
| `
|
|
292
|
-
| `subagent_stop`
|
|
294
|
+
| Tool | What it does |
|
|
295
|
+
| ---- | ------------ |
|
|
296
|
+
| `subagent_status` | Read-only inspection. Omit `id` to list this parent session's runs, or pass an exact numeric `id` to inspect one. |
|
|
297
|
+
| `subagent_stop` | Destructively cancel/retire a run by id/prefix, or all active runs with `all: true`. Delivers partial output and finalizes isolated changes. |
|
|
293
298
|
|
|
294
299
|
```ts
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
300
|
+
subagent_status({});
|
|
301
|
+
subagent_status({ id: 7 });
|
|
302
|
+
subagent_stop({ id: "7" });
|
|
298
303
|
```
|
|
299
304
|
|
|
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
|
-
`wait: true` instead holds that tool call until its new runs settle,
|
|
337
|
-
which is useful for one-shot `pi -p` sessions. It claims the delivery route before
|
|
338
|
-
launch, so the same result cannot also arrive as a background completion; if the
|
|
339
|
-
parent turn is aborted, delivery falls back to the completion path.
|
|
340
|
-
Use `wait: true` only when the result is the immediate dependency. Otherwise
|
|
341
|
-
leave it in the background and continue real disjoint work — never burn main
|
|
342
|
-
context on `sleep` or polling while a child keeps running.
|
|
343
|
-
|
|
344
|
-
The wait has no timer chosen by the model: it resolves when its run settles, and
|
|
345
|
-
a parked run returns its resume handle. Control operations are bounded so they do
|
|
346
|
-
not hang on a generation that is still settling.
|
|
347
|
-
|
|
348
|
-
A thread stays durable while its work is unfinished. Parked sessions, worktree
|
|
349
|
-
checkpoints, and result excerpts are recorded under the per-project storage root,
|
|
350
|
-
so reload, restart, or crash produces a resumable checkpoint. An isolated thread
|
|
351
|
-
continues in its original worktree.
|
|
352
|
-
|
|
353
|
-
Restore runs at session start. `subagent_control`, `subagent_stop`, prompt
|
|
354
|
-
injection, and new dispatches wait for it, so a parked id cannot be reported
|
|
355
|
-
missing or reused. If a recorded worktree is gone, the run is surfaced as failed
|
|
356
|
-
and non-resumable while its retained session and recovery record remain available
|
|
357
|
-
for inspection or destructive stop.
|
|
358
|
-
|
|
359
|
-
Persisted sessions and worktrees are resumed or removed only when their canonical paths
|
|
360
|
-
match the current project's managed storage layout and repository. Invalid records are
|
|
361
|
-
dropped without following or deleting their targets. Recovery-owned worktrees and patches
|
|
362
|
-
remain protected from startup sweeps and project-root retention until recovery is announced.
|
|
363
|
-
|
|
364
|
-
Only interrupted work needs a record, so a thread that completes or fails cleanly
|
|
365
|
-
drops its own. That also means a reload keeps interrupted threads resumable, while
|
|
366
|
-
threads that had already finished keep only their delivered result.
|
|
305
|
+
Status reads runtime state without starting, stopping, continuing, or waiting for a
|
|
306
|
+
child to finish. It includes the phase/task summary, activity, elapsed time, model,
|
|
307
|
+
usage, terminal diagnostics, and available result/session/recovery paths. States
|
|
308
|
+
distinguish `queued`, `running`, `interrupting`, `settling` (Git finalization),
|
|
309
|
+
`completed`, `failed`, `stopped`, and `interrupted` (recovered unfinished work).
|
|
310
|
+
Queued runs report their actual wait reason. Settled runs remain queryable in the
|
|
311
|
+
current parent session even after their transient widget rows disappear.
|
|
312
|
+
|
|
313
|
+
The tool returns these facts in Pi's existing structured `details.runs` field.
|
|
314
|
+
An individual run's failure does not make a successful status lookup a tool error;
|
|
315
|
+
an unknown `id` does. This is runtime-authored data, not a requirement for children
|
|
316
|
+
to generate strict JSON. Agent-written reports remain evidence to verify.
|
|
317
|
+
|
|
318
|
+
A background dispatch returns a launch receipt, then its completion arrives at
|
|
319
|
+
the next safe parent boundary—after current tool calls and before the next model
|
|
320
|
+
call. `wait: true` instead holds the dispatch until its new runs settle, which is
|
|
321
|
+
useful for one-shot `pi -p` sessions or an immediate dependency. Each run has one
|
|
322
|
+
delivery route; aborting the waiting parent turn transfers delivery to the
|
|
323
|
+
background path. Use status for on-demand inspection, not a polling or sleep loop.
|
|
324
|
+
|
|
325
|
+
Stop drops messages still queued inside Pi, performs a bounded RPC abort, and
|
|
326
|
+
terminates the child process tree. It retires the session; it never starts another
|
|
327
|
+
attempt. Worktree integration failures keep their recovery artifacts.
|
|
328
|
+
|
|
329
|
+
Interrupted work retains a durable record and any session/worktree artifacts for
|
|
330
|
+
manual recovery after reload or crash. Missing session files no longer discard
|
|
331
|
+
isolated edits. Restore runs at session start; lookup tools, prompt injection, and
|
|
332
|
+
fresh dispatch wait for that pass so an existing id cannot be reported missing or
|
|
333
|
+
reused. Missing recorded worktrees surface as failures without discarding the
|
|
334
|
+
remaining recovery evidence.
|
|
335
|
+
|
|
336
|
+
Canonical managed-path and repository validation remains in place. Invalid records
|
|
337
|
+
are dropped without following or deleting their targets. Recovery-owned worktrees
|
|
338
|
+
and patches stay protected from startup sweeps and project-root retention.
|
|
339
|
+
Completed/failed runs drop their durable thread record; after reload, inspect their
|
|
340
|
+
delivered result instead of expecting them in the current-session status list.
|
|
367
341
|
|
|
368
342
|
## Live status and results
|
|
369
343
|
|
|
@@ -383,14 +357,13 @@ and, dim under the label column, what it is doing right now:
|
|
|
383
357
|
● #15 scout src/models.ts · ↑1.2k ↓8.4k R31.0k W1.1k $0.0900 · openai/gpt-5-mini · think:low · 3m07s
|
|
384
358
|
↳ grep fallback
|
|
385
359
|
○ #23 artisan src/config.ts · repo lane
|
|
386
|
-
○ #24 artisan
|
|
360
|
+
○ #24 artisan tests/config.test.ts · queued · 5m02s
|
|
387
361
|
```
|
|
388
362
|
|
|
389
363
|
Telemetry drops leftmost-first when a row runs out of width (badge, wait state,
|
|
390
364
|
usage, model, thinking) while elapsed survives every width. Queued rows state
|
|
391
365
|
what they actually wait for — `queued` for a free process slot, `repo lane`
|
|
392
|
-
for shared-checkout write serialization, or `starting
|
|
393
|
-
carries a dim `↻` in its agent column with its cumulative time. The widget is
|
|
366
|
+
for shared-checkout write serialization, or `starting`. The widget is
|
|
394
367
|
capped at ten lines: when many runs are live, extra runs collapse into a
|
|
395
368
|
`… +N more` marker so the editor keeps its space.
|
|
396
369
|
|
|
@@ -444,7 +417,7 @@ no `thinking` field in agent Markdown. Precedence: your setup override > the
|
|
|
444
417
|
role default, then the model clamp. There is no separate vision mode — assign
|
|
445
418
|
a multimodal model and name the image paths in the task.
|
|
446
419
|
|
|
447
|
-
Every dispatch,
|
|
420
|
+
Every dispatch, startup retry, and model fallback snapshots the parent's active tools,
|
|
448
421
|
and all `subagent*` tools are removed so children remain leaves. A role without
|
|
449
422
|
an explicit list inherits that snapshot; an explicit list is a strict
|
|
450
423
|
intersection, so active extension tools are available only when named. A declared
|
|
@@ -471,8 +444,12 @@ search snippets, records material dates/versions, and marks uncertainty.
|
|
|
471
444
|
`/subagents-setup` opens the original settings menu: enable or disable roles,
|
|
472
445
|
configure one enabled role's model and thinking level, or walk through a full
|
|
473
446
|
re-setup. `Esc` moves back through the menu stack, and model lists support fuzzy
|
|
474
|
-
search.
|
|
475
|
-
|
|
447
|
+
search. The enable menu discovers built-ins and actual custom role files in the configured
|
|
448
|
+
scope, including roles never configured before. Project files require Pi's project trust.
|
|
449
|
+
Config-only names are not role definitions and never appear in the enable or configure
|
|
450
|
+
picker. Saving an enable selection or full setup discards unavailable role names and their
|
|
451
|
+
model/thinking settings; no retired-name aliases or configuration migration are applied.
|
|
452
|
+
To start over, remove `pi-subagents.json` and run `/subagents-setup` again. Other settings live in
|
|
476
453
|
`~/.pi/agent/pi-subagents.json` (following `PI_CODING_AGENT_DIR`):
|
|
477
454
|
|
|
478
455
|
```json
|
|
@@ -490,7 +467,7 @@ enable menu. Other settings live in
|
|
|
490
467
|
| Field | Meaning |
|
|
491
468
|
| --------------------- | ------- |
|
|
492
469
|
| `enabledAgents` | Agents available for discovery and delegation. `[]` disables all. |
|
|
493
|
-
| `knownAgents` |
|
|
470
|
+
| `knownAgents` | Catalog shown by setup; tracks built-in adoption, but cannot define a custom role without a file. |
|
|
494
471
|
| `agentModels` | Optional model per agent; missing means the current main model. |
|
|
495
472
|
| `agentThinkingLevels` | Optional setup override per agent; missing means the role default. |
|
|
496
473
|
| `maxResultLines` | Lines kept in a completion message before the artifact takes over. Default `40`. |
|
|
@@ -502,9 +479,9 @@ automatically. `enabledAgents` is authoritative after catalog adoption: a newly
|
|
|
502
479
|
shipped built-in is appended once, then `knownAgents` records that it was surfaced
|
|
503
480
|
so a deliberate later disable remains disabled. `sentinel` returns through that
|
|
504
481
|
rule: a config written by 4.3.5–4.3.7, which removed it, enables it once on the next
|
|
505
|
-
load; turn it off in `/subagents-setup` and it stays off.
|
|
506
|
-
|
|
507
|
-
|
|
482
|
+
load; turn it off in `/subagents-setup` and it stays off. Available custom roles remain
|
|
483
|
+
selectable even when disabled. Invalid known fields fall back safely, and unknown fields
|
|
484
|
+
are dropped when canonical config is persisted.
|
|
508
485
|
|
|
509
486
|
At session start, model overrides that pi no longer reports are removed with a
|
|
510
487
|
one-time notice. If pi's own session compaction fails mid-thread, a notice surfaces
|
|
@@ -546,7 +523,7 @@ that removes it, so this directory does not grow without bound:
|
|
|
546
523
|
| `pi-subagents.json` | Your configuration | Never — it is yours |
|
|
547
524
|
| `ferris-pi-subagents/pi-subagents-recovery.json` | Worktree integration and cleanup failures | When the retained patch or worktree it points at is gone |
|
|
548
525
|
| `ferris-pi-subagents/<project>/pi-subagents-threads.json` | One record per interrupted thread | When the thread settles, or after 30 days |
|
|
549
|
-
| `ferris-pi-subagents/<project>/sessions/` |
|
|
526
|
+
| `ferris-pi-subagents/<project>/sessions/` | Child sessions for in-run fallback and manual recovery | When the owning session ends and no recovery record claims them |
|
|
550
527
|
| `ferris-pi-subagents/<project>/worktrees/` | Isolated checkouts for parallel writers | On integration, or when no thread/recovery record claims them |
|
|
551
528
|
| `ferris-pi-subagents/<project>/results/` | Full text of truncated results | After 7 days, or beyond 50 per project |
|
|
552
529
|
| `ferris-pi-subagents/<project>/tmp/` | Child prompt copies and the no-retry policy shim | When its owning process exits |
|
|
@@ -554,7 +531,7 @@ that removes it, so this directory does not grow without bound:
|
|
|
554
531
|
|
|
555
532
|
Cleanup runs at session start and is deliberately conservative. A directory goes
|
|
556
533
|
away only when the process that created it is gone and no valid manifest record still
|
|
557
|
-
claims it, so a live sibling pi instance never loses state and
|
|
534
|
+
claims it, so a live sibling pi instance never loses state and interrupted or recovery-owned
|
|
558
535
|
work outlives its own process by design. Thread and recovery references always beat an
|
|
559
536
|
age rule.
|
|
560
537
|
|
|
@@ -571,6 +548,12 @@ grouped by responsibility under `src/`: configuration, delegation, execution, is
|
|
|
571
548
|
lifecycle, and presentation. Thread restoration, shared lifecycle coordination, RPC control,
|
|
572
549
|
and Git command execution live in focused modules rather than oversized catch-all files.
|
|
573
550
|
|
|
551
|
+
The test runner uses Node 22 or 24; Node 26 removed `--experimental-transform-types`.
|
|
552
|
+
Pi 0.85.0's unbundled SDK and CLI import `@earendil-works/pi-server` without declaring
|
|
553
|
+
it. This project declares the official server package as a peer (and a development
|
|
554
|
+
dependency), so npm can resolve it alongside the SDK in consumer installations.
|
|
555
|
+
It is not bundled into the extension, and no replacement RPC server is introduced.
|
|
556
|
+
|
|
574
557
|
## Changelog
|
|
575
558
|
|
|
576
559
|
See [CHANGELOG.md](./CHANGELOG.md) for published release notes.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ferris1225/pi-subagents",
|
|
3
|
-
"version": "4.3.
|
|
4
|
-
"description": "A managed sub-agent team for pi: scout, artisan, steward, and sentinel roles,
|
|
3
|
+
"version": "4.3.10",
|
|
4
|
+
"description": "A managed sub-agent team for pi: scout, artisan, steward, and sentinel roles, one-shot runs, read-only status, and Git worktree isolation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -43,17 +43,19 @@
|
|
|
43
43
|
"prepack": "npm run check"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@earendil-works/pi-agent-core": ">=0.
|
|
47
|
-
"@earendil-works/pi-ai": ">=0.
|
|
48
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
49
|
-
"@earendil-works/pi-
|
|
46
|
+
"@earendil-works/pi-agent-core": ">=0.85.0",
|
|
47
|
+
"@earendil-works/pi-ai": ">=0.85.0",
|
|
48
|
+
"@earendil-works/pi-coding-agent": ">=0.85.0",
|
|
49
|
+
"@earendil-works/pi-server": ">=0.85.0",
|
|
50
|
+
"@earendil-works/pi-tui": ">=0.85.0",
|
|
50
51
|
"typebox": "*"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
|
-
"@earendil-works/pi-agent-core": "^0.
|
|
54
|
-
"@earendil-works/pi-ai": "^0.
|
|
55
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
56
|
-
"@earendil-works/pi-
|
|
54
|
+
"@earendil-works/pi-agent-core": "^0.85.0",
|
|
55
|
+
"@earendil-works/pi-ai": "^0.85.0",
|
|
56
|
+
"@earendil-works/pi-coding-agent": "^0.85.0",
|
|
57
|
+
"@earendil-works/pi-server": "^0.85.0",
|
|
58
|
+
"@earendil-works/pi-tui": "^0.85.0",
|
|
57
59
|
"@types/node": "^22.10.0",
|
|
58
60
|
"typebox": "^1.3.9",
|
|
59
61
|
"typescript": "^5.9.0"
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { stat } from "node:fs/promises";
|
|
10
10
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
11
11
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
12
|
+
import { discoverAgents } from "../delegation/agents.ts";
|
|
12
13
|
import {
|
|
13
14
|
AGENT_PROFILES,
|
|
14
15
|
BUILTIN_AGENT_NAMES,
|
|
@@ -46,16 +47,13 @@ const THINKING_LEVEL_HINTS: Record<ThinkingLevel, string> = {
|
|
|
46
47
|
max: "strongest reasoning",
|
|
47
48
|
};
|
|
48
49
|
|
|
49
|
-
function setupAgentNames(config: SubagentsConfig): string[] {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
...Object.keys(config.agentThinkingLevels),
|
|
57
|
-
]),
|
|
58
|
-
];
|
|
50
|
+
function setupAgentNames(ctx: ExtensionCommandContext, config: SubagentsConfig): string[] {
|
|
51
|
+
const { agents } = discoverAgents(ctx.cwd, {
|
|
52
|
+
scope: config.agentScope,
|
|
53
|
+
projectTrusted: ctx.isProjectTrusted?.() === true,
|
|
54
|
+
});
|
|
55
|
+
const available = new Set(agents.map((agent) => agent.name));
|
|
56
|
+
return [...new Set([...BUILTIN_AGENT_NAMES, ...available])].filter((name) => available.has(name));
|
|
59
57
|
}
|
|
60
58
|
|
|
61
59
|
function agentPickerItems(names: readonly string[]): Array<{ value: string; label: string; description: string }> {
|
|
@@ -87,12 +85,13 @@ async function pickEnabledAgents(
|
|
|
87
85
|
ctx: ExtensionCommandContext,
|
|
88
86
|
config: SubagentsConfig,
|
|
89
87
|
): Promise<string[] | undefined> {
|
|
88
|
+
const names = setupAgentNames(ctx, config);
|
|
90
89
|
return promptSelectMany(
|
|
91
90
|
ctx,
|
|
92
91
|
"Which agents should run?",
|
|
93
92
|
"Each line is a role and its job. Space toggles • Enter confirms • Esc back",
|
|
94
|
-
agentPickerItems(
|
|
95
|
-
config.enabledAgents,
|
|
93
|
+
agentPickerItems(names),
|
|
94
|
+
config.enabledAgents.filter((name) => names.includes(name)),
|
|
96
95
|
);
|
|
97
96
|
}
|
|
98
97
|
|
|
@@ -210,8 +209,10 @@ async function configureOneAgent(
|
|
|
210
209
|
ctx: ExtensionCommandContext,
|
|
211
210
|
config: SubagentsConfig,
|
|
212
211
|
): Promise<ConfiguredAgentChoice | undefined> {
|
|
212
|
+
const available = setupAgentNames(ctx, config);
|
|
213
|
+
const enabled = config.enabledAgents.filter((name) => available.includes(name));
|
|
213
214
|
while (true) {
|
|
214
|
-
const name = await pickAgentToConfigure(ctx,
|
|
215
|
+
const name = await pickAgentToConfigure(ctx, enabled);
|
|
215
216
|
if (name === undefined) return undefined;
|
|
216
217
|
const profile = agentProfile(name);
|
|
217
218
|
if (profile) ctx.ui.notify(`${name}: ${profile.remark}`, "info");
|
|
@@ -289,7 +290,7 @@ async function runFullSetup(ctx: ExtensionCommandContext, configPath: string, ba
|
|
|
289
290
|
|
|
290
291
|
const next: SubagentsConfig = {
|
|
291
292
|
enabledAgents: enabled,
|
|
292
|
-
knownAgents: setupAgentNames(base),
|
|
293
|
+
knownAgents: setupAgentNames(ctx, base),
|
|
293
294
|
agentModels,
|
|
294
295
|
agentThinkingLevels: keepAgentEntries(base.agentThinkingLevels, enabled),
|
|
295
296
|
maxResultLines: base.maxResultLines,
|
|
@@ -326,6 +327,7 @@ async function runMenu(ctx: ExtensionCommandContext, configPath: string, config:
|
|
|
326
327
|
const enabled = await pickEnabledAgents(ctx, config);
|
|
327
328
|
if (enabled === undefined) continue;
|
|
328
329
|
next.enabledAgents = enabled;
|
|
330
|
+
next.knownAgents = setupAgentNames(ctx, config);
|
|
329
331
|
next.agentModels = keepAgentEntries(next.agentModels, enabled);
|
|
330
332
|
next.agentThinkingLevels = keepAgentEntries(next.agentThinkingLevels, enabled);
|
|
331
333
|
} else {
|