@oai404iao/pi-subagent 0.3.0 → 0.4.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +250 -75
- package/agents/worker.md +1 -1
- package/config.example.json +3 -1
- package/config.schema.json +24 -4
- package/package.json +7 -7
- package/src/agent-state.ts +125 -0
- package/src/agent-sync.ts +64 -53
- package/src/agents.ts +3 -22
- package/src/catalog.ts +49 -0
- package/src/completion-mailbox.ts +656 -0
- package/src/config.ts +51 -6
- package/src/coordinator.ts +2385 -231
- package/src/descriptor.ts +104 -11
- package/src/index.ts +175 -26
- package/src/mailbox.ts +451 -0
- package/src/providers.ts +221 -28
- package/src/render.ts +25 -8
- package/src/scheduler.ts +173 -0
- package/src/schemas.ts +111 -11
- package/src/task-path.ts +188 -0
- package/src/types.ts +56 -7
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ The design independently adapts the
|
|
|
5
5
|
[DeepSeek Harness subagent seam](https://github.com/deepseek-ai/deepseek-harness/tree/4d03472cd098dc48a630e526ca620f4f37f18a0e/docs/subsystems)
|
|
6
6
|
to Pi's extension and SDK APIs.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Peer floor: Pi 0.84.2; tested against 0.84.2 and 0.85.1.
|
|
9
9
|
|
|
10
10
|
> npm identity: `@oai404iao/pi-subagent`. Once the selected version is
|
|
11
11
|
> available on npm, install it from npm; use a local checkout before its
|
|
@@ -15,21 +15,29 @@ Compatibility: Pi 0.84.2 or newer; tested against 0.84.2.
|
|
|
15
15
|
|
|
16
16
|
- **Named providers**
|
|
17
17
|
- `spawn`: fresh child with no parent conversation
|
|
18
|
-
- `fork`:
|
|
18
|
+
- `fork`: child seeded through the parent's latest completed turn
|
|
19
|
+
- **Readable task paths** such as `/root/review/auth`, with relative addressing
|
|
20
|
+
- **Explicit context inheritance**: `fresh`, `all_completed`, or
|
|
21
|
+
`last_n_completed`
|
|
19
22
|
- **Two lifecycles**
|
|
20
23
|
- foreground one-shot runs return the child's final answer
|
|
21
|
-
- background continuable runs return a
|
|
24
|
+
- background continuable runs return a readable path and stable agent id at
|
|
25
|
+
prompt acceptance
|
|
22
26
|
- **Foreground-only policy** that removes background scheduling and lifecycle controls
|
|
23
27
|
- **Independent context and session** for every child
|
|
24
|
-
- **
|
|
25
|
-
|
|
28
|
+
- **User-owned agent catalog** with bundled templates used only for
|
|
29
|
+
first-install and package-version initialization
|
|
26
30
|
- **Durable descriptors and lineage** stored in child JSONL sessions
|
|
27
|
-
- **
|
|
31
|
+
- **Two background protocols**: compatible immediate follow-ups or an opt-in
|
|
32
|
+
durable mailbox with explicit turn starts
|
|
33
|
+
- **Quiet durable completion updates** with event-driven `wait_agent`
|
|
28
34
|
- **Control plane** with listing and interruption
|
|
29
35
|
- **Child-to-parent `report` channel** for continuable children
|
|
30
36
|
- **Nested delegation** with an absolute persisted depth limit
|
|
31
37
|
- **Dynamic agent-name enums** generated from the effective user/project catalog
|
|
32
38
|
- **Parallel-safe delegation**: multiple `subagent` calls in one assistant message may overlap
|
|
39
|
+
- **Bounded background execution** with per-agent cold-resume serialization
|
|
40
|
+
- **Optional idle runtime LRU** with transparent cold resume
|
|
33
41
|
- **Composable tool ceilings** that preserve model/extension tool decisions
|
|
34
42
|
- **Usage accounting, streaming progress, output caps, and custom TUI rendering**
|
|
35
43
|
|
|
@@ -57,17 +65,19 @@ For a temporary test:
|
|
|
57
65
|
pi -e /absolute/path/to/pi-extensions/pi-subagent
|
|
58
66
|
```
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
Development is pinned to Pi `0.85.1`; full compatibility checks retain the `0.84.2` floor.
|
|
61
69
|
|
|
62
70
|
## Model-facing tools
|
|
63
71
|
|
|
64
72
|
| Tool | Behavior |
|
|
65
73
|
| --- | --- |
|
|
66
|
-
| `subagent` | Starts a
|
|
67
|
-
| `subagent_fork` | Starts a
|
|
68
|
-
| `send_message` |
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
74
|
+
| `subagent` | Starts a named child with selectable context inheritance. Background continuable mode is the default unless configured otherwise; foreground-only mode always waits for the answer. |
|
|
75
|
+
| `subagent_fork` | Starts a child with all completed parent turns. It remains foreground by default; `run_in_background: true` creates a continuable fork. |
|
|
76
|
+
| `send_message` | Targets a direct child by path or durable id. Legacy starts/joins the next FIFO turn; `mailbox-v2` only durably appends. |
|
|
77
|
+
| `followup_task` | `mailbox-v2` only: targets a direct child by path or id, atomically claims the pending FIFO batch, and starts one scheduled turn. |
|
|
78
|
+
| `wait_agent` | `mailbox-v2` only: waits event-driven for unread direct-child completions without starting a model turn or consuming a scheduler slot. |
|
|
79
|
+
| `interrupt_agent` | Requests cancellation of a live descendant by path or id without deleting its session. Active only when background execution is enabled. |
|
|
80
|
+
| `list_agents` | Lists readable descendant paths as `running`, `idle`, or `ready`, including separate `pending=N` task and `updates=N` completion counts. Active only when background execution is enabled. |
|
|
71
81
|
| `report` | Child-only return channel. Installed automatically in continuable children. |
|
|
72
82
|
|
|
73
83
|
The `/subagents` command shows the effective scheduling mode, available agent definitions,
|
|
@@ -92,52 +102,118 @@ Use subagent_fork with planner to plan the change using our completed discussion
|
|
|
92
102
|
List my subagents, then send the scout a follow-up asking for exact call sites.
|
|
93
103
|
```
|
|
94
104
|
|
|
105
|
+
With `"backgroundProtocol": "mailbox-v2"`, enqueue first and start explicitly:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
Send the scout two mailbox messages, then call followup_task once so it handles
|
|
109
|
+
the current FIFO batch in one turn. Call wait_agent when the next action needs
|
|
110
|
+
its quiet completion update.
|
|
111
|
+
```
|
|
112
|
+
|
|
95
113
|
Pi executes sibling tool calls in parallel, so this package deliberately accepts one delegation per `subagent` call instead of embedding a separate `tasks` array.
|
|
96
114
|
|
|
97
|
-
|
|
115
|
+
### Task paths and context
|
|
98
116
|
|
|
99
|
-
|
|
100
|
-
these bundled definitions are read directly from the package. Startup does
|
|
101
|
-
**not** create, replace, remove, or back up files in the Pi agent directory.
|
|
102
|
-
`/subagents` reports those defaults as `(bundled)`.
|
|
117
|
+
Every new child has an immutable path rooted at `/root`:
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
119
|
+
```text
|
|
120
|
+
/root
|
|
121
|
+
├─ review
|
|
122
|
+
│ └─ auth
|
|
123
|
+
└─ tests
|
|
124
|
+
```
|
|
106
125
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
3
|
|
126
|
+
Set `task_name` to choose the final path segment. Names use 1–64 lowercase
|
|
127
|
+
ASCII letters, digits, hyphens, or underscores. If omitted, the extension
|
|
128
|
+
slugs `description` and appends `-2`, `-3`, and so on to avoid sibling
|
|
129
|
+
collisions. Explicit duplicate sibling names fail before child creation.
|
|
130
|
+
|
|
131
|
+
Control tools retain their existing parameter names for compatibility, but
|
|
132
|
+
accept any of:
|
|
133
|
+
|
|
134
|
+
- a durable UUIDv7 agent id;
|
|
135
|
+
- an absolute path such as `/root/review/auth`;
|
|
136
|
+
- a path relative to the caller, such as `auth`, `./auth`, or `../tests`.
|
|
137
|
+
|
|
138
|
+
References cannot escape `/root`. Path lookup is resolved to the durable agent
|
|
139
|
+
id before per-agent serialization; mailbox ownership, events, and durable
|
|
140
|
+
lineage remain UUID-based. Direct-child restrictions still apply to
|
|
141
|
+
`send_message` and `followup_task`, while `interrupt_agent` still requires a
|
|
142
|
+
descendant. Paths do not bypass those checks.
|
|
143
|
+
|
|
144
|
+
`subagent` accepts an optional context object:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"task_name": "review",
|
|
149
|
+
"context": {
|
|
150
|
+
"mode": "last_n_completed",
|
|
151
|
+
"completed_turns": 2
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
110
155
|
|
|
111
|
-
|
|
112
|
-
when project scope is enabled. Project agents are disabled by the default
|
|
113
|
-
`agentScope: "user"`. Setting the scope to `project` explicitly selects only
|
|
114
|
-
project definitions; `both` loads bundled definitions, user overrides, then
|
|
115
|
-
project overrides.
|
|
156
|
+
Context modes are:
|
|
116
157
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
158
|
+
| Mode | Initial child context |
|
|
159
|
+
| --- | --- |
|
|
160
|
+
| `fresh` | No parent conversation. This is the compatible `subagent` default. |
|
|
161
|
+
| `all_completed` | The parent's compaction-aware context through its latest completed assistant turn. |
|
|
162
|
+
| `last_n_completed` | The last `completed_turns` complete parent turns, bounded to 1–100. |
|
|
163
|
+
|
|
164
|
+
The active assistant/tool-call suffix is always excluded. A compaction summary
|
|
165
|
+
is retained when it is the only safe representation of completed history; if
|
|
166
|
+
it prevents exact turn counting, `last_n_completed` keeps that summary only
|
|
167
|
+
when fewer than the requested number of explicit completed turns remain.
|
|
168
|
+
Context is copied once into a new child session. Descriptor, lineage, mailbox,
|
|
169
|
+
completion, and other plain extension-state entries are not copied.
|
|
170
|
+
|
|
171
|
+
`subagent_fork` is the compatibility shortcut for `all_completed`. It remains
|
|
172
|
+
foreground unless `run_in_background: true` is explicitly supplied, even when
|
|
173
|
+
`defaultBackground` is true. A background fork is continuable and supports the
|
|
174
|
+
same legacy or mailbox-v2 follow-up lifecycle as a fresh child.
|
|
175
|
+
|
|
176
|
+
New sessions persist descriptor version 3 with their task path and context
|
|
177
|
+
policy. Version-2 descriptors remain readable and controllable by UUID; they
|
|
178
|
+
are displayed under the deterministic compatibility namespace
|
|
179
|
+
`/root/.legacy/<agent-id>`.
|
|
121
180
|
|
|
122
|
-
|
|
181
|
+
## Agent definitions
|
|
123
182
|
|
|
124
|
-
|
|
125
|
-
|
|
183
|
+
The package ships `scout`, `planner`, `reviewer`, and `worker` as initialization
|
|
184
|
+
templates. On the first extension startup after installation, and whenever the
|
|
185
|
+
detected package version changes, those templates are materialized into:
|
|
126
186
|
|
|
127
187
|
```text
|
|
128
188
|
<Pi agent dir>/agents/*.md
|
|
129
189
|
```
|
|
130
190
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
191
|
+
The package copies are **never runtime agent definitions or fallbacks**.
|
|
192
|
+
Runtime discovery reads only:
|
|
193
|
+
|
|
194
|
+
1. `<Pi agent dir>/agents/*.md`
|
|
195
|
+
2. nearest trusted `.pi/agents/*.md`
|
|
196
|
+
|
|
197
|
+
Project definitions replace user definitions with the same name when project
|
|
198
|
+
scope is enabled. Project agents are disabled by the default
|
|
199
|
+
`agentScope: "user"`. Setting the scope to `project` selects only project
|
|
200
|
+
definitions; `both` loads user definitions followed by project overrides.
|
|
201
|
+
|
|
202
|
+
After the current package version has been initialized, the user directory is
|
|
203
|
+
authoritative. Same-version startups do not restore missing files or refresh
|
|
204
|
+
changed templates. If the user deletes every agent definition, the effective
|
|
205
|
+
catalog is empty and delegation tools are inactive after restart or `/reload`.
|
|
206
|
+
A later package-version change starts a new initialization pass and installs
|
|
207
|
+
missing bundled templates again.
|
|
208
|
+
|
|
209
|
+
Initialization behavior:
|
|
134
210
|
|
|
135
211
|
1. **First startup:** missing presets are installed. A different pre-existing same-name file
|
|
136
212
|
is backed up before the bundled version replaces it.
|
|
137
213
|
2. **Ordinary restart of the same release:** user edits are preserved.
|
|
138
214
|
3. **Plugin update:** differing user presets are backed up, then replaced with the new
|
|
139
|
-
bundled versions. A bundled prompt
|
|
140
|
-
|
|
215
|
+
bundled versions. A bundled prompt change without a package-version change does not
|
|
216
|
+
trigger a refresh.
|
|
141
217
|
4. **Retired preset:** a formerly bundled name is backed up and removed so an obsolete
|
|
142
218
|
prompt does not remain silently active.
|
|
143
219
|
5. Files whose names were never managed bundled presets are left untouched.
|
|
@@ -146,8 +222,10 @@ Synchronization holds a cross-process lock, then preflights and stages the whole
|
|
|
146
222
|
before changing agent files. If a commit fails, it rolls back already-applied changes and
|
|
147
223
|
fails extension startup rather than falling back to package prompts. Same-name symbolic
|
|
148
224
|
links are preserved as symbolic links inside the backup directory before the user path is
|
|
149
|
-
replaced. An invalid synchronization manifest is copied to a
|
|
150
|
-
|
|
225
|
+
replaced. An invalid synchronization manifest is copied to a content-addressed
|
|
226
|
+
`.corrupt-*` file and skips template initialization; user and project agent discovery
|
|
227
|
+
continues with a warning. Repair the manifest, or deliberately remove it to request a new
|
|
228
|
+
first-install initialization pass.
|
|
151
229
|
|
|
152
230
|
Synchronization state and backups live at:
|
|
153
231
|
|
|
@@ -236,10 +314,12 @@ See [`config.example.json`](config.example.json) and [`config.schema.json`](conf
|
|
|
236
314
|
{
|
|
237
315
|
"$schema": "/path/to/pi-subagent/config.schema.json",
|
|
238
316
|
"agentScope": "user",
|
|
239
|
-
"syncBundledAgents": false,
|
|
240
317
|
"maxDepth": 3,
|
|
241
318
|
"enableRunInBackground": true,
|
|
242
319
|
"defaultBackground": true,
|
|
320
|
+
"maxConcurrentBackgroundRuns": 4,
|
|
321
|
+
"maxIdleRuntimes": 0,
|
|
322
|
+
"backgroundProtocol": "legacy",
|
|
243
323
|
"reportDelivery": "wakeup",
|
|
244
324
|
"inheritExtensions": false,
|
|
245
325
|
"openAIIdentity": false,
|
|
@@ -250,17 +330,23 @@ See [`config.example.json`](config.example.json) and [`config.schema.json`](conf
|
|
|
250
330
|
| Setting | Default | Meaning |
|
|
251
331
|
| --- | --- | --- |
|
|
252
332
|
| `agentScope` | `user` | Select user definitions, project definitions, or user definitions followed by project overrides. |
|
|
253
|
-
| `syncBundledAgents` | `false` | **User-level config only.** Opt in to writing managed bundled presets into `<Pi agent dir>/agents`. `true` may install, replace, retire, and back up those files. |
|
|
254
333
|
| `maxDepth` | `3` | Absolute delegation depth; a top-level Pi session is depth 0. |
|
|
255
334
|
| `enableRunInBackground` | `true` | Enable continuable background children and their model-facing lifecycle controls. Set `false` for strict foreground-only mode. |
|
|
256
|
-
| `defaultBackground` | `true` | Default scheduling for
|
|
257
|
-
| `
|
|
335
|
+
| `defaultBackground` | `true` | Default scheduling for `subagent` calls when background execution is enabled. `subagent_fork` remains foreground unless explicitly requested. |
|
|
336
|
+
| `maxConcurrentBackgroundRuns` | `4` | Maximum continuable subagent turns executing at once in one extension runtime. Additional top-level runs wait in FIFO order; nested work fails at capacity instead of deadlocking its parent turn. |
|
|
337
|
+
| `maxIdleRuntimes` | `0` | Process-wide LRU capacity for settled continuable runtimes. `0` preserves immediate unload; a positive value keeps the most recently used idle runtimes and transparently cold-resumes evicted paths. |
|
|
338
|
+
| `backgroundProtocol` | `legacy` | `legacy` preserves immediate `send_message` turns. `mailbox-v2` makes `send_message` enqueue-only and requires `followup_task` to start a turn. The protocol is snapshotted in each child descriptor. |
|
|
339
|
+
| `reportDelivery` | `wakeup` | Controls explicit `report` calls: `wakeup` starts/queues a parent turn; `quiet` waits for the parent's next turn. Mailbox-v2 completion updates are always quiet. |
|
|
258
340
|
| `inheritExtensions` | `false` | Load other Pi extensions in child runtimes. This package filters itself out; explicit agent tool ceilings still apply. |
|
|
259
341
|
| `openAIIdentity` | `false` | For OpenAI Responses child models, inject only the named `pi-codex-minimal-tools` identity lifecycle inline. Codex Session/Thread/Turn/Window ids remain owned and serialized by that package. |
|
|
260
|
-
| `maxOutputBytes` | `51200` | Cap for parent-visible foreground output, reports, and settlement notices. Full output remains in the child session. |
|
|
342
|
+
| `maxOutputBytes` | `51200` | Cap for parent-visible foreground output, reports, completion updates, and legacy settlement notices. Full output remains in the child session. |
|
|
261
343
|
|
|
262
344
|
Invalid configuration and unknown child tool names fail loud before the child's first model request.
|
|
263
345
|
|
|
346
|
+
The retired user-level `syncBundledAgents` key from versions 0.2 and 0.3 is
|
|
347
|
+
accepted for configuration compatibility but ignored. Template initialization
|
|
348
|
+
is now automatic and runtime discovery never reads bundled definitions.
|
|
349
|
+
|
|
264
350
|
`openAIIdentity` and `inheritExtensions` are independent. The former adds only
|
|
265
351
|
the lightweight Codex identity lifecycle even when normal extension inheritance
|
|
266
352
|
is disabled. Enable `inheritExtensions` as well when the child should receive
|
|
@@ -285,14 +371,15 @@ In this mode:
|
|
|
285
371
|
- `run_in_background` is removed from the model-facing schema at session startup;
|
|
286
372
|
- a forced `run_in_background: true` call is rejected before a child is created;
|
|
287
373
|
- nested subagents inherit the foreground-only policy through the durable runtime snapshot;
|
|
288
|
-
- `send_message`, `interrupt_agent`, and `list_agents` are removed from the active
|
|
374
|
+
- `send_message`, `followup_task`, `wait_agent`, `interrupt_agent`, and `list_agents` are removed from the active
|
|
289
375
|
model tool set, including inside nested children;
|
|
290
376
|
- sibling foreground calls may still execute in parallel in one assistant message.
|
|
291
377
|
|
|
292
|
-
`subagent_fork`
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
378
|
+
`subagent_fork` remains foreground in this mode and its `run_in_background`
|
|
379
|
+
field is removed too. The `/subagents` command remains available for human
|
|
380
|
+
inspection of historical children, but persisted continuable children cannot
|
|
381
|
+
be resumed until background execution is re-enabled. Run `/reload` or restart
|
|
382
|
+
Pi after changing this setting so the active tool set and displayed schema are
|
|
296
383
|
refreshed.
|
|
297
384
|
|
|
298
385
|
## Lifecycle
|
|
@@ -313,42 +400,131 @@ The caller waits for one isolated child run. Only the child's last non-empty ass
|
|
|
313
400
|
|
|
314
401
|
### Continuable
|
|
315
402
|
|
|
316
|
-
The start tool resolves at prompt preflight acceptance and returns the child's
|
|
317
|
-
agent id (UUIDv7). Agent ids are independent of
|
|
403
|
+
The start tool resolves at prompt preflight acceptance and returns the child's
|
|
404
|
+
readable task path plus stable agent id (UUIDv7). Agent ids are independent of
|
|
405
|
+
Pi session (file) ids: they are
|
|
318
406
|
generated once per subagent, recorded in the child's session as `pi-subagent/agent`,
|
|
319
407
|
and chained through `parentAgentId` in the descriptor, so children stay addressable
|
|
320
408
|
even when a parent session is forked or re-created. When an activation settles:
|
|
321
409
|
|
|
322
|
-
1.
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
410
|
+
1. `legacy` sends the parent its existing wakeup settlement; `mailbox-v2`
|
|
411
|
+
appends a quiet completion update to the direct parent's session instead;
|
|
412
|
+
2. once owned descendants are done, the child runtime is either disposed or
|
|
413
|
+
retained in the optional idle LRU;
|
|
414
|
+
3. an unloaded persistent session is `ready`; a retained settled runtime is
|
|
415
|
+
`idle`;
|
|
416
|
+
4. legacy `send_message`, or mailbox-v2 `followup_task`, can cold-resume that
|
|
417
|
+
same session for another turn.
|
|
418
|
+
|
|
419
|
+
A child can explicitly call `report` before settlement. Reports retain
|
|
420
|
+
`reportDelivery` behavior and are separate from quiet mailbox-v2 completions.
|
|
421
|
+
|
|
422
|
+
Continuable turns share a bounded scheduler. Calls targeting the same durable
|
|
423
|
+
agent are serialized so concurrent messages cannot create multiple cold
|
|
424
|
+
runtimes for one child session. Every scheduler-admitted run has a stable
|
|
425
|
+
`turnId` in delegation details and the paired `pi-subagent:turn-start` /
|
|
426
|
+
`pi-subagent:turn-end` events. FIFO follow-ups accepted while that
|
|
427
|
+
`AgentSession` is already running remain part of the same admitted run.
|
|
428
|
+
Existing `pi-subagent:start` / `pi-subagent:end` events continue to describe
|
|
429
|
+
the wider activation lifecycle and now include `taskPath`.
|
|
430
|
+
|
|
431
|
+
With `maxIdleRuntimes: 0`, disposal behavior is unchanged. A positive value
|
|
432
|
+
retains only settled continuable runtimes with no active run, owned descendant,
|
|
433
|
+
or pending mailbox claim. LRU accounting is serialized across concurrent
|
|
434
|
+
settlements. Eviction disposes only the runtime; the descriptor, path, context,
|
|
435
|
+
session history, task mailbox, and completion mailbox remain durable, so the
|
|
436
|
+
next accepted turn cold-resumes normally.
|
|
437
|
+
|
|
438
|
+
#### Mailbox-v2
|
|
439
|
+
|
|
440
|
+
Set `"backgroundProtocol": "mailbox-v2"` to separate delivery from execution:
|
|
441
|
+
|
|
442
|
+
1. `send_message` appends a bounded message record to the direct child's JSONL
|
|
443
|
+
session and returns its stable message id. It does not create a runtime,
|
|
444
|
+
acquire a scheduler permit, create a `turnId`, or emit turn events.
|
|
445
|
+
2. `followup_task` snapshots the current pending FIFO prefix, waits for the
|
|
446
|
+
normal background scheduler, and starts one turn containing that batch.
|
|
447
|
+
Messages arriving after the snapshot remain pending for a later turn.
|
|
448
|
+
3. A claim is committed only after Pi prompt preflight succeeds. The durable
|
|
449
|
+
user-turn marker makes a claim without its corresponding prompt recoverable
|
|
450
|
+
after a crash. Once the user turn is durable, the batch is consumed even if
|
|
451
|
+
that model turn later fails or is interrupted.
|
|
452
|
+
4. Scheduler rejection, cancellation while queued, and shutdown before prompt
|
|
453
|
+
acceptance leave the batch pending. Concurrent sends and starts for one
|
|
454
|
+
agent are serialized within the extension process.
|
|
455
|
+
5. A completed turn appends a stable completion record to the direct parent's
|
|
456
|
+
separate notification mailbox before the child unloads. This custom entry
|
|
457
|
+
does not enter model context and does not wake or start the parent.
|
|
458
|
+
6. `wait_agent` returns existing unread updates immediately or subscribes to
|
|
459
|
+
in-process mailbox activity and rechecks durable state after wakeup. Its
|
|
460
|
+
optional timeout defaults to 30 seconds and is capped at 120 seconds.
|
|
461
|
+
7. A returned update becomes read only after Pi durably appends the successful
|
|
462
|
+
`wait_agent` tool result. An interrupted/failed delivery is released at the
|
|
463
|
+
end of the parent turn; a process restart also makes an orphan reservation
|
|
464
|
+
available again. Delivery output is bounded to a 256 KiB FIFO prefix.
|
|
465
|
+
8. If the parent completion append fails, the child records an undelivered
|
|
466
|
+
fallback in its own session and emits `pi-subagent:completion-error` before
|
|
467
|
+
normal residency cleanup; no false completion is exposed to `wait_agent`.
|
|
468
|
+
|
|
469
|
+
Each message is limited to 131,072 characters; a mailbox is limited to 256 pending
|
|
470
|
+
messages and 256 KiB of pending UTF-8 content. `list_agents` exposes task
|
|
471
|
+
`pending` and completion `updates` independently from lifecycle and scheduler
|
|
472
|
+
state.
|
|
473
|
+
|
|
474
|
+
FIFO follows durable append order after target resolution, not the invocation
|
|
475
|
+
order of concurrent `send_message` calls. Each returned `pendingMessages` count
|
|
476
|
+
describes that append. If one message must precede another, await the first send
|
|
477
|
+
before starting the next.
|
|
478
|
+
|
|
479
|
+
`mailbox-v2` is opt-in. Existing descriptors without a protocol field resume as
|
|
480
|
+
`legacy`, and the default legacy tool behavior is unchanged. A persisted
|
|
481
|
+
mailbox-v2 child keeps its protocol snapshot. `followup_task` and `wait_agent` remain available
|
|
482
|
+
when such a child exists even if the current default is later changed back to
|
|
483
|
+
legacy.
|
|
484
|
+
|
|
485
|
+
`wait_agent` observes only completions written by the current agent's direct
|
|
486
|
+
children. Nested parents consume their own child updates; a root wait does not
|
|
487
|
+
steal grandchild updates. Legacy settlements and all explicit reports retain
|
|
488
|
+
their previous behavior.
|
|
489
|
+
|
|
490
|
+
### Inherited-context boundary
|
|
491
|
+
|
|
492
|
+
The parent is executing a tool when an inherited-context child starts, so its
|
|
493
|
+
current assistant/tool-result sequence is incomplete. The provider projects
|
|
494
|
+
Pi's active compaction-aware context only through a safe completed boundary,
|
|
495
|
+
then copies model-facing entries into a new child session. This avoids seeding
|
|
496
|
+
an invalid unbalanced tool turn and prevents parent control-log records from
|
|
497
|
+
becoming child descriptors or mailbox ownership.
|
|
332
498
|
|
|
333
499
|
## Security
|
|
334
500
|
|
|
335
501
|
- Extensions and subagents run with the user's OS permissions.
|
|
336
|
-
-
|
|
337
|
-
agent directory and may create backups under
|
|
338
|
-
`<Pi agent dir>/.pi-subagent/backups`.
|
|
339
|
-
paths.
|
|
502
|
+
- First-install and package-version initialization writes bundled templates
|
|
503
|
+
into the user agent directory and may create backups under
|
|
504
|
+
`<Pi agent dir>/.pi-subagent/backups`.
|
|
340
505
|
- Project-local agents are repository-controlled prompts. They are loaded only when the project is trusted and configuration enables project scope.
|
|
341
506
|
- `inheritExtensions` is disabled by default because loading an extension in a child executes its code and may duplicate external side effects.
|
|
342
507
|
- Explicit agent tool lists are enforced as registry ceilings, but this controls model visibility and execution composition rather than providing an OS sandbox.
|
|
343
|
-
- A child may send content only to its recorded direct parent through `report`;
|
|
508
|
+
- A child may send content only to its recorded direct parent through `report`;
|
|
509
|
+
path resolution is only an address lookup, and `send_message` /
|
|
510
|
+
`followup_task` still require direct-parent identity.
|
|
344
511
|
|
|
345
512
|
## Current limitations
|
|
346
513
|
|
|
347
|
-
- Activations
|
|
348
|
-
|
|
349
|
-
-
|
|
514
|
+
- Activations, scheduling ownership, and mailbox serialization are process-local;
|
|
515
|
+
two Pi processes must not concurrently control the same child session.
|
|
516
|
+
- Readable-path reservation and idle-LRU accounting are process-local. Durable
|
|
517
|
+
UUID identity remains authoritative when multiple processes are involved,
|
|
518
|
+
which is still unsupported.
|
|
519
|
+
- Resident parents still retain `ownedChildren` until descendants settle;
|
|
520
|
+
actor-graph residency, orphan handling, and background GC are not implemented.
|
|
521
|
+
- Pi lazily creates a new child JSONL file on its first assistant entry. The
|
|
522
|
+
initial background agent id therefore has a crash window after prompt
|
|
523
|
+
acceptance; mailbox-v2 `send_message` waits for that first durable checkpoint
|
|
524
|
+
before acknowledging an enqueue.
|
|
525
|
+
- Legacy `send_message` still has Pi's prompt-acceptance crash window. Use
|
|
526
|
+
`mailbox-v2` when delivery must be persisted before an explicit turn start.
|
|
350
527
|
- `interrupt_agent` is fire-and-return and relies on Pi's current `AgentSession.abort()` queue behavior.
|
|
351
|
-
- The fork provider is intentionally one-shot.
|
|
352
528
|
- Structured-output delegation is not implemented yet.
|
|
353
529
|
- Continuable starts require a persisted parent session; ephemeral (`--no-session`) parents can use foreground one-shot delegation only.
|
|
354
530
|
- `subagent_fork` needs a persisted parent to copy completed history; before the first completed turn its safe prefix is empty and it behaves like a fresh child.
|
|
@@ -368,6 +544,5 @@ The test suite includes provider-boundary, descriptor, configuration, discovery,
|
|
|
368
544
|
MIT © 2026 oai404iao. See [LICENSE](LICENSE) and
|
|
369
545
|
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
370
546
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
writing user files.
|
|
547
|
+
Bundled presets are initialization templates only. Runtime agent discovery is
|
|
548
|
+
limited to user and trusted project configuration.
|
package/agents/worker.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: worker
|
|
3
3
|
description: General-purpose implementation agent with coding tools
|
|
4
|
-
tools: read, grep, find, ls, bash, $mutation, subagent, subagent_fork, send_message, interrupt_agent, list_agents
|
|
4
|
+
tools: read, grep, find, ls, bash, $mutation, subagent, subagent_fork, send_message, followup_task, wait_agent, interrupt_agent, list_agents
|
|
5
5
|
thinking: high
|
|
6
6
|
---
|
|
7
7
|
|
package/config.example.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./config.schema.json",
|
|
3
3
|
"agentScope": "user",
|
|
4
|
-
"syncBundledAgents": false,
|
|
5
4
|
"maxDepth": 3,
|
|
6
5
|
"enableRunInBackground": true,
|
|
7
6
|
"defaultBackground": true,
|
|
7
|
+
"maxConcurrentBackgroundRuns": 4,
|
|
8
|
+
"maxIdleRuntimes": 0,
|
|
9
|
+
"backgroundProtocol": "legacy",
|
|
8
10
|
"reportDelivery": "wakeup",
|
|
9
11
|
"inheritExtensions": false,
|
|
10
12
|
"openAIIdentity": false,
|
package/config.schema.json
CHANGED
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"syncBundledAgents": {
|
|
21
21
|
"type": "boolean",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
22
|
+
"deprecated": true,
|
|
23
|
+
"description": "Retired user-level compatibility key from versions 0.2 and 0.3. It is validated but ignored; template initialization is automatic and bundled definitions are never used at runtime."
|
|
24
24
|
},
|
|
25
25
|
"maxDepth": {
|
|
26
26
|
"type": "integer",
|
|
@@ -36,13 +36,33 @@
|
|
|
36
36
|
},
|
|
37
37
|
"defaultBackground": {
|
|
38
38
|
"type": "boolean",
|
|
39
|
-
"description": "Default run mode for
|
|
39
|
+
"description": "Default run mode for subagent calls when background execution is enabled. subagent_fork remains foreground unless explicitly requested.",
|
|
40
40
|
"default": true
|
|
41
41
|
},
|
|
42
|
+
"maxConcurrentBackgroundRuns": {
|
|
43
|
+
"type": "integer",
|
|
44
|
+
"minimum": 1,
|
|
45
|
+
"maximum": 9007199254740991,
|
|
46
|
+
"description": "Maximum number of continuable subagent turns that may execute concurrently within one extension runtime.",
|
|
47
|
+
"default": 4
|
|
48
|
+
},
|
|
49
|
+
"maxIdleRuntimes": {
|
|
50
|
+
"type": "integer",
|
|
51
|
+
"minimum": 0,
|
|
52
|
+
"maximum": 9007199254740991,
|
|
53
|
+
"description": "Maximum settled continuable child runtimes retained in the process-wide idle LRU. Zero unloads immediately.",
|
|
54
|
+
"default": 0
|
|
55
|
+
},
|
|
56
|
+
"backgroundProtocol": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"enum": ["legacy", "mailbox-v2"],
|
|
59
|
+
"description": "Background message protocol. legacy starts or follows a turn from send_message; mailbox-v2 durably enqueues until followup_task explicitly starts one turn.",
|
|
60
|
+
"default": "legacy"
|
|
61
|
+
},
|
|
42
62
|
"reportDelivery": {
|
|
43
63
|
"type": "string",
|
|
44
64
|
"enum": ["wakeup", "quiet"],
|
|
45
|
-
"description": "Whether child reports trigger a parent turn or wait for the parent's next turn.",
|
|
65
|
+
"description": "Whether explicit child reports trigger a parent turn or wait for the parent's next turn. mailbox-v2 completion updates are always quiet.",
|
|
46
66
|
"default": "wakeup"
|
|
47
67
|
},
|
|
48
68
|
"inheritExtensions": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oai404iao/pi-subagent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-alpha.0",
|
|
4
4
|
"description": "Durable, continuable subagents for Pi with spawn/fork providers and lifecycle controls.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"typebox": "*"
|
|
39
39
|
},
|
|
40
40
|
"optionalDependencies": {
|
|
41
|
-
"@oai404iao/pi-codex-minimal-tools": "1.4.0"
|
|
41
|
+
"@oai404iao/pi-codex-minimal-tools": "1.4.1-alpha.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@earendil-works/pi-agent-core": "
|
|
45
|
-
"@earendil-works/pi-ai": "
|
|
46
|
-
"@earendil-works/pi-coding-agent": "
|
|
47
|
-
"@earendil-works/pi-tui": "
|
|
44
|
+
"@earendil-works/pi-agent-core": "0.85.1",
|
|
45
|
+
"@earendil-works/pi-ai": "0.85.1",
|
|
46
|
+
"@earendil-works/pi-coding-agent": "0.85.1",
|
|
47
|
+
"@earendil-works/pi-tui": "0.85.1",
|
|
48
48
|
"@types/node": "^26.2.0",
|
|
49
49
|
"tsx": "^4.20.6",
|
|
50
50
|
"typebox": "^1.1.24",
|
|
@@ -87,5 +87,5 @@
|
|
|
87
87
|
"optional": true
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "53026bf9e3f6a1d16a9c990e6034b49041928eab"
|
|
91
91
|
}
|