@howarewoo/pi-subagents 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +7 -7
- package/docs/delegation-contract.md +8 -8
- package/docs/images/subagent-hub.svg +1 -1
- package/docs/images/subagent-widget.svg +1 -1
- package/docs/verification.md +5 -1
- package/package.json +1 -1
- package/src/child-execution.ts +17 -8
- package/src/coordinator.ts +110 -21
- package/src/delegation-types.ts +7 -0
- package/src/hub.ts +55 -47
- package/src/pi-extended-subagents.ts +5 -19
- package/src/subagent-widget.ts +44 -9
- package/src/task-presentation.ts +31 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.0]
|
|
6
|
+
|
|
7
|
+
Requires Node 22.19+ and stable Pi 1.5.2 or newer, unchanged from 0.2.x. Tested host
|
|
8
|
+
remains Pi 1.5.2; newer stable hosts are allowed, not guaranteed compatible.
|
|
9
|
+
|
|
10
|
+
### Breaking — completed-context resume and migration
|
|
11
|
+
|
|
12
|
+
- Resume of successfully completed work now continues the same full SDK conversation and tool history, with the same identity, generation and session count, rather than starting a fresh session. To start fresh work in a new generation, use explicit model-issued `delegate_coordinate` `followup` or `revive` and supply the context it needs; those operations do not replay the old conversation.
|
|
13
|
+
- Only the deadline window resets on resume; request/tool/spawn counters remain cumulative, with at most 64 execution windows per generation. Paused windows retain provisional structured submission state and publish no final outcome artifacts. Completed windows preserve immutable outcome/artifact evidence in `completedWindows`; later completed-window artifacts use `window-N/` without replacing earlier files. Resumed completed structured assignments require a new `submit_result`.
|
|
14
|
+
- Context restoration lasts only for the current parent runtime; saved transcripts are not reload/restart recovery state. Let active tasks drain before updating, then restart Pi. Reload/shutdown aborts and drains children rather than migrating them. Resume the exact parent generation first, then explicitly resume selected children; descendants never resume automatically. Existing authority, grants, authentication, capacity and writer checks still apply.
|
|
15
|
+
|
|
16
|
+
### Changes
|
|
17
|
+
|
|
18
|
+
- Make the queued deadline/continuation lifecycle regression test deterministic with a controlled deadline clock, preserving pre-dispatch expiry and repeated continuation coverage while verifying shutdown disposes an actual retained SDK session. Runtime deadline policy is unchanged.
|
|
19
|
+
|
|
20
|
+
- Correct resume to continue paused or successfully completed conversations with the same identity, generation, session count and full SDK/tool history. Completed runtimes restore from the canonical SessionManager into the same transcript, never a result summary or silent fresh generation. Preserve cumulative budgets and earlier window artifacts/outcomes; revalidate current authority/auth/capacity, reject stopped/failed/retired/unavailable identities, and bound continuations to 64 windows. Explicit followup/revive behavior is unchanged.
|
|
21
|
+
|
|
22
|
+
- Preserve successfully completed descendants across ancestor completion for explicit parent-first same-context resume, without undoing explicit retirement. Validate retained post-handoff model availability on resume rather than requiring the obsolete admission model; keep lineage, grants and writer checks.
|
|
23
|
+
|
|
24
|
+
- Count individual subagent sessions, including retained historical generations, in the widget total using the same roster source as the unfiltered Hub. Distinct tasks sharing a profile and nested sessions each count separately; active widget rows remain bounded and scheduling/lifecycle behavior is unchanged.
|
|
25
|
+
|
|
26
|
+
## [0.2.1]
|
|
27
|
+
|
|
28
|
+
Requires Node 22.19+ and stable Pi 1.5.2 or newer. Tested host remains Pi 1.5.2;
|
|
29
|
+
newer stable hosts are allowed, not guaranteed compatible. No configuration migration is
|
|
30
|
+
required. Let active tasks finish before updating, then restart Pi; reload and shutdown
|
|
31
|
+
abort and drain active children rather than migrating them. Permissions, scheduling limits
|
|
32
|
+
and lifecycle behavior are unchanged.
|
|
33
|
+
|
|
34
|
+
- Keep Hub tree lanes, unselected agent names and status text in the normal foreground color. Highlight the selected name and selection marker with the accent color, while profile words and status circles retain lifecycle coloring, including compact views.
|
|
35
|
+
|
|
36
|
+
- Replace the widget activity preview with a summary below the visible child when its parent has additional hidden running children. Show “2 more nested subagents running” for the capacity illustration while keeping the total hidden-fleet overflow count unchanged.
|
|
37
|
+
|
|
38
|
+
- Add lifecycle-colored status circles to the Hub roster and compact selected-agent header. Use a tee for widget activity when a visible child follows, preserving the last child's elbow connector.
|
|
39
|
+
|
|
40
|
+
- Render connected subagent trees with three-column widget lanes and four-column Hub lanes, last-sibling elbow branches and continuing ancestor pipes, including aligned activity/profile rows. Group descendants by parent generation. The widget closes its last visible nested sibling before the overflow summary; Hub connectors reflect the full roster across viewport clipping. Remove blank separator rows between Hub agents and refresh the README illustrations. Indentation remains capped at three displayed levels and width/row bounds are unchanged.
|
|
41
|
+
|
|
42
|
+
- Refresh README Hub and widget illustrations to show the default capacity of 16 running tasks and 32 queued, with depth-two scout/review nesting and bounded widget overflow. Move the widget to the README introduction and the Hub image into its own section. Generate fixtures from the scheduling defaults and retain explicit synthetic-data disclosures; runtime limits are unchanged.
|
|
43
|
+
|
|
5
44
|
- Simplify README installation and update guidance now that the repository rename is complete. Keep current npm/Git sources, duplicate-loading precautions and a link to the historical package migration instructions.
|
|
6
45
|
|
|
7
46
|
## [0.2.0]
|
package/README.md
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
Delegate work to subagents in Pi, follow their progress, and steer or stop them from Subagent Hub. Subagents use your selected model by default, with their own assignments and explicit tool grants.
|
|
7
7
|
|
|
8
|
-

