pi-better-subagents 0.1.1 → 0.1.3

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 CHANGED
@@ -1,420 +1,43 @@
1
1
  # pi-better-subagents
2
2
 
3
- A better subagent extension for [pi](https://github.com/earendil-works/pi-coding-agent).
3
+ Detached, sandboxed subagents for [Pi](https://pi.dev).
4
4
 
5
- Not a clone of Claude Code's subagents — a rethink of what a subagent system
6
- should be: **autonomous, non-blocking, and safe by default.** You delegate work
7
- and keep going; each subagent runs on its own in an isolated process, confined to
8
- what it needs, and reports back when it's done. No blocking waits, no
9
- back-channel for it to stall on, no unbounded blast radius.
5
+ Delegate work and keep going. Each subagent runs in its own `pi -p` child process, reports back when finished, and leaves the foreground session free for the human.
10
6
 
11
- ```
12
- launch is the result · completion triggers fetch · the foreground never blocks
13
- ```
14
-
15
- ## Principles
16
-
17
- - **The foreground never blocks.** Launching a subagent *is* the deliverable —
18
- `subagent_spawn` starts a detached `pi -p` child and returns immediately,
19
- leaving the session free for the human. When the child finishes, it sends a
20
- lightweight trigger; the foreground calls `subagent_result` and presents the
21
- result (as a `followUp`, never cutting into work in progress). The foreground
22
- is nudged once, at completion — never on a wait/poll loop.
23
- - **Subagents are autonomous; communication is one-way (parent → child).** The
24
- parent front-loads everything the child needs into the spawn; the child runs to
25
- completion and **returns a result**. There is no mid-task child→parent blocking
26
- call for a subagent to waste wall-clock on — a child missing a piece of info
27
- resolves it from what it was given, or records it unavailable and returns.
28
- - **Safe by default.** Every subagent is OS-sandboxed — writes confined to its
29
- working directory, reads and network open — and scoped to an explicit tool
30
- allowlist. It can't corrupt the parent, escape its directory, or recurse into
31
- more subagents without opt-in.
32
- - **Observable.** A live status widget and on-demand queries show each run's
33
- elapsed time and token/cost spend.
34
-
35
- ## Tools
36
-
37
- | Tool | Blocks? | What it does |
38
- |------|---------|--------------|
39
- | `subagent_spawn` | never | Launch a task in a background subagent; returns a run id at once. Params: `prompt`, `name`, `model`, `tools` (allowlist), `exclude_tools`, `sandbox`, `sandbox_dir`, `callback`, `clean`, `cwd`, `git_clone_workspace`, `approve`, `allow_nested`. |
40
- | `subagent_spawn_batch` | never | Launch several independent subagents at once. Each job becomes a normal run. Params: `batchName`, `shared` (options applied to every job), `jobs[]` (each needs `prompt`; same optional params as `subagent_spawn`), `onCapacity` (`reject` or `launch-available`). |
41
- | `subagent_list` | never | List running/finished runs with status, model, elapsed, spend, and batch info. Params: `all`, `limit` (default 20, max 100; larger values are clamped), `status` (`running`, `completed`, `failed`, `killed`, `exited`, durable `orphaned`, `lost`). Degraded health facts (stale, long tool, compacting, model error, …) appear only when actionable. |
42
- | `subagent_output` | never | Tail a run's live output as it stands right now. Includes a `[health: …]` diagnostic for orphaned, lost, and degraded running runs; healthy/quiet stays quiet. |
43
- | `subagent_result` | never | Read a finished run's final output (says "still running" otherwise). For `orphaned` returns a non-final diagnostic plus best-current artifacts; for `lost` a terminal-unknown diagnostic plus best-available artifacts. In the TUI, the result is folded by default for display only; expanding the tool row shows the full bounded result, and the model-facing payload is unchanged. |
44
- | `subagent_stop` | never | SIGTERM a running run's process group. |
45
-
46
- ## Non-blocking, by construction
47
-
48
- - **Process isolation.** Each run is a `detached` + `unref`'d `pi -p` process.
49
- Its context can't clog the parent, its crash can't corrupt parent state, and
50
- its output is durable in a log file.
51
- - **Completion triggers a turn that fetches the result.** When the child exits,
52
- a lightweight trigger is sent with `pi.sendMessage(..., { deliverAs: "followUp", triggerTurn: true })` —
53
- it waits until the foreground agent has no pending tool calls (never cutting
54
- into work mid-stream), then the model calls `subagent_result` and presents the
55
- result. The actual result is never embedded in the trigger to avoid double-display.
56
- The run itself never blocks the foreground; the single nudge happens only at
57
- the end. Prefer `callback:false` to finish quietly and read the result on demand
58
- via `subagent_result`.
59
- - **The prompt guidelines forbid polling.** The foreground agent is told, in the
60
- tool guidelines, that spawning is done and it must not loop on `output`/`result`
61
- or sleep to wait.
62
-
63
- ## Autonomy & safety
64
-
65
- Every subagent is confined by default, and the confinement is **self-contained** —
66
- it does not depend on any other extension being installed.
7
+ ## Core Features
67
8
 
68
- - **OS sandbox (default on, macOS and Linux).** The child runs under
69
- `sandbox-exec` on macOS or [bubblewrap](https://github.com/containers/bubblewrap)
70
- (`bwrap`) on Linux with a simple rule: **reads and network are open; writes are
71
- confined to the working directory and host `/tmp`.** Kernel-enforced — unlike a
72
- cooperative guardrail that matches tool inputs, this denies the write syscall
73
- itself, so a crafted `bash` command can't escape it. `sandbox:false` lifts it;
74
- `sandbox_dir` moves the writable root (and becomes the child's cwd). `/dev`
75
- remains usable. macOS also permits pi state writes under `~/.pi`; Linux exposes
76
- that directory read-only, so Linux children must put writable pi state in their
77
- work directory or `/tmp`. Everything else (your home, the repo, `/etc`, …) is
78
- read-only to the subagent.
79
- - **Tool allowlist.** The child is scoped to an explicit set of tools, which also
80
- decides what extension code loads (see below).
81
- - **No runaway recursion.** A subagent cannot spawn its own subagents unless
82
- `allow_nested:true` — and not by denying the tools after the fact: without that
83
- flag this package isn't loaded in the child, so the tools don't exist.
9
+ - Non-blocking subagent launches.
10
+ - Default OS write sandboxing on macOS and Linux.
11
+ - Explicit tool allowlists for child sessions.
12
+ - Durable logs and result retrieval across reloads.
13
+ - Live background-work navigator for active runs.
84
14
 
85
- ### Git-mutating subagents and linked worktrees
86
-
87
- A sandboxed subagent that will mutate Git should set **`git_clone_workspace:true`**
88
- on `subagent_spawn`. The parent prepares a fresh, self-contained Git clone whose
89
- `.git/` directory lives **inside the sandbox writable root**, then runs the child
90
- in that clone.
91
-
92
- Why this matters: a linked Git worktree (created with `git worktree add`) has a
93
- `.git` file that points back to administrative state under the main repository,
94
- typically outside the sandbox directory. A sandbox that only allows writes under
95
- the worktree directory therefore cannot support normal Git producer operations
96
- such as fetch, rebase, commit, and push — the child stalls or fails when Git
97
- tries to write metadata it cannot reach. `git_clone_workspace:true` avoids this
98
- by cloning the repository with a real `.git/` directory inside the writable root.
99
-
100
- The clone uses:
15
+ ## Install
101
16
 
17
+ ```sh
18
+ pi install npm:pi-better-subagents
102
19
  ```
103
- git clone --reference-if-able <local-reference-repo> --dissociate \
104
- <remote-url> <sandbox-workspace>
105
- ```
106
-
107
- `--reference-if-able` borrows local objects from the parent repository during
108
- setup; `--dissociate` removes the alternates link afterwards, so the clone is
109
- self-contained and safe to delete. The clone source prefers the source
110
- workspace's upstream remote URL (`origin` when set) so the disposable
111
- workspace's `origin` points at the real remote rather than the parent working
112
- tree — pushes therefore target upstream, not the sandboxed parent. The local
113
- repository is used only as a reference (and as a content fallback when no
114
- remote is configured). Source remotes are re-synced after clone. The
115
- checked-out branch/commit matches the source workspace at spawn time.
116
- Repo-local Git identity settings from the source (`user.name`, `user.email`,
117
- and `user.signingkey` when set) are copied into the clone so ordinary commits
118
- work without reconfiguring identity inside the disposable workspace.
119
-
120
- If the source workspace is a linked worktree, the clone is prepared from the
121
- main repository's object database and the requested branch/commit; the child is
122
- never launched into the structurally broken linked-worktree sandbox. If clone
123
- preparation fails, the spawn fails fast with a message explaining that the
124
- linked-worktree Git metadata is outside the sandbox and recommending
125
- `git_clone_workspace:true`.
126
-
127
- Note that because children load only the extensions backing their tools, a
128
- guardrails extension (e.g. `@aliou/pi-guardrails`) does **not** apply inside a
129
- subagent unless you map a tool to it. The OS write sandbox above is what confines
130
- the child, and it doesn't depend on any extension.
131
-
132
- ## Tool scoping (allowlist)
133
20
 
134
- Precedence, highest first: the per-call `tools` param → `config.json`
135
- `defaultTools` → a built-in default (`read, bash, edit, write, web_search,
136
- web_fetch`; just `read, bash` in a `clean` child). `exclude_tools` subtracts on
137
- top.
21
+ Try it for one run:
138
22
 
139
- `config.json` (next to the extension) also sets:
140
-
141
- - `defaultModel` — model for spawns that don't specify one (`null` = inherit the
142
- foreground model).
143
- - `maxConcurrent` — how many subagents may run at once (**default 4**). A spawn
144
- past the cap is rejected until a running one finishes.
145
-
146
- ## The allowlist also decides what LOADS
147
-
148
- The `tools` allowlist does double duty: it is both what the child may call **and**
149
- which extension *code* is loaded into it. A child launches as
150
-
151
- ```
152
- pi -p --mode json --no-extensions -e <package backing a requested tool> ...
23
+ ```sh
24
+ pi -e npm:pi-better-subagents
153
25
  ```
154
26
 
155
- so a package that backs no requested tool never loads. With the default
156
- allowlist (`read, bash, edit, write, web_search, web_fetch`) exactly one package
157
- loads — the web-tools one — and `web_fetch` works normally.
158
-
159
- Two maps in `config.json` drive it:
160
-
161
- - `toolExtensions` — tool name → package(s) providing it. Built-ins (`read`,
162
- `bash`, `edit`, `write`) need no entry.
163
- - `providerExtensions` — provider → auth package. Model auth is not tool-shaped:
164
- `xai/grok-4.5` needs `pi-xai-oauth` loaded whatever tools it was granted.
165
-
166
- Ask for a tool with no mapping and the spawn still succeeds, but says so at
167
- launch — the tool simply will not exist in the child.
168
-
169
- `clean:true` is the narrowest case of the same mechanism: no extensions at all.
170
- `allow_nested:true` is the one thing that loads *this* package into the child;
171
- without it, nested spawning is impossible because the code isn't there.
172
-
173
- `inheritExtensions: true` in `config.json` restores the old load-everything
174
- behavior. It is **operator-only** — no spawn parameter can reach it, so the child
175
- model cannot widen its own runtime. It also re-exposes the failure below.
176
-
177
- ### Why: a subagent that loads everything can die mid-turn reporting success
178
-
179
- Loading every installed package means inheriting their startup side effects. A
180
- package that replaces builtin `bash` with a `detached` + `unref()` spawn breaks
181
- `pi -p`: on a parallel `bash` + `read` batch the in-process `read` finishes, the
182
- unref'd `bash` doesn't hold the event loop, Node drains, and the child **exits 0
183
- mid-turn** — no `tool_execution_end`, no `agent_end`. Historically, exit 0 was
184
- indistinguishable from a clean finish, so all 17 observed mid-turn exits were
185
- reported as ✓ completed. Finalization now requires terminal agent evidence and
186
- no unmatched tool starts. Lifecycle validation classifies runs as `complete`,
187
- `incomplete_no_terminal_event`, `incomplete_open_tools`, `failed_exit`, or
188
- `killed`; incoherent exit-0 streams are recorded as failed with named lifecycle
189
- diagnostics on `subagent_result` and attention wording on completion callbacks.
190
-
191
- A tool allowlist alone cannot fix this. `--tools` restricts what the model may
192
- *call*; the package already overrode builtin `bash` at startup, so the `bash` in
193
- your allowlist **is** the broken one. Measured with the default 6 tools:
194
-
195
- | runtime | tool starts / ends | terminal event |
196
- |---|---|---|
197
- | all extensions loaded | 2 / 1 | none — exits 0 mid-turn |
198
- | `--no-extensions -e <web-tools>` | 3 / 3 | `agent_settled`, `web_fetch` OK |
199
-
200
- A package *denylist* isn't expressible either: pi has only `-e <path>` (add one)
201
- and `--no-extensions` (all off) — there is no "load all except X" flag. Naming
202
- what you want is the only mechanism that excludes anything, and it excludes
203
- future offenders too, with no name to keep updated.
204
-
205
- ### Known incompatibility: `pi-patty-bg-tasks`
206
-
207
- **`pi-patty-bg-tasks` (tested at 1.1.6) is incompatible with subagents and must
208
- not be loaded into a child.** It is the package that produced the failure above:
209
- it replaces builtin `bash` and spawns `detached` + `proc.unref()`
210
- (`src/spawn.ts`), which in print mode drains the event loop mid-turn. Bisected
211
- against all 18 installed packages — alone it reproduces; every other package
212
- alone is fine.
213
-
214
- The default configuration already excludes it, structurally, because it backs no
215
- requested tool. You only re-expose it by setting `inheritExtensions: true`, or by
216
- mapping a tool to it in `toolExtensions`. Don't.
217
-
218
- A proper fix belongs upstream — preserve builtin `bash` semantics when overriding
219
- it, keep foreground subprocesses referenced until the tool promise settles, and
220
- put genuinely detached work behind a separate background-task tool.
27
+ Linux sandboxing uses `bubblewrap` when available:
221
28
 
222
- ## Status & cost tracking
223
-
224
- Driven by the child's `--mode json` usage events:
225
-
226
- - **Live widget** above the editor while any subagent runs — a spinner per run
227
- with elapsed time, the current tool, and running token/cost spend, ticking once
228
- a second. It clears itself when the last run finishes. (TUI/RPC only; silent in
229
- `-p`/print mode.)
230
- - **On demand** — `subagent_list`, `subagent_output`, and `subagent_result` all
231
- carry `elapsed · N tok (↑in ↓out) · $cost · tools`. The completion notice and
232
- toast include the final elapsed + spend too.
233
- - **Folded result display.** In interactive TUI sessions, `subagent_result`
234
- renders a compact preview by default so long child answers do not flood the
235
- transcript. Clicking the tool row, or using the row expand action, shows the
236
- full bounded result. This is a display concern only: the tool still returns
237
- the complete bounded `content` payload to the model.
238
-
239
- Spend is summed from each finalized assistant turn's `usage` (so multi-turn
240
- tool-using runs total correctly), and cost comes straight from the model's
241
- reported per-request cost.
242
-
243
- ## Subagent navigator (TUI)
244
-
245
- In an interactive TUI session, a **subagent navigator** lets you inspect and
246
- organize runs without asking the model to call a tool. The running-subagents
247
- widget can be focused from an empty input line for quick actions; detail output
248
- opens in the overlay. Print/RPC modes do not install the navigator; tool access
249
- is unchanged in every mode.
250
-
251
- ### Open
252
-
253
- - With the editor **empty** and at least one non-dismissed current-parent run
254
- still running, press `←` to focus the main-window subagent list above the
255
- input line.
256
- - If the editor contains text, `←` keeps normal cursor-left behavior.
257
- - While running runs exist, the default footer shows `← subagents · N`. The
258
- live widget also includes a secondary `← to navigate` hint on its title line
259
- for terminals that do not render the default footer status. The hint clears
260
- when no non-dismissed current-parent run is still running.
261
- - While the main-window list is focused, the title hint changes to
262
- `Enter to view · x to stop`; the selected row is marked with `›`. Press
263
- `↓` from the bottom row to return to the input line.
264
- - `↑` moves to the previous row when multiple running rows are shown. `↓`
265
- moves toward the input line, returning to normal input from the bottom row.
266
- - `Enter` opens the selected run's live detail view. `x` stops the selected
267
- running run using shared `subagent_stop` semantics and dismisses it from the
268
- navigator.
269
-
270
- ### Detail view
271
-
272
- - Detail uses the same command-sheet treatment, with section rules for the
273
- inspector groups and command bars at the top and bottom of the view.
274
- - Shows status (colorized), model/effort, elapsed, tools, spend, and parsed
275
- output, plus sectioned health: process identity/liveness, activity,
276
- compaction, active tool, model call/error, last log write, thresholds, and
277
- callback notification timestamps. Compaction, active tool, and model state
278
- are separate sections. The view refreshes about once per second while open.
279
- - Detail opened from the main-window list closes back to the main page; the
280
- main-window selection remains on the viewed run when it is still visible.
281
- - `x` arms Stop for a running run, or Dismiss for a terminal run.
282
- - `esc` closes the detail view and returns to the main page.
283
-
284
- ### Two-press `x` stop/dismiss
285
-
286
- - First `x` on the selected (list) or viewed (detail) run arms the action for three
287
- seconds and shows a footer hint: `x again to stop <name>` while running, or
288
- `x again to dismiss <name>` when terminal.
289
- - Second `x` within the window, on the **same** run, acts:
290
- - **Running** — stop the process group (shared `subagent_stop` semantics),
291
- mark killed, then dismiss from the navigator.
292
- - **Terminal** — dismiss only; terminal status is not rewritten.
293
- - Changing selection, leaving the view, closing the overlay, arming timeout,
294
- reload, and session teardown all disarm close and clear the confirm hint.
295
-
296
- ### Dismissal is navigator-only
297
-
298
- Dismissed runs leave the navigator list and footer count. Logs, prompt, session
299
- data, metadata, and id-based tool access stay intact. `subagent_list`,
300
- `subagent_output`, `subagent_result`, and `subagent_stop` still resolve dismissed
301
- run ids. Dismissal survives `/reload` as dismissed in the navigator.
302
-
303
- ### Reload and teardown
304
-
305
- `/reload` and session restart reinstall the empty-editor wrapper without stacking
306
- duplicate handlers, republish the footer count, and clear any leftover overlay
307
- timers or close-confirm state. Session shutdown disposes open navigator timers
308
- and clears navigator footer statuses (TUI only).
309
-
310
- ## Design notes
311
-
312
- - Runtime lives outside any repo, under `$TMPDIR/pi-better-subagents/`
313
- (`runs/<id>/` holds `output.log`, `prompt.md`, `meta.json`; `sessions/` holds
314
- child session state). The `meta.json` sidecar is authoritative, so `list` /
315
- `output` / `result` survive turns, `/reload`, and pi restarts.
316
- - The child runs `--mode json`; `subagent_result` / `subagent_output` **parse**
317
- the event stream and return just the final answer (plus which tools ran).
318
- Non-JSON banner/warning lines fail to parse and are dropped, so the result is
319
- clean. The prompt is passed as a **positional argument**, never `@file` — some
320
- models refuse an @-attached file as untrusted content.
321
- - The child gets **only** the explicit prompt — no silent parent-context bleed.
322
- - `--approve` is **off by default** (headless runs can't prompt for trust).
323
-
324
-
325
- ## Parent-process scoping
326
-
327
- The live widget, default `subagent_list`, concurrency cap, and `session_start` ticker only include runs this pi process spawned (`spawnPid === process.pid`). The on-disk registry stays machine-global for durability. `subagent_list` shows newest runs first and is capped at 20 rows by default; pass `limit:N` to request fewer or more rows, up to the documented maximum of 100 (larger values are clamped with a clear note). Pass `all:true` for a global view; it still respects the default or explicit limit. Pass `status:[...]` to filter by effective status: `running`, `completed`, `failed`, `killed`, transient `exited`, or durable `orphaned` / `lost`. Id-based `subagent_result` / `subagent_output` / `subagent_stop` still resolve any run id (cross-session recovery).
328
-
329
- ## Supervision health (`orphaned` / `lost`)
330
-
331
- While a current-parent run is `running` or `orphaned`, a periodic health tick
332
- reconciles process-group evidence only (see `docs/adr/0002-process-group-only-subagent-health.md`):
333
-
334
- - **`orphaned`** — direct supervision of the child is broken, but related
335
- process-group work may still be alive. Non-terminal and non-final; operationally
336
- unhealthy immediately. The coordinator (when `callback:true`) gets one durable
337
- ATTENTION follow-up naming `subagent_result` / `subagent_output` / `subagent_stop`
338
- so it can inspect artifacts and decide whether to wait, stop, or retry. Human
339
- `ui.notify` still fires when `callback:false`.
340
- - **`lost`** — no related process remains and no coherent terminal completion was
341
- observed. Terminal with unknown outcome (not the same as `failed`). Same one-shot
342
- ATTENTION follow-up + diagnostic `subagent_result` path with best-available
343
- artifacts.
344
-
345
- Callbacks use the same non-interrupting `{ deliverAs: "followUp", triggerTurn: true }`
346
- mechanics as completion, with distinct ATTENTION wording. Per-status markers on
347
- `meta.json` (`orphanedCallbackSentAt` / `lostCallbackSentAt`) are written only after
348
- a successful handoff and dedupe across reloads and repeated health ticks. Persisted
349
- unmarked orphaned/lost states are recovered on the health ticker after `/reload`
350
- even when process evidence does not produce a fresh transition.
351
-
352
- ### Surfacing health (tools + passive widget)
353
-
354
- Multi-dimensional observations (`stale`, long tool, compacting / long compaction,
355
- model error/retry, plus process `orphaned` / `lost`) are computed from durable
356
- status + child-event evidence and surfaced on existing paths without a parallel
357
- health model:
358
-
359
- - **`subagent_list`** — durable `orphaned` / `lost` status brackets; degraded
360
- compact facts only when actionable. Healthy/quiet rows stay on the compact format.
361
- - **`subagent_output` / `subagent_result`** — `[health: …]` diagnostics for
362
- orphaned, lost, and degraded running runs; #65 orphaned/lost result bodies kept.
363
- - **Passive live widget** — healthy/quiet unchanged; degraded (and orphaned) may
364
- show a short suffix. Still `setWidget` only — never focusable.
365
- - **`callback:false`** suppresses coordinator follow-up only; human `ui.notify` and
366
- TUI/passive visibility remain.
367
-
368
- ## Install
369
-
370
- Linux sandboxing requires the system `bubblewrap` package. Install it before
371
- launching sandboxed children:
372
-
373
- ```bash
374
- # Debian/Ubuntu
29
+ ```sh
375
30
  sudo apt-get install bubblewrap
376
- # Fedora/RHEL
377
- sudo dnf install bubblewrap
378
- # Arch Linux
379
- sudo pacman -S bubblewrap
380
31
  ```
381
32
 
382
- When `bwrap` is absent, explicit sandbox requests fail with an installation hint;
383
- default-on sandboxing preserves the documented direct-execution fallback. Once
384
- `bwrap` is selected, a launch failure fails closed rather than retrying the child
385
- without confinement.
386
-
387
- Symlink the project into pi's auto-discovered extensions dir:
33
+ ## Update Or Remove
388
34
 
389
- ```bash
390
- ln -sfn "$PWD" ~/.pi/agent/extensions/pi-better-subagents
35
+ ```sh
36
+ pi update npm:pi-better-subagents
37
+ pi remove npm:pi-better-subagents
391
38
  ```
392
39
 
393
- Then `/reload` (or restart pi). It appears as `pi-better-subagents`.
394
-
395
- > Do **not** add it to `settings.json`'s `extensions` array — a live pi session
396
- > rewrites that file on its own saves and drops hand-added entries. Auto-discovery
397
- > via the symlink is stable. Quick throwaway test without installing:
398
- > `pi -e ./index.ts`.
399
-
400
- ## Tests
401
-
402
- Unit tests (`node --test tests/*.test.mjs`) cover the pure logic — widget
403
- rendering, completion delivery, and extension resolution.
404
-
405
- Real integration smoke tests live in [`tests/`](tests/) — a subagent using
406
- `web_fetch`, one driving `gh`, env inheritance through the sandbox, and headless
407
- isolation surviving a parallel `bash` + `read` batch. See
408
- [`tests/README.md`](tests/README.md).
409
-
410
- ## Roadmap
411
-
412
- Tracked in [issues](https://github.com/1aboveio/pi-better-subagents/issues).
413
- Near-term:
40
+ ## More Detail
414
41
 
415
- - Guarantee subagent autonomy — verify/deny any child→parent supervision
416
- back-channel so a child can never block on the parent ([#1](https://github.com/1aboveio/pi-better-subagents/issues/1)).
417
- - Make `callback:true` a lightweight trigger instead of embedding the full result
418
- twice ([#2](https://github.com/1aboveio/pi-better-subagents/issues/2)) — **done**.
419
- - Named agent-definition files (per-agent system prompt + tool allowlist) and
420
- chain/parallel orchestration.
42
+ - Repository: https://github.com/1aboveio/pi-better-harness
43
+ - Detailed notes: https://github.com/1aboveio/pi-better-harness/blob/main/packages/pi-better-subagents/docs/usage.md
package/index.ts CHANGED
@@ -28,7 +28,7 @@ import {
28
28
  type BackgroundWorkDetail,
29
29
  type BackgroundWorkProvider,
30
30
  type BackgroundWorkRow,
31
- } from "../navigator/index.ts";
31
+ } from "./shared-navigator.ts";
32
32
  import { spawnDetached, type SpawnResult } from "./spawn.ts";
33
33
  import { parseRun, type Usage } from "./parse.ts";
34
34
  import { finalizeRun as finalizeRunCore } from "./finalization.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-better-subagents",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Claude Code-style async subagents for pi, built on detached background pi -p processes. Launching is the deliverable; the foreground never blocks.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -9,7 +9,9 @@
9
9
  "subagents"
10
10
  ],
11
11
  "pi": {
12
- "extensions": ["./index.ts"],
12
+ "extensions": [
13
+ "./index.ts"
14
+ ],
13
15
  "image": "https://raw.githubusercontent.com/1aboveio/pi-better-harness/main/docs/images/package-gallery/pi-better-subagents.png"
14
16
  },
15
17
  "repository": {