@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 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.9** — dispatch admission now accepts bounded stable `phaseId` identities and exact
16
- declarative write `scope` claims. Fresh/resumed writers are checked against active leases;
17
- parallel batches preflight deterministic duplicates and all declared scope conflicts before
18
- allocation. Omitted scopes remain compatible; a parallel call that omits `scope` reports
19
- `independence not verified`. Declared claims do not prove natural-language task independence.
20
- The no-model-call `subagent_risk` advisory classifies changed tracked and untracked paths
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
- - [Threads: steer, resume, park, stop](#threads-steer-resume-park-stop)
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
- - Follow-up work stays on the same thread: `steer` a running phase, `resume` or
59
- `park` a thread with its retained context, `stop` a phase the evidence made moot.
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
- slot.
65
- - Interrupted threads retain their session for resume after reload or crash; a
66
- configured child-model failure continues the same session on the main model.
67
- - Start, restore, and integration failures surface with retained recovery paths
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.84.4** and **Node.js >= 22.19.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
- The id remains immutable across resume. Calls that omit `phaseId` keep the old exact
163
- normalized task+cwd behavior; consequently, equal task text with different phase ids is
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. Follow-up work goes to the same thread,
189
- never a second one: new in-scope evidence travels through `subagent_control steer`
190
- (a thread that has settled or is parked continues with it), a follow-up on a
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 routes it to the thread that owns
208
- the change with `subagent_control resume`, or fixes it inline when that is cheaper.
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 single dispatches and resumes check a declared writer scope against active, parked,
240
- resuming, interrupting, or settling writer leases before allocating a generation. Scope
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
- ## Threads: steer, resume, park, stop
287
+ ## Runs: status and stop
286
288
 
287
- Every dispatch returns a stable `#id`, which is the handle for the thread tools:
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 | What it does |
290
- | ------------------ | ------------ |
291
- | `subagent_control` | `steer` a running RPC attempt with additional evidence/guidance, continuing the same thread with it when the thread has settled or is parked; `resume` a parked/settled thread with an optional appended `objective` and additive `scope`; `park` a running thread at a stable checkpoint, keeping its session and worktree for a later resume. |
292
- | `subagent_stop` | Destructively cancel, deliver partial output, and retire the thread. Steering and follow-up messages still queued in the child are dropped so nothing can revive it later. |
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
- subagent_control({ action: "steer", id: 7, objective: "The failing request used an expired token; account for that evidence." });
296
- subagent_control({ action: "park", id: 7 });
297
- subagent_control({ action: "resume", id: 7, objective: "Finish the tests." });
300
+ subagent_status({});
301
+ subagent_status({ id: 7 });
302
+ subagent_stop({ id: "7" });
298
303
  ```
299
304
 
300
- A fresh dispatch stores `phaseId` and normalized `scope` on its stable thread and durable
301
- v1 record. `resume` always keeps the thread's phase id. An optional resume `scope` adds
302
- normalized claims to the retained scope; it cannot shrink or clear prior claims, so edits
303
- already present in a retained worktree stay covered by admission. Resume also rechecks the
304
- unioned scope against other active writer leases before starting a generation. Existing v1
305
- manifests without these optional fields remain readable.
306
-
307
- `steer` requires a nonblank `objective`. While the child RPC is running, it adds
308
- guidance to the current phase without replacing the original task. If the thread has
309
- already reached `completed`, `failed`, or `parked` including a generation that settles
310
- between the state check and RPC acceptance the control call resumes the same stable
311
- id, reuses retained context when available, and supplies the guidance as its appended
312
- objective, so evidence is never re-bought by a second dispatch. Queued, starting,
313
- retrying, resuming, interrupting, stopped, retired, and missing threads are rejected
314
- without changing them. Steering ACKs are bounded, and steering/stop are serialized so
315
- stop can clear queued child messages and abort without a stale steer landing afterward.
316
-
317
- `park` pauses a running thread at its next safe point: the child is interrupted the
318
- same way a session shutdown interrupts it, but the thread returns as `parked` rather
319
- than failed, its retained session and any active worktree are kept, and its durable
320
- record is written immediately so the checkpoint survives a reload. Nothing is
321
- integrated or delivered on park; the tool result carries the usage so far and the
322
- resume handle. Only an active running attempt with a retained session can be parked;
323
- a run that has not started has nothing worth keeping, so `subagent_stop` discards it.
324
-
325
- A resumed child is told that its earlier work is preserved and must not be redone, and
326
- that the workspace may have changed while the thread was inactive — main may have
327
- integrated sibling worktrees or edited the tree so it re-reads a file before editing
328
- it unless it read it during the continuation. A resume with an appended objective is
329
- framed as the same thread continuing on top of finished work, never as a restart.
330
-
331
- There is no status, polling, or separate wait tool. A background dispatch returns
332
- a launch receipt, then its completion is steered at the next safe parent boundary—after
333
- the current tool calls and before the next model call. This wakes the main model without
334
- waiting for its whole run to end.
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 tests/config.test.ts · queued · 5m02s
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` and a resumed thread
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, resume, retry, and fallback snapshots the parent's active tools,
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. Built-in and previously configured custom roles remain available in the
475
- enable menu. Other settings live in
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` | Roles already surfaced by setup; retains disabled custom roles and tracks built-in adoption. |
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. Custom roles and other
506
- known-agent entries remain intact. Invalid known fields fall back safely, and unknown
507
- fields are dropped when canonical config is persisted.
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/` | Retained child sessions that a resume continues from | When the thread settles or its retained record is removed |
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 parked or recovery-owned
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.9",
4
- "description": "A managed sub-agent team for pi: scout, artisan, steward, and sentinel roles, durable threads, model fallback, and Git worktree isolation.",
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.84.4",
47
- "@earendil-works/pi-ai": ">=0.84.4",
48
- "@earendil-works/pi-coding-agent": ">=0.84.4",
49
- "@earendil-works/pi-tui": ">=0.84.4",
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.84.4",
54
- "@earendil-works/pi-ai": "^0.84.4",
55
- "@earendil-works/pi-coding-agent": "^0.84.4",
56
- "@earendil-works/pi-tui": "^0.84.4",
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
- return [
51
- ...new Set([
52
- ...BUILTIN_AGENT_NAMES,
53
- ...config.knownAgents,
54
- ...config.enabledAgents,
55
- ...Object.keys(config.agentModels),
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(setupAgentNames(config)),
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, config.enabledAgents);
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 {
@@ -52,7 +52,7 @@ const READ_ONLY_TOOL_NAMES = new Set([
52
52
  ]);
53
53
  export const SUBAGENT_TOOL_NAMES = [
54
54
  "subagent",
55
- "subagent_control",
55
+ "subagent_status",
56
56
  "subagent_stop",
57
57
  "subagent_risk",
58
58
  ] as const;