|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
_Pinned Subagents widget at default capacity: 16 running tasks and 32 queued. Counts and nested-agent progress stay visible above the editor. Synthetic demo data, not a live load test._
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
@@ -104,7 +104,7 @@ Pi discovers the native `subagent` tool at startup through its tool description
|
|
|
104
104
|
- `worker` maps to the configured `implementation` profile; `scout`, `review` and `general` are also available.
|
|
105
105
|
- Calls are async by default and wake the parent after drain. Set `async:false` to wait; use `tasks:[{agent,task,cwd?}]` for a batch.
|
|
106
106
|
- Control a task with its returned `id` and `action:"status"`, `"steer"`, `"stop"` or `"resume"`. Steer/resume also require `message`.
|
|
107
|
-
- Resume
|
|
107
|
+
- Resume continues a drained paused **or completed** conversation, preserving the same identity, generation, session count and full SDK conversation/tool history. Completed idle/parked agents restore their canonical session into a new SDK runtime using the same transcript, not a result summary. Missing restoration state, stopped/failed identities and retired descendants reject; there is no fresh-context fallback. Explicit `delegate_coordinate` followup/revive still start fresh work.
|
|
108
108
|
|
|
109
109
|
The coordinator supplies an existing workspace and the complete handoff, including accessible skill/reference paths. The extension does not create or manage worktrees. This is the [supported orchestration interface](docs/delegation-contract.md#native-orchestration-compatibility), not compatibility with every competing workflow script or custom agent definition.
|
|
110
110
|
|
|
@@ -126,11 +126,11 @@ Subagent Hub shows the task list beside the selected conversation using Pi's nat
|
|
|
126
126
|
|
|
127
127
|
The thread follows new output until you scroll up. Press End to follow again. The pinned Subagents widget appears after the first task starts. Closing Subagent Hub does not stop the work.
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
The Hub and widget illustrations use native renderer output with a synthetic fleet filling the default 16 concurrent slots and 32-item queue. Four read-only audit leads each have three foreground descendants, reaching the default nesting depth of two. The queue represents two further 16-task root batches, not one oversized batch. These are illustrations, not terminal screenshots or live-provider stress-test evidence. Regenerate them with `node scripts/render-hub-hero.ts` and `node scripts/render-hub-hero.ts --widget`.
|
|
130
130
|
|
|
131
|
-

|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
_Subagent Hub at default capacity: tasks and conversations side by side, with nested scouts/reviewers at depth two. The roster scrolls through all 48 tasks._
|
|
134
134
|
|
|
135
135
|
| Key | Action |
|
|
136
136
|
| --------------------- | ------------------------------------------------- |
|
|
@@ -197,7 +197,7 @@ All bundled profiles may delegate to `scout` and `review` by default, within a t
|
|
|
197
197
|
Default task limits are **30 minutes**, **100 model requests** and **100 tool calls**:
|
|
198
198
|
|
|
199
199
|
- A deadline pauses the active subtree after tool/provider drain, releasing capacity and writer leases but retaining sessions and conversations.
|
|
200
|
-
- Use `subagent` resume or root-only `delegate_coordinate` `{action:"resume",target:{id,generation},assignment:"Continue…"}` to continue the same identity and conversation. Only the deadline resets; request/tool/spawn counters remain cumulative.
|
|
200
|
+
- Use `subagent` resume or root-only `delegate_coordinate` `{action:"resume",target:{id,generation},assignment:"Continue…"}` to continue the same identity and conversation. Only the deadline resets; request/tool/spawn counters remain cumulative (at most 64 windows per generation). Completed windows retain earlier result/artifact evidence in `completedWindows`; a resumed completed structured assignment requires a new `submit_result`.
|
|
201
201
|
- Resume the parent first, then explicitly selected children. Descendants never resume automatically.
|
|
202
202
|
- Stop, shutdown and hard request/tool limits cancel and dispose. Unresponsive code must drain before pause or cancellation can release resources.
|
|
203
203
|
|
|
@@ -29,10 +29,10 @@ The model-only `subagent` tool is registered and described through Pi's public `
|
|
|
29
29
|
- Launch: `{agent,task,cwd?,model?,limits?,async?}`. `agent` is required: `general`, `scout`, `review`, `implementation`, or explicit compatibility name `worker` for the configured `implementation` profile. Unknown/custom agent definitions are rejected, not silently mapped. Authority and prompts still resolve through the existing profiles; no ambient Markdown agent loading or role/model fallback is added.
|
|
30
30
|
- Batch: `{tasks:[{agent,task,cwd?,model?,limits?}],cwd?,async?}`. Shared cwd is the default for items lacking one. Existing whole-batch preflight, FIFO limits, ordered outcomes and global writer serialization apply.
|
|
31
31
|
- `async` defaults true; false waits for final results. Accepted calls return immediately with exact `id:"UUID@generation"`, `taskId` (original UUID), generation and normal snapshot fields/artifact references. Control handles never prefix-match or resolve to the latest generation. Native `delegate_task` retains its UUID+generation output and foreground default.
|
|
32
|
-
- Read/control: `{action:"agents"}` or `"list"`; `{action:"status"|"stop",id}`; `{action:"steer"|"resume",id,message}`. Status can inspect a historical generation; mutations refuse stale handles. Resume continues a drained paused assignment in the same
|
|
32
|
+
- Read/control: `{action:"agents"}` or `"list"`; `{action:"status"|"stop",id}`; `{action:"steer"|"resume",id,message}`. Status can inspect a historical generation; mutations refuse stale handles. Resume continues a drained paused or successfully completed (idle/parked) assignment in the same conversation and generation, without increasing session count. Completed runtime graphs are reconstructed from the retained canonical SessionManager, preserving system context and actual tool history in the same transcript; no previous-result-summary or fresh-context fallback is allowed. Stopped, failed, cancelled, retired or unavailable conversations reject without starting new work. Use explicit `delegate_coordinate` followup/revive for fresh work. Native coordination remains available for richer inbox/wait/park behavior.
|
|
33
33
|
- Model overrides accept the native exact selection object or `provider/id[:effort]`. Omitted effort uses the parent's selected effort; overrides still require exact operator grants, availability/auth/scope and supported effort. Bare model IDs and unknown providers are not guessed. Omitting model retains ordinary parent/profile routing.
|
|
34
34
|
|
|
35
|
-
An async compatibility launch sends one window-outcome custom message per single/batch call after actual drain (paused or completed), using public `sendMessage(...,{triggerTurn:true,deliverAs:"followUp"})` to wake the parent. Compatibility resume does the same once for its new execution window
|
|
35
|
+
An async compatibility launch sends one window-outcome custom message per single/batch call after actual drain (paused or completed), using public `sendMessage(...,{triggerTurn:true,deliverAs:"followUp"})` to wake the parent. Compatibility resume does the same once for its new execution window; rejected resumes send no completion notification. This may cause a parent model turn and provider charges; no polling or detached worker survives parent shutdown. The original native tool's notification-only behavior is unchanged. Neither a notification nor a receipt proves the model understood the outcome.
|
|
36
36
|
|
|
37
37
|
The coordinator owns workspace allocation, exclusive writer handoff, Git/PR publication and retirement under the active workflow. Supply a complete task and accessible skill/reference paths: general inherits available skills and restricted reviewed leaf capabilities as specified below; workers never inherit parent instructions/history or context files. No scripts/workflow engine, supervisor RPC, automatic worktree lifecycle, external CLI worker, retained-run migration or blanket competitor API parity is promised.
|
|
38
38
|
|
|
@@ -158,11 +158,11 @@ A parent waiting in its child-local `delegate_task` retains its permit. Nested b
|
|
|
158
158
|
|
|
159
159
|
Deadlines pause rather than cancel. `queued|setup|running → pausing → paused` stops new dispatch, aborts SDK work and waits for actual subtree drain before releasing capacity and writer leases. Snapshots expose `pauseReason` (`deadline` or `ancestor deadline`), `retainedContext`, `window`, cumulative request/tool/spawn counters, and unfinalized structured submission state. Paused is neither success nor failure; no final outcome artifacts are published. A queued assignment can pause before any session/transcript exists.
|
|
160
160
|
|
|
161
|
-
Root-only `delegate_coordinate` `{action:"resume",target:{id,generation},assignment:"Continue…"}` or `subagent` `{action:"resume",id:"UUID@generation",message:"Continue…"}` appends that message to the retained SDK conversation. UUID, generation, assignment, workspace, selected model/prewalk state, role instructions, all prior SDK messages/tool calls/results
|
|
161
|
+
Root-only `delegate_coordinate` `{action:"resume",target:{id,generation},assignment:"Continue…"}` or `subagent` `{action:"resume",id:"UUID@generation",message:"Continue…"}` appends that message to the retained SDK conversation. UUID, generation, assignment, workspace, selected model/prewalk state, role instructions, all prior SDK messages/tool calls/results remain intact. A paused window retains its provisional structured submission state. Completed windows retain immutable result/outcome/artifact references in `completedWindows`; their existing files are never replaced. A resumed completed structured assignment requires a new submission (the previous validated value is evidence, not the new window's result). Later completed-window artifacts are published exclusively under `window-N/` inside the same task directory. Each explicit resume starts a fresh configured deadline window (still bounded by originally admitted and current limits). Cumulative requests/tools/spawns are **not** replenished. Each generation permits at most 64 execution windows, bounding completion evidence and notifications. A pre-session queued pause starts the original assignment followed by the continuation when dispatched. After a completed prewalk handoff, resume validates the retained current model and current/admitted lineage grants, not the obsolete admission model; it neither broadens model grants nor rearms prewalk. No automatic replay, undo, process freezing, restart or cross-parent recovery is provided.
|
|
162
162
|
|
|
163
|
-
An ancestor deadline marks its entire active subtree before draining any member. Resume the exact original parent generation first, then explicitly resume selected children; resuming a parent does not resume descendants. Existing no-permit-lending, writer ancestry and admission rules still apply. Parent completion
|
|
163
|
+
An ancestor deadline marks its entire active subtree before draining any member. Resume the exact original parent generation first, then explicitly resume selected children; resuming a parent does not resume descendants. Existing no-permit-lending, writer ancestry and admission rules still apply. Parent completion retires active/paused children, but preserves successfully completed retained child conversations for later explicit resume once that exact parent generation is running again. Explicit stop/retirement remains effective even across parent resume; failed/cancelled children cannot resume.
|
|
164
164
|
|
|
165
|
-
Resume rechecks operator/trusted-project limits and grants, ancestor spawn/capability ceilings, model availability/authentication, callable tools/provenance and writer/capacity admission. It never broadens original admission. A revoked retained grant rejects rather than
|
|
165
|
+
Resume rechecks operator/trusted-project limits and grants, ancestor spawn/capability ceilings, model availability/authentication, callable tools/provenance and writer/capacity admission. It never broadens original admission. A revoked retained grant rejects rather than silently changing the admitted SDK tool/resource graph; restore the grant or stop and launch a newly authorized identity. Policy/auth/capacity/restoration failure leaves the paused or completed conversation intact with an actionable tool error; there is no fallback model or replacement agent. Concurrent duplicate resumes reject atomically. Stop/shutdown wins a concurrent pending resume and disposes retained sessions.
|
|
166
166
|
|
|
167
167
|
Requests/tools remain hard cancellation guards. The first committed hard-limit reason (`requests` or `tools`) is retained and produces final `status:"cancelled"`, `limitReason`, and explanatory `error`. Stop before setup cancels without SDK setup/transcript. Request guards check **before forwarding** to the parent's public registry. Counts include failed dispatches but not rejected over-limit dispatches, auth preflight or provider-internal retries/subrequests. Tool guards count entered, granted custom-tool executions, including permission-denied forwarded calls; malformed/unknown calls rejected by Pi before execution are not counted. Requests still bound loops of rejected tools.
|
|
168
168
|
|
|
@@ -212,7 +212,7 @@ Operator `coordination` grants selected `message`, `inbox`, `wait` actions; abse
|
|
|
212
212
|
| `status` | Root-only pinned `target`; returns `{snapshot,generations,agents}`. Snapshot/history describe assignments; agents describes current presence. Full detached details, bounded text preview. |
|
|
213
213
|
| `stop` | Root-only pinned current `target`; closes idle/parked presence or aborts/drains active subtree. Completed outcomes/files are unchanged. Stopped identities cannot revive. |
|
|
214
214
|
| `park` | Root-only current disposed idle target; records parked presence. Active parking rejects: stop active work explicitly. No live SDK session, shell, permit or writer lease is retained while idle or parked. |
|
|
215
|
-
| `resume` | Root-only drained paused `target` and nonblank `assignment` continuation. Returns the same identity/window snapshot and sends one notification after that resumed window drains. No schema replacement or descendant auto-resume.
|
|
215
|
+
| `resume` | Root-only drained paused or successfully completed `target` and nonblank `assignment` continuation. Returns the same identity/window snapshot and sends one notification after that resumed window drains. No schema replacement or descendant auto-resume. |
|
|
216
216
|
| `followup` / `revive` | Root-only current target and nonblank `assignment`, optional supported `resultSchema`. Followup requires idle; revive requires parked. Returns the new admitted snapshot, not final success. Use wait/status for completion; no unsolicited duplicate generation-completion message is added. |
|
|
217
217
|
|
|
218
218
|
A message returns `{id,sender,recipient,text,mode,status,error?}`. `accepted` means mailbox admission, `queued` means the public SDK accepted a steer/followUp, `handled` means an SDK input handler consumed it, `delivered` means the exact message entered the recipient transcript or an inbox tool/wait returned it. None means model acknowledgment, understanding or assignment completion. `not-running` means no running recipient (including an undelivered receipt whose recipient ended), and `error` preserves delivery errors. Unknown/foreign/stale identities or receipts reject visibly, not as apparent successful delivery. Inbox messages are not automatically steered; steer/followUp are also retained in the bounded mailbox. Their `delivered` state comes from actual SDK user-message events, not queue acceptance. Message text is literal prefixed data, not tool authority.
|
|
@@ -227,7 +227,7 @@ Followup/revive re-resolve operator/trusted-project policy and selected root mod
|
|
|
227
227
|
|
|
228
228
|
The UUID stays stable and generation increments atomically **only after** synchronous admission checks. Concurrent renewals race on the original reference; exactly one can replace it. A newly owned generation directory `<id>-g<N>` holds its SDK session, `agent/`, transcript and exclusive artifacts. Generation 1 keeps `<id>/`. For these completed-agent fresh generations, no old files are opened for continuation, consulted, replayed, appended or migrated. The new prompt contains only the new explicit assignment plus current role/resources and identity; provide any relevant prior conclusions explicitly. This deliberately avoids retained-conversation replay/tool execution and does not claim a warm resumed Pi session.
|
|
229
229
|
|
|
230
|
-
Descendant renewal requires its **exact original** `parentId+parentGeneration` still active, non-cancelling and authorized. Current ancestor spawn roles, depth/limits, remaining spawn count, immediate nested capacity and writer ancestry all revalidate before generation mutation/setup. Replaced/disposed/stopped ancestors reject; the caller must delegate a new identity through an authorized live parent, never reparent the old one.
|
|
230
|
+
Descendant renewal requires its **exact original** `parentId+parentGeneration` still active, non-cancelling and authorized. Current ancestor spawn roles, depth/limits, remaining spawn count, immediate nested capacity and writer ancestry all revalidate before generation mutation/setup. Replaced/disposed/stopped ancestors reject; the caller must delegate a new identity through an authorized live parent, never reparent the old one. Explicit parent stop closes descendant idle/parked presence too. Successful parent completion does not retire already-successful retained descendant conversations; their explicit resume still requires the exact original active parent generation. Old callbacks, steering, stops, submissions, message delivery and waits capture the originating entry/reference, never retarget by latest UUID. Wait outcomes remain pinned even if a later generation is admitted. Shutdown/reload closes all presence and waiters, drains actual resources and suppresses old-runtime final messages; no cross-parent/process revival exists.
|
|
231
231
|
|
|
232
232
|
## Writer coordination and unsupported shell boundary
|
|
233
233
|
|
|
@@ -256,7 +256,7 @@ Hub names are snapshot-derived assignment headlines plus role, not a naming regi
|
|
|
256
256
|
| Outcome wait | Hub `w` → native event wait with explicit 1000ms bound; native tool supports 1–60000ms outcome/inbox/receipt waits with existing deadlock/refusal rules. |
|
|
257
257
|
| Stop subtree | Hub `x` → pinned target → `y` confirmation → existing stop/drain, retaining capacity/writer until disposal. Queued/setup/running/paused UI targets supported; historical/pausing/draining/disposed UI targets refuse, including transitions during pinned input. `/subagent-stop` and native root stop retain existing semantics. |
|
|
258
258
|
| Park | Hub `p` or native root tool; only disposed idle current identity with valid original parent. No warm SDK retained. |
|
|
259
|
-
| Followup/revive | **Native model-issued `delegate_coordinate`
|
|
259
|
+
| Followup/revive | **Native model-issued `delegate_coordinate` followup/revive only**. Idle/parked assignments use fresh session/generation/current narrowed authority. `subagent` resume continues paused or successfully completed conversations with full restored context and unchanged identity/generation/session count. Both require the exact active original parent for descendants. Hub command context lacks `tools/executeTool`: it cannot safely start a generation; f/r only explain refusal, allocate nothing and dispatch nothing. |
|
|
260
260
|
| Child coordination/spawn/model authority | Coordination/model authority remains operator default-off; spawn defaults to scout/review only. All remain project/request/ancestor subset-only; the UI cannot mint grants or impersonate a child. |
|
|
261
261
|
| Manual !/!!, external editors/terminals, arbitrary extension JS | Uncoordinated; model-tool-only writer boundary, never a shell ban/wrapper/sandbox. |
|
|
262
262
|
| Supplied workspace / production isolation | Explicit path/shell-cwd adaptation through root hooks is supported for existing supplied workspaces. Filesystem sandboxing, managed worktrees, copying/apply and cleanup remain unimplemented; cwd is not a resource grant. |
|