@melihmucuk/pi-crew 1.0.6 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-discovery.d.ts +0 -5
- package/dist/agent-discovery.js +1 -1
- package/dist/bootstrap-session.d.ts +13 -4
- package/dist/bootstrap-session.js +25 -16
- package/dist/index.js +37 -9
- package/dist/integration/register-command.d.ts +2 -2
- package/dist/integration/register-command.js +5 -5
- package/dist/integration/register-renderers.js +3 -0
- package/dist/integration/register-tools.d.ts +2 -2
- package/dist/integration/register-tools.js +2 -2
- package/dist/integration/tool-presentation.d.ts +2 -3
- package/dist/integration/tool-presentation.js +7 -8
- package/dist/integration/tools/crew-abort.d.ts +1 -1
- package/dist/integration/tools/crew-abort.js +3 -3
- package/dist/integration/tools/crew-done.d.ts +1 -1
- package/dist/integration/tools/crew-done.js +2 -2
- package/dist/integration/tools/crew-list.d.ts +1 -1
- package/dist/integration/tools/crew-list.js +3 -3
- package/dist/integration/tools/crew-respond.d.ts +1 -1
- package/dist/integration/tools/crew-respond.js +6 -7
- package/dist/integration/tools/crew-spawn.d.ts +1 -1
- package/dist/integration/tools/crew-spawn.js +17 -14
- package/dist/integration/tools/tool-deps.d.ts +3 -2
- package/dist/integration.d.ts +2 -2
- package/dist/integration.js +3 -3
- package/dist/runtime/crew-runtime.d.ts +61 -0
- package/dist/{crew-manager.js → runtime/crew-runtime.js} +84 -58
- package/dist/runtime/delivery-coordinator.d.ts +16 -7
- package/dist/runtime/delivery-coordinator.js +47 -21
- package/dist/runtime/subagent-registry.d.ts +1 -0
- package/dist/runtime/subagent-registry.js +3 -0
- package/dist/runtime/subagent-state.d.ts +2 -0
- package/dist/status-widget.d.ts +2 -2
- package/dist/status-widget.js +3 -3
- package/dist/subagent-messages.d.ts +5 -2
- package/dist/subagent-messages.js +5 -4
- package/docs/architecture.md +106 -847
- package/package.json +7 -7
- package/dist/crew-manager.d.ts +0 -44
package/docs/architecture.md
CHANGED
|
@@ -1,908 +1,167 @@
|
|
|
1
1
|
# pi-crew Architecture
|
|
2
2
|
|
|
3
|
-
This document explains the technical architecture of `@melihmucuk/pi-crew
|
|
3
|
+
This document explains the technical architecture of `@melihmucuk/pi-crew`, focusing on what makes this extension unique.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
For pi fundamentals, see pi docs: `extensions.md`, `sdk.md`, `session.md`. Project-level guardrails are in `AGENTS.md`.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## 1. What pi-crew adds
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
`pi-crew` is a non-blocking subagent orchestration extension. It lets one pi session delegate work to isolated subagent sessions without blocking the caller. Results are delivered back as `crew-result` custom messages.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Primary components:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- `extension/runtime/crew-runtime.ts` - Process-level singleton owning all subagent state
|
|
14
|
+
- `extension/runtime/subagent-registry.ts` - In-memory subagent registry
|
|
15
|
+
- `extension/runtime/delivery-coordinator.ts` - Owner-based result routing
|
|
16
|
+
- `extension/bootstrap-session.ts` - Subagent session construction with extension filtering
|
|
17
|
+
- `extension/agent-discovery.ts` - Subagent definition discovery and validation
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
## 2. Core runtime components
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
- a slash-command emergency abort path
|
|
19
|
-
- TUI renderers for subagent custom messages
|
|
20
|
-
- a live status widget for active subagents owned by the current session
|
|
21
|
-
- bundled subagent definitions and a bundled review prompt template
|
|
21
|
+
### 2.1 CrewRuntime singleton
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
- `package.json`
|
|
26
|
-
- `extension/index.ts`
|
|
27
|
-
- `README.md`
|
|
28
|
-
|
|
29
|
-
## 2. Architectural goals
|
|
30
|
-
|
|
31
|
-
The extension is built around a few explicit goals:
|
|
32
|
-
|
|
33
|
-
1. **Keep the caller session interactive**
|
|
34
|
-
The main session must not block while background work is happening.
|
|
35
|
-
|
|
36
|
-
2. **Preserve session isolation**
|
|
37
|
-
Each subagent gets its own pi SDK session, context window, and resolved tool/skill set.
|
|
38
|
-
|
|
39
|
-
3. **Route results to the owning session**
|
|
40
|
-
Results are not sent to whichever session happens to be active. They are sent to the session that created the subagent.
|
|
41
|
-
|
|
42
|
-
4. **Make multi-agent work understandable in the TUI**
|
|
43
|
-
Users need visible state, clear completion messages, and an emergency stop path.
|
|
44
|
-
|
|
45
|
-
5. **Stay behavior-first**
|
|
46
|
-
Agent definitions, tool restrictions, and delivery semantics are designed as explicit contracts, not incidental implementation details.
|
|
47
|
-
|
|
48
|
-
Project-level guardrails that define these contracts live in:
|
|
49
|
-
|
|
50
|
-
- `AGENTS.md`
|
|
51
|
-
|
|
52
|
-
## 3. Package layout and extension surface
|
|
53
|
-
|
|
54
|
-
### 3.1 Package registration in pi
|
|
55
|
-
|
|
56
|
-
`pi-crew` is packaged as a pi extension package.
|
|
57
|
-
|
|
58
|
-
Registration metadata lives in:
|
|
59
|
-
|
|
60
|
-
- `package.json`
|
|
61
|
-
|
|
62
|
-
Important package-level behaviors:
|
|
63
|
-
|
|
64
|
-
- `pi.extensions` points pi to the built extension entry at `./dist/index.js`
|
|
65
|
-
- `pi.prompts` exposes the bundled prompt template directory at `./prompts`
|
|
66
|
-
- `agents/` is shipped as package data and auto-discovered as the lowest-priority source during agent discovery
|
|
67
|
-
|
|
68
|
-
### 3.2 Repository structure
|
|
69
|
-
|
|
70
|
-
Main implementation areas:
|
|
71
|
-
|
|
72
|
-
- `extension/` - runtime extension logic
|
|
73
|
-
- `extension/runtime/` - in-memory state and delivery coordination
|
|
74
|
-
- `extension/integration/` - pi tool, command, and renderer registration
|
|
75
|
-
- `agents/` - bundled subagent definitions
|
|
76
|
-
- `prompts/` - bundled prompt templates
|
|
77
|
-
|
|
78
|
-
## 4. Core runtime components
|
|
79
|
-
|
|
80
|
-
### 4.1 Extension bootstrap
|
|
81
|
-
|
|
82
|
-
File:
|
|
83
|
-
|
|
84
|
-
- `extension/index.ts`
|
|
85
|
-
|
|
86
|
-
Responsibilities:
|
|
87
|
-
|
|
88
|
-
- instantiate one `CrewManager` for the extension runtime
|
|
89
|
-
- observe pi session lifecycle events
|
|
90
|
-
- activate delivery routing when the active pi session changes
|
|
91
|
-
- abort owned abortable subagents when an owner session shuts down
|
|
92
|
-
- register tools, command, and message renderers
|
|
93
|
-
- refresh the status widget when state changes
|
|
94
|
-
|
|
95
|
-
Session lifecycle events used by the extension:
|
|
96
|
-
|
|
97
|
-
- `session_start`
|
|
98
|
-
- `session_switch`
|
|
99
|
-
- `session_fork`
|
|
100
|
-
- `session_shutdown`
|
|
101
|
-
|
|
102
|
-
This is the bridge between pi core events and `pi-crew` runtime behavior.
|
|
103
|
-
|
|
104
|
-
### 4.2 Crew manager
|
|
105
|
-
|
|
106
|
-
File:
|
|
107
|
-
|
|
108
|
-
- `extension/crew-manager.ts`
|
|
109
|
-
|
|
110
|
-
`CrewManager` is the main orchestration service.
|
|
111
|
-
|
|
112
|
-
It owns the extension’s operational workflow:
|
|
113
|
-
|
|
114
|
-
- create subagent state records
|
|
115
|
-
- bootstrap isolated subagent sessions
|
|
116
|
-
- send prompts into subagent sessions
|
|
117
|
-
- interpret prompt outcomes
|
|
118
|
-
- transition subagents between `running`, `waiting`, `done`, `error`, and `aborted`
|
|
119
|
-
- deliver results back to the owner session
|
|
120
|
-
- enforce ownership checks for `respond`, `done`, and owned abort paths
|
|
121
|
-
- dispose finished subagents
|
|
122
|
-
|
|
123
|
-
In practice, `CrewManager` is the coordination layer above the registry and delivery subsystems.
|
|
124
|
-
|
|
125
|
-
### 4.3 Subagent registry
|
|
126
|
-
|
|
127
|
-
Files:
|
|
128
|
-
|
|
129
|
-
- `extension/runtime/subagent-registry.ts`
|
|
130
|
-
- `extension/runtime/subagent-state.ts`
|
|
131
|
-
|
|
132
|
-
Responsibilities:
|
|
133
|
-
|
|
134
|
-
- store live in-memory subagent state in a `Map`
|
|
135
|
-
- generate unique runtime IDs such as `<name>-<hex>`
|
|
136
|
-
- filter subagents by owner session
|
|
137
|
-
- provide summaries for the TUI widget and abort command
|
|
138
|
-
- count other still-running subagents for ordered delivery notes
|
|
139
|
-
|
|
140
|
-
Important architectural property:
|
|
141
|
-
|
|
142
|
-
- the registry is **in-memory only**
|
|
143
|
-
- active subagents are therefore runtime-scoped, not globally persistent across process restarts
|
|
144
|
-
|
|
145
|
-
However, per project rules, subagent session files themselves are intentionally not cleaned up, so post-hoc inspection through pi session history remains possible.
|
|
146
|
-
|
|
147
|
-
### 4.4 Delivery coordinator
|
|
148
|
-
|
|
149
|
-
File:
|
|
150
|
-
|
|
151
|
-
- `extension/runtime/delivery-coordinator.ts`
|
|
152
|
-
|
|
153
|
-
This component solves one of the most important architecture problems in the extension: **how to deliver background results to the correct session at the correct time**.
|
|
23
|
+
`CrewRuntime` is a process-level singleton that survives pi runtime replacement (`/resume`, `/new`, `/fork`). When pi discards an old extension instance and creates a new one, the new instance reconnects to the same `crewRuntime` and picks up existing subagent state.
|
|
154
24
|
|
|
155
25
|
Responsibilities:
|
|
156
26
|
|
|
157
|
-
-
|
|
158
|
-
-
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
- preserve ordering between the main result message and the optional “remaining subagents” note
|
|
162
|
-
|
|
163
|
-
This separation keeps delivery logic independent from spawning logic.
|
|
164
|
-
|
|
165
|
-
## 5. Integration with pi
|
|
166
|
-
|
|
167
|
-
### 5.1 Registered tools
|
|
168
|
-
|
|
169
|
-
Files:
|
|
170
|
-
|
|
171
|
-
- `extension/integration/register-tools.ts`
|
|
172
|
-
- `extension/integration/tools/crew-list.ts`
|
|
173
|
-
- `extension/integration/tools/crew-spawn.ts`
|
|
174
|
-
- `extension/integration/tools/crew-abort.ts`
|
|
175
|
-
- `extension/integration/tools/crew-respond.ts`
|
|
176
|
-
- `extension/integration/tools/crew-done.ts`
|
|
177
|
-
|
|
178
|
-
The extension registers five tools:
|
|
179
|
-
|
|
180
|
-
- `crew_list`
|
|
181
|
-
- `crew_spawn`
|
|
182
|
-
- `crew_abort`
|
|
183
|
-
- `crew_respond`
|
|
184
|
-
- `crew_done`
|
|
185
|
-
|
|
186
|
-
These are the primary public API for LLM-driven orchestration.
|
|
187
|
-
|
|
188
|
-
Behavioral contracts:
|
|
189
|
-
|
|
190
|
-
- `crew_list` shows discovered subagent definitions and active subagents owned by the current session
|
|
191
|
-
- `crew_spawn` starts a non-blocking subagent owned by the current session
|
|
192
|
-
- `crew_abort` can abort one, many, or all active subagents owned by the current session
|
|
193
|
-
- `crew_respond` continues a waiting interactive subagent without blocking the caller session
|
|
194
|
-
- `crew_done` closes a waiting interactive subagent without emitting a duplicate completion message
|
|
195
|
-
|
|
196
|
-
### 5.2 Registered command
|
|
197
|
-
|
|
198
|
-
File:
|
|
199
|
-
|
|
200
|
-
- `extension/integration/register-command.ts`
|
|
201
|
-
|
|
202
|
-
The extension also registers the `/pi-crew-abort` command.
|
|
203
|
-
|
|
204
|
-
This command differs from `crew_abort` in one important way:
|
|
205
|
-
|
|
206
|
-
- it is intentionally unrestricted across sessions
|
|
207
|
-
|
|
208
|
-
It exists as an emergency escape hatch. This is a deliberate operational tool, not an ownership-safe automation surface.
|
|
209
|
-
|
|
210
|
-
### 5.3 Custom message renderers
|
|
211
|
-
|
|
212
|
-
Files:
|
|
213
|
-
|
|
214
|
-
- `extension/integration/register-renderers.ts`
|
|
215
|
-
- `extension/subagent-messages.ts`
|
|
216
|
-
|
|
217
|
-
The extension defines two custom message types:
|
|
218
|
-
|
|
219
|
-
- `crew-result`
|
|
220
|
-
- `crew-remaining`
|
|
221
|
-
|
|
222
|
-
These render in the TUI with custom formatting so asynchronous subagent output is readable and visually distinct from normal assistant text.
|
|
223
|
-
|
|
224
|
-
### 5.4 Status widget
|
|
225
|
-
|
|
226
|
-
File:
|
|
227
|
-
|
|
228
|
-
- `extension/status-widget.ts`
|
|
229
|
-
|
|
230
|
-
When the current session owns active subagents, a live widget shows:
|
|
231
|
-
|
|
232
|
-
- subagent ID
|
|
233
|
-
- the latest assistant-reported model name, or `…` before the first assistant turn ends
|
|
234
|
-
- turn count
|
|
235
|
-
- the latest `assistant.usage.totalTokens` value, displayed as `ctx`
|
|
236
|
-
- running vs waiting state
|
|
237
|
-
|
|
238
|
-
This widget is session-scoped. It only shows subagents owned by the currently active session.
|
|
239
|
-
|
|
240
|
-
## 6. Subagent definition model
|
|
241
|
-
|
|
242
|
-
### 6.1 Discovery sources and priority
|
|
243
|
-
|
|
244
|
-
File:
|
|
245
|
-
|
|
246
|
-
- `extension/agent-discovery.ts`
|
|
247
|
-
|
|
248
|
-
Subagent definitions are discovered from three directories in priority order:
|
|
249
|
-
|
|
250
|
-
1. **Project**: `<cwd>/.pi/agents/*.md`
|
|
251
|
-
2. **User global**: `~/.pi/agent/agents/*.md`
|
|
252
|
-
3. **Bundled**: `agents/` in the package
|
|
253
|
-
|
|
254
|
-
When the same subagent name exists in multiple sources, the higher-priority source wins silently. Duplicate names within the same directory produce a warning.
|
|
255
|
-
|
|
256
|
-
If a directory does not exist, it is skipped without warnings.
|
|
257
|
-
|
|
258
|
-
### 6.2 Definition format
|
|
259
|
-
|
|
260
|
-
Each subagent is a Markdown file with YAML frontmatter plus a Markdown body.
|
|
261
|
-
|
|
262
|
-
Frontmatter fields currently recognized by the runtime:
|
|
263
|
-
|
|
264
|
-
- `name`
|
|
265
|
-
- `description`
|
|
266
|
-
- `model`
|
|
267
|
-
- `thinking`
|
|
268
|
-
- `tools`
|
|
269
|
-
- `skills`
|
|
270
|
-
- `compaction`
|
|
271
|
-
- `interactive`
|
|
272
|
-
|
|
273
|
-
The Markdown body becomes appended system prompt content for the spawned subagent session.
|
|
274
|
-
|
|
275
|
-
### 6.3 JSON override sources and precedence
|
|
276
|
-
|
|
277
|
-
File:
|
|
278
|
-
|
|
279
|
-
- `extension/agent-discovery.ts`
|
|
280
|
-
|
|
281
|
-
After `.md` discovery, the runtime loads optional per-agent override config from two JSON files:
|
|
282
|
-
|
|
283
|
-
- global: `~/.pi/agent/pi-crew.json`
|
|
284
|
-
- project: `<cwd>/.pi/pi-crew.json`
|
|
285
|
-
|
|
286
|
-
Only these fields are overridable:
|
|
287
|
-
|
|
288
|
-
- `model`
|
|
289
|
-
- `thinking`
|
|
290
|
-
- `tools`
|
|
291
|
-
- `skills`
|
|
292
|
-
- `compaction`
|
|
293
|
-
- `interactive`
|
|
294
|
-
|
|
295
|
-
`name` and `description` are never overridable.
|
|
296
|
-
|
|
297
|
-
Merge behavior:
|
|
298
|
-
|
|
299
|
-
- global config is loaded first
|
|
300
|
-
- project config is loaded second
|
|
301
|
-
- project overrides global for the same subagent and field
|
|
302
|
-
- if both files define the same subagent, unspecified fields from global remain unless project overrides them
|
|
303
|
-
|
|
304
|
-
### 6.4 Validation and fallback behavior
|
|
305
|
-
|
|
306
|
-
Key behaviors implemented in discovery and bootstrap:
|
|
307
|
-
|
|
308
|
-
- missing or empty `name` or `description` makes the definition invalid and it is ignored
|
|
309
|
-
- names cannot contain whitespace
|
|
310
|
-
- later duplicate names are skipped once an earlier valid definition with the same name has been loaded
|
|
311
|
-
- `model` must use `provider/model-id` format to be considered valid
|
|
312
|
-
- invalid model format is ignored for model resolution with a warning
|
|
313
|
-
- invalid `thinking` values are ignored with a warning
|
|
314
|
-
- invalid `tools` or `skills` field formats produce a warning and are treated as empty lists in frontmatter
|
|
315
|
-
- unknown tools are filtered out with a warning
|
|
316
|
-
- unknown skills are not part of discovery validation; when `skills` is present, bootstrap filters against the loaded skill set, omits unknown names, and writes a `console.warn`
|
|
317
|
-
- non-boolean `compaction` or `interactive` values in frontmatter are ignored without a warning
|
|
318
|
-
|
|
319
|
-
Override-specific validation behavior:
|
|
320
|
-
|
|
321
|
-
- override entry value must be a JSON object
|
|
322
|
-
- unknown override fields produce warnings
|
|
323
|
-
- non-overridable fields (`name`, `description`) produce warnings
|
|
324
|
-
- invalid field types in overrides produce warnings and are ignored
|
|
325
|
-
- invalid `model`/`thinking` values in overrides produce warnings and are ignored
|
|
326
|
-
- invalid `tools`/`skills` formats in overrides produce warnings and are ignored
|
|
327
|
-
- unknown tool names in override `tools` produce warnings; valid names in the same list are still applied
|
|
328
|
-
- override entries for undiscovered subagent names produce warnings and are ignored
|
|
329
|
-
|
|
330
|
-
Important semantic distinction:
|
|
331
|
-
|
|
332
|
-
- omitted `tools` means “use the full supported tool allowlist”
|
|
333
|
-
- omitted `skills` means “do not install a `skillsOverride`, so all skills from the base resource loader remain available”
|
|
334
|
-
- explicit empty `tools` or `skills` means “grant none”
|
|
335
|
-
|
|
336
|
-
That distinction matters for both end users and coding agents authoring subagent definitions.
|
|
337
|
-
|
|
338
|
-
### 6.5 Supported tool set for spawned subagents
|
|
339
|
-
|
|
340
|
-
File:
|
|
341
|
-
|
|
342
|
-
- `extension/tool-registry.ts`
|
|
343
|
-
|
|
344
|
-
The current built-in tool allowlist for spawned subagents is:
|
|
345
|
-
|
|
346
|
-
- `read`
|
|
347
|
-
- `bash`
|
|
348
|
-
- `edit`
|
|
349
|
-
- `write`
|
|
350
|
-
- `grep`
|
|
351
|
-
- `find`
|
|
352
|
-
- `ls`
|
|
353
|
-
|
|
354
|
-
Important limitation:
|
|
355
|
-
|
|
356
|
-
- tool restriction here is a pi tool-resolution choice, not an OS sandbox boundary
|
|
357
|
-
- for example, a “read-only” subagent remains read-only because of instruction and selected tool capabilities, not because of a kernel-level confinement model
|
|
358
|
-
|
|
359
|
-
## 7. Session bootstrapping and isolation
|
|
360
|
-
|
|
361
|
-
### 7.1 How a subagent session is created
|
|
362
|
-
|
|
363
|
-
File:
|
|
364
|
-
|
|
365
|
-
- `extension/bootstrap-session.ts`
|
|
366
|
-
|
|
367
|
-
When `crew_spawn` is executed, the runtime does not clone the current conversation directly. It creates a new agent session with explicit configuration.
|
|
368
|
-
|
|
369
|
-
Bootstrapping responsibilities:
|
|
370
|
-
|
|
371
|
-
- resolve the target model
|
|
372
|
-
- resolve the selected tool set
|
|
373
|
-
- construct a `DefaultResourceLoader`
|
|
374
|
-
- optionally filter skills
|
|
375
|
-
- append the subagent system prompt body
|
|
376
|
-
- create an in-memory settings manager for compaction settings
|
|
377
|
-
- create a new `SessionManager`
|
|
378
|
-
- call `sessionManager.newSession({ parentSession: parentSessionFile })` before creating the agent session
|
|
379
|
-
- create the actual `AgentSession`
|
|
380
|
-
|
|
381
|
-
### 7.2 Parent-child session linkage
|
|
382
|
-
|
|
383
|
-
A critical implementation rule is that the subagent session must be created through `SessionManager.newSession({ parentSession })`.
|
|
384
|
-
|
|
385
|
-
The current caller session file is passed when one exists. This is the supported way to preserve parent-child linkage for resumable sessions. Project rules explicitly forbid creating subagent sessions through the wrong session factory because it breaks lifecycle expectations.
|
|
386
|
-
|
|
387
|
-
Architectural rationale is documented in:
|
|
388
|
-
|
|
389
|
-
- `AGENTS.md`
|
|
390
|
-
|
|
391
|
-
### 7.3 Preventing recursive orchestration
|
|
392
|
-
|
|
393
|
-
One of the most important safety guards in the system is this:
|
|
394
|
-
|
|
395
|
-
- spawned subagent sessions must not load the `pi-crew` extension again
|
|
396
|
-
|
|
397
|
-
This is enforced by filtering the extension out through `extensionsOverride` inside the resource loader.
|
|
398
|
-
|
|
399
|
-
Why it matters:
|
|
400
|
-
|
|
401
|
-
- if a subagent can access `crew_spawn`, it can create more subagents
|
|
402
|
-
- that creates recursive or runaway orchestration loops
|
|
403
|
-
- preventing that at session bootstrap time is far safer than relying on prompt instructions alone
|
|
404
|
-
|
|
405
|
-
### 7.4 Model resolution
|
|
406
|
-
|
|
407
|
-
The runtime resolves models in two stages:
|
|
408
|
-
|
|
409
|
-
1. if the subagent definition does not specify a valid parsed model, the caller session model is reused
|
|
410
|
-
2. if a model is specified but not found in the active pi model registry, the runtime falls back to the caller session model and writes a `console.warn`
|
|
411
|
-
|
|
412
|
-
This keeps execution resilient to local model availability differences.
|
|
413
|
-
|
|
414
|
-
### 7.5 Compaction behavior
|
|
415
|
-
|
|
416
|
-
Each subagent session gets its own in-memory settings manager.
|
|
417
|
-
|
|
418
|
-
Behavior:
|
|
419
|
-
|
|
420
|
-
- `compaction` defaults to `true` if omitted
|
|
421
|
-
- a definition can explicitly disable it
|
|
422
|
-
|
|
423
|
-
This setting is applied per spawned session and does not reuse the caller session's compaction setting.
|
|
424
|
-
|
|
425
|
-
## 8. Spawn lifecycle
|
|
426
|
-
|
|
427
|
-
### 8.1 High-level flow
|
|
428
|
-
|
|
429
|
-
Relevant files:
|
|
430
|
-
|
|
431
|
-
- `extension/integration/tools/crew-spawn.ts`
|
|
432
|
-
- `extension/crew-manager.ts`
|
|
433
|
-
- `extension/bootstrap-session.ts`
|
|
434
|
-
|
|
435
|
-
Behavior sequence:
|
|
436
|
-
|
|
437
|
-
1. The `crew_spawn` tool handler calls `discoverAgents()` to load the current subagent definitions.
|
|
438
|
-
2. The requested subagent name is resolved against that discovery result.
|
|
439
|
-
3. The current session ID becomes the subagent owner ID.
|
|
440
|
-
4. `CrewManager.spawn()` creates a registry entry with status `running` and returns a runtime subagent ID immediately.
|
|
441
|
-
5. `CrewManager` starts asynchronous session bootstrap in the background.
|
|
442
|
-
6. Once bootstrapped, the new subagent session receives the task string as its prompt.
|
|
443
|
-
7. Completion or failure is delivered later as a `crew-result` custom message. If the owner session is already streaming, that message is delivered with `deliverAs: "steer"`.
|
|
444
|
-
|
|
445
|
-
This immediate-return plus background-execution split is the key non-blocking contract of the extension.
|
|
446
|
-
|
|
447
|
-
### 8.2 Runtime metrics during execution
|
|
448
|
-
|
|
449
|
-
`CrewManager` subscribes to subagent `turn_end` events.
|
|
450
|
-
|
|
451
|
-
Tracked metrics include:
|
|
452
|
-
|
|
453
|
-
- turn count, incremented on each `turn_end`
|
|
454
|
-
- the latest `assistant.usage.totalTokens` value seen on a `turn_end`
|
|
455
|
-
- the latest assistant-reported model name
|
|
456
|
-
|
|
457
|
-
These metrics power the status widget and active subagent summaries.
|
|
458
|
-
|
|
459
|
-
### 8.3 Prompt outcome interpretation
|
|
460
|
-
|
|
461
|
-
After a prompt cycle completes, the runtime inspects the last assistant message in the subagent session.
|
|
462
|
-
|
|
463
|
-
Outcome mapping:
|
|
464
|
-
|
|
465
|
-
- assistant stop reason `error` -> subagent status `error`
|
|
466
|
-
- assistant stop reason `aborted` -> subagent status `aborted`
|
|
467
|
-
- normal completion with `interactive: true` -> subagent status `waiting`
|
|
468
|
-
- normal completion with non-interactive definition -> subagent status `done`
|
|
469
|
-
|
|
470
|
-
This means interactive subagents and non-interactive subagents share the same prompt execution flow up to the final state transition.
|
|
471
|
-
|
|
472
|
-
## 9. Delivery model and message ordering
|
|
473
|
-
|
|
474
|
-
### 9.1 Owner-based routing
|
|
475
|
-
|
|
476
|
-
The most important delivery rule is:
|
|
477
|
-
|
|
478
|
-
- results belong to the session that spawned the subagent
|
|
479
|
-
|
|
480
|
-
They do not belong to:
|
|
481
|
-
|
|
482
|
-
- the currently visible session
|
|
483
|
-
- the most recent session
|
|
484
|
-
- the session that called a command later
|
|
485
|
-
|
|
486
|
-
Ownership identity is based on the current session ID, not the session file path. This matters because unsaved or in-memory sessions may not have stable file paths.
|
|
487
|
-
|
|
488
|
-
### 9.2 Immediate vs deferred delivery
|
|
489
|
-
|
|
490
|
-
Relevant files:
|
|
491
|
-
|
|
492
|
-
- `extension/runtime/delivery-coordinator.ts`
|
|
493
|
-
- `extension/index.ts`
|
|
494
|
-
|
|
495
|
-
Delivery branches:
|
|
496
|
-
|
|
497
|
-
- if the owner session is currently active, the result is sent immediately
|
|
498
|
-
- if the owner session is not active, the result is queued in memory until that session becomes active again
|
|
499
|
-
|
|
500
|
-
Queued results are flushed when the extension sees that owner session through:
|
|
501
|
-
|
|
502
|
-
- `session_start`
|
|
503
|
-
- `session_switch`
|
|
504
|
-
- `session_fork`
|
|
505
|
-
|
|
506
|
-
### 9.3 Idle vs streaming session behavior
|
|
507
|
-
|
|
508
|
-
pi requires different delivery semantics depending on whether the target session is idle or already processing output.
|
|
509
|
-
|
|
510
|
-
Behavioral rule for a `crew-result` when no separate remaining-note ordering is needed:
|
|
511
|
-
|
|
512
|
-
- idle owner session -> send with `triggerTurn: true`
|
|
513
|
-
- streaming owner session -> send as steering content with `deliverAs: "steer"` and `triggerTurn: true`
|
|
514
|
-
|
|
515
|
-
When an idle owner also needs a `crew-remaining` note, section 9.5 describes the deliberate `triggerTurn: false` / `true` split used to preserve message order.
|
|
516
|
-
|
|
517
|
-
Why this distinction exists:
|
|
518
|
-
|
|
519
|
-
- sending `deliverAs: "steer"` to an idle session can leave the message unprocessed because there is no active turn loop
|
|
520
|
-
- when the owner session is already streaming, the extension injects the result into that active turn as steering content instead of using the idle-session delivery path
|
|
521
|
-
|
|
522
|
-
This is one of the most subtle but important integration details in the extension.
|
|
523
|
-
|
|
524
|
-
### 9.4 Deferred flush timing
|
|
525
|
-
|
|
526
|
-
Pending message flush after session activation is intentionally deferred to the next macrotask.
|
|
527
|
-
|
|
528
|
-
Reason:
|
|
529
|
-
|
|
530
|
-
- pi-core can emit `session_switch` before reconnecting the agent listener during resume flows
|
|
531
|
-
- synchronous message delivery at that moment can lose custom message persistence
|
|
532
|
-
|
|
533
|
-
This is why queued results are flushed asynchronously instead of synchronously during session activation.
|
|
534
|
-
|
|
535
|
-
### 9.5 Result and remaining-note ordering
|
|
536
|
-
|
|
537
|
-
Files:
|
|
538
|
-
|
|
539
|
-
- `extension/subagent-messages.ts`
|
|
540
|
-
- `extension/runtime/delivery-coordinator.ts`
|
|
541
|
-
|
|
542
|
-
When a result is delivered and other subagents from the same owner are still in `running` state, the extension may send two messages:
|
|
543
|
-
|
|
544
|
-
1. the `crew-result`
|
|
545
|
-
2. a separate `crew-remaining` note
|
|
546
|
-
|
|
547
|
-
They are intentionally separate messages.
|
|
548
|
-
|
|
549
|
-
Why:
|
|
550
|
-
|
|
551
|
-
- the result message should stay focused on one subagent outcome
|
|
552
|
-
- the remaining count is transient orchestration state, not part of that result payload
|
|
553
|
-
|
|
554
|
-
Ordering guarantee:
|
|
555
|
-
|
|
556
|
-
- the result must appear before the remaining-note message
|
|
557
|
-
|
|
558
|
-
When the owner is idle and other subagents are still running, the extension sends the `crew-result` with `triggerTurn: false`, then sends the remaining note with `triggerTurn: true` so the next turn processes both in order.
|
|
559
|
-
|
|
560
|
-
When the owner is already streaming, the extension sends the `crew-result` first with `deliverAs: "steer"` and `triggerTurn: true`, then sends the `crew-remaining` note after it with `deliverAs: "steer"` and `triggerTurn: false`.
|
|
561
|
-
|
|
562
|
-
The remaining count is computed at send time from the current registry state, not stored in the `crew-result` payload.
|
|
563
|
-
|
|
564
|
-
## 10. Interactive subagents
|
|
565
|
-
|
|
566
|
-
### 10.1 Waiting state
|
|
567
|
-
|
|
568
|
-
Interactive subagents are defined with `interactive: true` in frontmatter.
|
|
569
|
-
|
|
570
|
-
After a successful prompt cycle, they transition to `waiting` instead of `done`.
|
|
571
|
-
|
|
572
|
-
Meaning of `waiting`:
|
|
573
|
-
|
|
574
|
-
- the session remains alive
|
|
575
|
-
- the subagent can receive follow-up messages
|
|
576
|
-
- the status widget shows a waiting icon rather than a spinner
|
|
577
|
-
|
|
578
|
-
### 10.2 `crew_respond`
|
|
579
|
-
|
|
580
|
-
Relevant files:
|
|
581
|
-
|
|
582
|
-
- `extension/integration/tools/crew-respond.ts`
|
|
583
|
-
- `extension/crew-manager.ts`
|
|
584
|
-
|
|
585
|
-
Behavior:
|
|
586
|
-
|
|
587
|
-
- validate that the subagent exists
|
|
588
|
-
- validate that it belongs to the caller session
|
|
589
|
-
- validate that it is in `waiting` state
|
|
590
|
-
- mark it `running`
|
|
591
|
-
- asynchronously send the follow-up prompt
|
|
592
|
-
- return immediately to the caller
|
|
593
|
-
|
|
594
|
-
This is deliberately fire-and-forget. The response comes later as another `crew-result` message.
|
|
595
|
-
|
|
596
|
-
### 10.3 `crew_done`
|
|
597
|
-
|
|
598
|
-
Relevant files:
|
|
599
|
-
|
|
600
|
-
- `extension/integration/tools/crew-done.ts`
|
|
601
|
-
- `extension/crew-manager.ts`
|
|
602
|
-
|
|
603
|
-
Behavior:
|
|
604
|
-
|
|
605
|
-
- validate existence, ownership, and `waiting` state
|
|
606
|
-
- dispose the session
|
|
607
|
-
- remove the subagent from the registry
|
|
608
|
-
- do **not** send another `crew-result` message
|
|
609
|
-
|
|
610
|
-
That last point is essential. The latest subagent response was already delivered when it entered `waiting`. Sending another completion custom message on `crew_done` would duplicate signal and create an unnecessary turn.
|
|
611
|
-
|
|
612
|
-
## 11. Abort semantics
|
|
613
|
-
|
|
614
|
-
### 11.1 Supported abort paths
|
|
615
|
-
|
|
616
|
-
There are three conceptually different abort sources:
|
|
617
|
-
|
|
618
|
-
1. tool-triggered aborts through `crew_abort`
|
|
619
|
-
2. unrestricted manual aborts through `/pi-crew-abort`
|
|
620
|
-
3. cleanup aborts when an owner session shuts down
|
|
621
|
-
|
|
622
|
-
Each path should report the real reason.
|
|
623
|
-
|
|
624
|
-
### 11.2 Owned abort behavior
|
|
625
|
-
|
|
626
|
-
Relevant files:
|
|
627
|
-
|
|
628
|
-
- `extension/integration/tools/crew-abort.ts`
|
|
629
|
-
- `extension/crew-manager.ts`
|
|
630
|
-
|
|
631
|
-
`crew_abort` supports exactly one mode per call:
|
|
632
|
-
|
|
633
|
-
- `subagent_id`
|
|
634
|
-
- `subagent_ids`
|
|
635
|
-
- `all: true`
|
|
636
|
-
|
|
637
|
-
It only operates on subagents owned by the current session.
|
|
638
|
-
|
|
639
|
-
The result separates:
|
|
640
|
-
|
|
641
|
-
- actually aborted IDs
|
|
642
|
-
- missing or already finished IDs
|
|
643
|
-
- IDs that belong to another session
|
|
644
|
-
|
|
645
|
-
### 11.3 Unrestricted command abort
|
|
646
|
-
|
|
647
|
-
Relevant file:
|
|
648
|
-
|
|
649
|
-
- `extension/integration/register-command.ts`
|
|
650
|
-
|
|
651
|
-
`/pi-crew-abort` can target any active abortable subagent, regardless of owner. This is not a bug. It is an explicit operational decision.
|
|
652
|
-
|
|
653
|
-
### 11.4 Session shutdown cleanup
|
|
654
|
-
|
|
655
|
-
Relevant file:
|
|
656
|
-
|
|
657
|
-
- `extension/index.ts`
|
|
658
|
-
|
|
659
|
-
On `session_shutdown`, the extension:
|
|
660
|
-
|
|
661
|
-
- aborts all abortable subagents currently owned by that session
|
|
662
|
-
- clears pending queued messages for that owner
|
|
663
|
-
|
|
664
|
-
This avoids memory leaks and prevents stale queued results from surviving after their owner session is gone.
|
|
665
|
-
|
|
666
|
-
## 12. Ownership and isolation rules
|
|
667
|
-
|
|
668
|
-
These are core architecture invariants, not optional conventions.
|
|
669
|
-
|
|
670
|
-
### 12.1 Owner identity
|
|
671
|
-
|
|
672
|
-
Owner identity uses the pi session ID.
|
|
673
|
-
|
|
674
|
-
Why:
|
|
675
|
-
|
|
676
|
-
- session file paths may be undefined for in-memory sessions
|
|
677
|
-
- file-path-based ownership can collapse multiple live sessions into the same logical owner
|
|
678
|
-
|
|
679
|
-
### 12.2 Session-scoped visibility
|
|
680
|
-
|
|
681
|
-
The following surfaces are ownership-restricted:
|
|
682
|
-
|
|
683
|
-
- `crew_list` active subagent section
|
|
684
|
-
- `crew_abort`
|
|
685
|
-
- `crew_respond`
|
|
686
|
-
- `crew_done`
|
|
687
|
-
- status widget
|
|
688
|
-
- owner cleanup on session shutdown
|
|
689
|
-
|
|
690
|
-
This prevents cross-session interference in normal tool-driven workflows.
|
|
691
|
-
|
|
692
|
-
### 12.3 What is intentionally not isolated
|
|
693
|
-
|
|
694
|
-
The emergency command `/pi-crew-abort` is intentionally cross-session.
|
|
695
|
-
|
|
696
|
-
This is the only major exception to normal ownership isolation.
|
|
697
|
-
|
|
698
|
-
## 13. User-facing message model
|
|
699
|
-
|
|
700
|
-
Relevant file:
|
|
701
|
-
|
|
702
|
-
- `extension/subagent-messages.ts`
|
|
703
|
-
|
|
704
|
-
Subagent outcome messaging is normalized into one common format.
|
|
705
|
-
|
|
706
|
-
Every `crew-result` payload includes:
|
|
707
|
-
|
|
708
|
-
- runtime subagent ID
|
|
709
|
-
- logical subagent name
|
|
710
|
-
- final status
|
|
711
|
-
- an optional body derived from the subagent result or error
|
|
712
|
-
|
|
713
|
-
In current completion and error paths, the runtime usually populates that body with assistant text, an error message, or `"(no output)"`.
|
|
714
|
-
|
|
715
|
-
`crew-remaining` is simpler. It carries display text only and does not attach structured `details`.
|
|
716
|
-
|
|
717
|
-
The `SubagentStatus` union currently includes:
|
|
718
|
-
|
|
719
|
-
- `running`
|
|
720
|
-
- `waiting`
|
|
721
|
-
- `done`
|
|
722
|
-
- `error`
|
|
723
|
-
- `aborted`
|
|
724
|
-
|
|
725
|
-
Current `crew-result` deliveries use `waiting`, `done`, `error`, or `aborted`. `running` is a live registry/widget state, not a completion message state.
|
|
726
|
-
|
|
727
|
-
## 14. Bundled subagents and prompt template
|
|
728
|
-
|
|
729
|
-
### 14.1 Bundled subagents
|
|
730
|
-
|
|
731
|
-
Files:
|
|
732
|
-
|
|
733
|
-
- `agents/scout.md`
|
|
734
|
-
- `agents/planner.md`
|
|
735
|
-
- `agents/oracle.md`
|
|
736
|
-
- `agents/worker.md`
|
|
737
|
-
- `agents/code-reviewer.md`
|
|
738
|
-
- `agents/quality-reviewer.md`
|
|
739
|
-
|
|
740
|
-
These are opinionated subagent definitions for common workflows.
|
|
741
|
-
|
|
742
|
-
They demonstrate how the extension is intended to be used:
|
|
743
|
-
|
|
744
|
-
- `scout` for quick investigation
|
|
745
|
-
- `planner` for interactive planning
|
|
746
|
-
- `oracle` for decision evaluation and blind spot detection
|
|
747
|
-
- `worker` for implementation
|
|
748
|
-
- `code-reviewer` for correctness review
|
|
749
|
-
- `quality-reviewer` for maintainability review
|
|
750
|
-
|
|
751
|
-
Architecturally, these files are not special-cased by the runtime. They are auto-discovered as the lowest-priority source (priority 3) and go through the same discovery and bootstrap pipeline as project-level or user-level definitions. Users can override any bundled subagent by placing a same-named `.md` file in `<cwd>/.pi/agents/` or `~/.pi/agent/agents/`.
|
|
752
|
-
|
|
753
|
-
### 14.2 Bundled plan orchestration prompt
|
|
754
|
-
|
|
755
|
-
File:
|
|
756
|
-
|
|
757
|
-
- `prompts/pi-crew-plan.md`
|
|
758
|
-
|
|
759
|
-
This prompt template orchestrates discovery and planning workflow.
|
|
760
|
-
|
|
761
|
-
It tells the orchestrating agent to:
|
|
762
|
-
|
|
763
|
-
- gather minimal orientation context
|
|
764
|
-
- spawn scout subagents to investigate specific areas
|
|
765
|
-
- collect and synthesize scout findings
|
|
766
|
-
- delegate planning to a planner subagent
|
|
767
|
-
- relay the planner's output to the user
|
|
768
|
-
|
|
769
|
-
The prompt enforces strict delegation boundaries:
|
|
770
|
-
|
|
771
|
-
- the orchestrator must not perform deep investigation itself
|
|
772
|
-
- the orchestrator must not write the plan itself
|
|
773
|
-
- detailed discovery belongs to scouts
|
|
774
|
-
- plan creation belongs to the planner
|
|
775
|
-
|
|
776
|
-
### 14.3 Bundled review orchestration prompt
|
|
777
|
-
|
|
778
|
-
File:
|
|
779
|
-
|
|
780
|
-
- `prompts/pi-crew-review.md`
|
|
27
|
+
- Create subagent state records
|
|
28
|
+
- Bootstrap isolated subagent sessions
|
|
29
|
+
- Transition subagents between states
|
|
30
|
+
- Deliver results to owner sessions
|
|
781
31
|
|
|
782
|
-
|
|
32
|
+
### 2.2 Delivery coordinator
|
|
783
33
|
|
|
784
|
-
|
|
34
|
+
Routes subagent results to the correct session at the correct time. Key behaviors:
|
|
785
35
|
|
|
786
|
-
-
|
|
787
|
-
-
|
|
788
|
-
-
|
|
789
|
-
-
|
|
36
|
+
- Tracks active session via `ActiveRuntimeBinding` (set on `session_start`, cleared on `session_shutdown`)
|
|
37
|
+
- Queues results when owner session is inactive
|
|
38
|
+
- Flushes queued results when owner session activates (`session_start` with `reason: "resume"` or `"fork"`)
|
|
39
|
+
- Uses `triggerTurn: false/true` split to preserve ordering between `crew-result` and `crew-remaining`
|
|
790
40
|
|
|
791
|
-
|
|
41
|
+
Underlying delivery: see pi's `sendMessage({ deliverAs, triggerTurn })` in extensions.md.
|
|
792
42
|
|
|
793
|
-
|
|
794
|
-
- prompts provide workflow policy
|
|
43
|
+
### 2.3 Subagent registry
|
|
795
44
|
|
|
796
|
-
|
|
45
|
+
In-memory, process-scoped: `Map<subagentId, SubagentState>`
|
|
797
46
|
|
|
798
|
-
|
|
47
|
+
- Owner session filtering
|
|
48
|
+
- Runtime ID generation (`<name>-<hex>`)
|
|
799
49
|
|
|
800
|
-
|
|
50
|
+
Does not persist across process restarts. Subagent session files remain for post-hoc inspection.
|
|
801
51
|
|
|
802
|
-
|
|
803
|
-
- `extension/integration/register-tools.ts`
|
|
52
|
+
## 3. Session bootstrapping
|
|
804
53
|
|
|
805
|
-
|
|
54
|
+
When `crew_spawn` executes:
|
|
806
55
|
|
|
807
|
-
|
|
56
|
+
1. Resolve subagent definition from discovery sources
|
|
57
|
+
2. Resolve model (fallback to caller session model if invalid)
|
|
58
|
+
3. Resolve tools, skills
|
|
59
|
+
4. Create `DefaultResourceLoader` with `extensionsOverride` that excludes `pi-crew`
|
|
60
|
+
5. Call `sessionManager.newSession({ parentSession })` for parent-child linkage
|
|
61
|
+
6. Create `AgentSession` with resolved configuration
|
|
62
|
+
7. Send task prompt asynchronously
|
|
808
63
|
|
|
809
|
-
-
|
|
810
|
-
- `crew_list` includes those warnings in its text output
|
|
811
|
-
- `crew_list` and `crew_spawn` both trigger one-time UI notifications when a UI is available
|
|
64
|
+
**Extension filtering:** Subagent sessions must not load `pi-crew` again. Prevents recursive orchestration loops.
|
|
812
65
|
|
|
813
|
-
|
|
66
|
+
## 4. Delivery model
|
|
814
67
|
|
|
815
|
-
|
|
68
|
+
### 4.1 Owner-based routing
|
|
816
69
|
|
|
817
|
-
|
|
70
|
+
Results belong to the session that spawned the subagent. Owner identity uses `getSessionId()`, not file path (in-memory sessions have undefined paths).
|
|
818
71
|
|
|
819
|
-
|
|
72
|
+
### 4.2 Idle vs streaming
|
|
820
73
|
|
|
821
|
-
|
|
74
|
+
Check owner session state before delivery:
|
|
822
75
|
|
|
823
|
-
|
|
76
|
+
- **Idle (`isIdle() = true`):** Send with `triggerTurn: true`
|
|
77
|
+
- **Streaming (`isIdle() = false`):** Send with `deliverAs: "steer"` and `triggerTurn: true`
|
|
824
78
|
|
|
825
|
-
|
|
79
|
+
Critical: `deliverAs: "steer"` to an idle session leaves the message unprocessed (no active turn loop).
|
|
826
80
|
|
|
827
|
-
|
|
81
|
+
### 4.3 Deferred flush
|
|
828
82
|
|
|
829
|
-
|
|
83
|
+
Pending message flush after `session_start` is deferred to next macrotask. Synchronous delivery loses custom message persistence (pi-core emits `session_start` before reconnecting agent listener during resume).
|
|
830
84
|
|
|
831
|
-
|
|
85
|
+
### 4.4 TTL cleanup
|
|
832
86
|
|
|
833
|
-
|
|
87
|
+
Pending messages older than 24 hours are discarded during `flushPending`.
|
|
834
88
|
|
|
835
|
-
|
|
836
|
-
- bundled prompt template availability
|
|
837
|
-
- copied subagent definition files in `~/.pi/agent/agents/`
|
|
838
|
-
- pi session history files created for subagents
|
|
89
|
+
## 5. Subagent state lifecycle
|
|
839
90
|
|
|
840
|
-
###
|
|
91
|
+
### 5.1 States
|
|
841
92
|
|
|
842
|
-
-
|
|
843
|
-
-
|
|
844
|
-
-
|
|
93
|
+
- `running` - Actively processing
|
|
94
|
+
- `waiting` - Interactive subagent awaiting `crew_respond` or `crew_done`
|
|
95
|
+
- `done` - Completed successfully
|
|
96
|
+
- `error` - Failed with error
|
|
97
|
+
- `aborted` - Cancelled
|
|
845
98
|
|
|
846
|
-
|
|
99
|
+
### 5.2 State transitions
|
|
847
100
|
|
|
848
|
-
|
|
101
|
+
After prompt cycle completion, inspect assistant stop reason:
|
|
849
102
|
|
|
850
|
-
|
|
103
|
+
- `stopReason: "error"` → status `error`
|
|
104
|
+
- `stopReason: "aborted"` → status `aborted`
|
|
105
|
+
- Normal completion + `interactive: true` → status `waiting`
|
|
106
|
+
- Normal completion + non-interactive → status `done`
|
|
851
107
|
|
|
852
|
-
|
|
853
|
-
2. Results must route to the owning session, not merely the currently active one.
|
|
854
|
-
3. Ownership must be based on session ID.
|
|
855
|
-
4. Subagent sessions must not load `pi-crew` again.
|
|
856
|
-
5. Interactive subagents must remain alive after responding until explicitly closed.
|
|
857
|
-
6. `crew_respond` must return immediately and deliver its result asynchronously later.
|
|
858
|
-
7. `crew_done` must clean up only and must not emit a duplicate result message.
|
|
859
|
-
8. When the owner session is inactive, result delivery must be queued and later flushed.
|
|
860
|
-
9. Result messages must appear before any “remaining subagents” note.
|
|
861
|
-
10. Session shutdown must abort owned abortable subagents and clear pending queued messages for that owner.
|
|
862
|
-
11. Tool ownership restrictions must remain strict, except for the emergency abort command.
|
|
108
|
+
### 5.3 Interactive subagents
|
|
863
109
|
|
|
864
|
-
|
|
110
|
+
`interactive: true` subagents enter `waiting` after each response. They accept follow-up messages via `crew_respond` until explicitly closed with `crew_done`. Closing does NOT emit a duplicate `crew-result`.
|
|
865
111
|
|
|
866
|
-
##
|
|
112
|
+
## 6. Ownership and isolation
|
|
867
113
|
|
|
868
|
-
|
|
114
|
+
Invariants:
|
|
869
115
|
|
|
870
|
-
1. `
|
|
871
|
-
|
|
116
|
+
1. `crew_list`, `crew_abort`, `crew_respond`, `crew_done`, status widget: session-scoped. Only owner sees/controls.
|
|
117
|
+
2. `/pi-crew-abort`: cross-session emergency escape hatch.
|
|
118
|
+
3. `session_shutdown` deactivates delivery binding only; subagents continue running. Abort happens on process exit.
|
|
872
119
|
|
|
873
|
-
|
|
874
|
-
Non-obvious architecture guardrails that must not regress.
|
|
120
|
+
## 7. Subagent definition model
|
|
875
121
|
|
|
876
|
-
|
|
877
|
-
Extension bootstrap and session event wiring.
|
|
122
|
+
Discovery priority:
|
|
878
123
|
|
|
879
|
-
|
|
880
|
-
|
|
124
|
+
1. Project: `<cwd>/.pi/agents/*.md`
|
|
125
|
+
2. User global: `~/.pi/agent/agents/*.md`
|
|
126
|
+
3. Bundled: `agents/` in package
|
|
881
127
|
|
|
882
|
-
|
|
883
|
-
Owner routing, queueing, and turn-trigger behavior.
|
|
128
|
+
Higher priority wins. Same-name duplicates in same directory produce warning.
|
|
884
129
|
|
|
885
|
-
|
|
886
|
-
Session construction, model/tool/skill resolution, and extension filtering.
|
|
130
|
+
Frontmatter: `name`, `description`, `model`, `thinking`, `tools`, `skills`, `compaction`, `interactive`
|
|
887
131
|
|
|
888
|
-
|
|
889
|
-
Subagent definition semantics and validation rules.
|
|
132
|
+
Tools/skills semantics:
|
|
890
133
|
|
|
891
|
-
|
|
892
|
-
|
|
134
|
+
- **Omitted:** Use full supported allowlist
|
|
135
|
+
- **Empty list (`tools: []`):** Grant none
|
|
893
136
|
|
|
894
|
-
|
|
895
|
-
Real workflow examples built on top of the runtime.
|
|
137
|
+
JSON overrides: `~/.pi/agent/pi-crew.json` (global), `<cwd>/.pi/pi-crew.json` (project). Project wins.
|
|
896
138
|
|
|
897
|
-
##
|
|
139
|
+
## 8. Behavioral invariants
|
|
898
140
|
|
|
899
|
-
|
|
141
|
+
1. Spawned subagent must not block caller session.
|
|
142
|
+
2. Results route to owning session (by ID), not currently active session.
|
|
143
|
+
3. Subagent sessions must not load `pi-crew`.
|
|
144
|
+
4. `crew_respond` returns immediately; result delivered asynchronously.
|
|
145
|
+
5. `crew_done` cleans up only; no duplicate result message.
|
|
146
|
+
6. Queued results flush when owner session becomes active.
|
|
147
|
+
7. `crew-result` messages appear before `crew-remaining` notes (ordering via `triggerTurn` split).
|
|
148
|
+
8. Pending messages preserved for inactive sessions; TTL (24h) prevents memory leak.
|
|
149
|
+
9. Active subagent state survives runtime replacement within same process.
|
|
900
150
|
|
|
901
|
-
|
|
902
|
-
- `npm run build`
|
|
151
|
+
## 9. Reading guide
|
|
903
152
|
|
|
904
|
-
|
|
153
|
+
1. `README.md` - Product surface
|
|
154
|
+
2. `AGENTS.md` - Architecture guardrails
|
|
155
|
+
3. `extension/index.ts` - Session event wiring
|
|
156
|
+
4. `extension/runtime/crew-runtime.ts` - Orchestration, state transitions
|
|
157
|
+
5. `extension/runtime/delivery-coordinator.ts` - Owner routing, queueing
|
|
158
|
+
6. `extension/bootstrap-session.ts` - Session construction
|
|
159
|
+
7. `extension/agent-discovery.ts` - Definition validation
|
|
160
|
+
8. `extension/integration/` - Tools, command, renderers
|
|
905
161
|
|
|
906
|
-
|
|
162
|
+
## 10. Verification
|
|
907
163
|
|
|
908
|
-
|
|
164
|
+
```bash
|
|
165
|
+
npm run typecheck
|
|
166
|
+
npm run build
|
|
167
|
+
```
|