@ferris1225/pi-subagents 0.27.0 → 0.28.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 +25 -15
- package/package.json +1 -1
- package/src/index.ts +23 -19
- package/src/prompt.ts +7 -3
package/README.md
CHANGED
|
@@ -18,9 +18,11 @@ report their results back to the main agent automatically.
|
|
|
18
18
|
agent automatically: injected as soon as the current tool call finishes (even
|
|
19
19
|
mid-turn), or starting a new turn when idle. No polling, no "go check" step.
|
|
20
20
|
- **Sub-agent toolbelt** — three companion tools that replace the classic
|
|
21
|
-
sleep/poll anti-pattern: `subagent_wait`
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
sleep/poll anti-pattern: `subagent_wait` looks results up in-turn — **non-blocking
|
|
22
|
+
by default** (a settled run returns its result immediately, a still-active run
|
|
23
|
+
tells the model to end its turn and wait for the wake-up message; pass
|
|
24
|
+
`timeoutMs` to block) — `subagent_status` inspects active and finished runs, and
|
|
25
|
+
`subagent_stop` cancels a run (delivering its partial output as an aborted result).
|
|
24
26
|
- **Honest completions** — a run that exited cleanly but whose tool calls failed
|
|
25
27
|
(e.g. a broken build) is reported as `completed with N failed tool call(s)`
|
|
26
28
|
with the errors attached, so a rosy final text can never hide a failure.
|
|
@@ -55,9 +57,10 @@ Several tools now offer some form of sub-agents. What this extension does differ
|
|
|
55
57
|
- **Results come back on their own.** The extension turns the child's completion
|
|
56
58
|
into a message that wakes the main agent automatically — delivered even
|
|
57
59
|
mid-turn, right after the current tool call. No polling, no "go check
|
|
58
|
-
the other window" step, and **no `sleep
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
the other window" step, and **no `sleep`** and no waiting: the model ends its
|
|
61
|
+
turn and the result wakes it. A settled result can be fetched in-turn with
|
|
62
|
+
`subagent_wait` (a non-blocking lookup by default; `timeoutMs` opts into
|
|
63
|
+
blocking) instead of sleeping or polling.
|
|
61
64
|
- **Failures are handled, not reported.** Three layers of resilience: a provider-
|
|
62
65
|
level model failure first retries the same model up to five times on a transient
|
|
63
66
|
provider error, then retries once with the main window's model; terminal errors
|
|
@@ -333,10 +336,13 @@ main agent
|
|
|
333
336
|
The extension registers three companion tools so the main agent never has to
|
|
334
337
|
`sleep`/poll for a background run:
|
|
335
338
|
|
|
336
|
-
- `subagent_wait` —
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
339
|
+
- `subagent_wait` — looks up a run's result in-turn. It does **not block by
|
|
340
|
+
default**: a settled run returns its result immediately; a still-active run
|
|
341
|
+
returns a note telling the model to end its turn (the completion message then
|
|
342
|
+
wakes it). Pass `timeoutMs` to block inside the tool call (event-driven, wakes
|
|
343
|
+
on the run's completion) — only when the current turn must receive the result
|
|
344
|
+
right now (sequential dependent steps). Otherwise end the turn and the
|
|
345
|
+
completion message wakes you.
|
|
340
346
|
- `subagent_status` — lists active runs (id, agent, model, usage, elapsed, activity)
|
|
341
347
|
and finished results; pass an id to read a finished run's full result.
|
|
342
348
|
- `subagent_stop` — cancels an active run (or `all: true`); the child is terminated
|
|
@@ -385,9 +391,11 @@ Start dependent work only after the relevant result has been delivered.
|
|
|
385
391
|
|
|
386
392
|
### Waiting for a result in-turn
|
|
387
393
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
394
|
+
Results arrive as messages that wake the main agent automatically, so waiting is
|
|
395
|
+
usually unnecessary: end your turn and the result resumes you. When a result must
|
|
396
|
+
be fetched in-turn, `subagent_wait` is a **non-blocking lookup by default** — a
|
|
397
|
+
settled run returns its result immediately, a still-active run returns a note
|
|
398
|
+
telling the model to end its turn:
|
|
391
399
|
|
|
392
400
|
```json
|
|
393
401
|
{
|
|
@@ -395,8 +403,10 @@ When the next step depends on a run's result and the turn must not end, use
|
|
|
395
403
|
}
|
|
396
404
|
```
|
|
397
405
|
|
|
398
|
-
|
|
399
|
-
|
|
406
|
+
Only when the turn must not end AND the result is needed right now (e.g. the user
|
|
407
|
+
asked for it) pass `timeoutMs` to block; on timeout it reports the still-running
|
|
408
|
+
runs and the model ends the turn (the completion message then wakes it) or
|
|
409
|
+
re-invokes with a longer timeout.
|
|
400
410
|
|
|
401
411
|
### Inspecting runs
|
|
402
412
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ferris1225/pi-subagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Focused sub-agent delegation for pi: explore / worker / reviewer agents in isolated context, with proactive dispatch injection and per-agent model selection.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/index.ts
CHANGED
|
@@ -310,7 +310,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
310
310
|
"Modes: single ({agent, task}) or parallel ({tasks: [{agent, task}, ...]}).",
|
|
311
311
|
"It starts agents in the background and immediately returns control to the main window; completion messages automatically wake the main agent to continue.",
|
|
312
312
|
"Each agent has no memory of this conversation — brief it fully (goal, exact paths, constraints, expected output).",
|
|
313
|
-
"
|
|
313
|
+
"Results arrive as wake-up messages automatically — you do NOT need to wait. If you must get a result in-turn, subagent_wait is a non-blocking lookup by default (pass timeoutMs to block)."
|
|
314
314
|
].join(" "),
|
|
315
315
|
promptSnippet:
|
|
316
316
|
"Start background subagents: explore (read-only search), worker (implement), reviewer (adversarial review); completion automatically resumes the main agent. Simple tasks: use direct tools, not subagents.",
|
|
@@ -321,8 +321,8 @@ export default function (pi: ExtensionAPI): void {
|
|
|
321
321
|
"Use subagent with agent 'reviewer' for a fresh read-only review before reporting work done or committing.",
|
|
322
322
|
"subagent launches work in the background and ends the current turn; when a result arrives, the main agent is automatically resumed with it.",
|
|
323
323
|
"Run independent tasks in parallel by passing a tasks array to subagent; let the automatically resumed main agent start dependent work after results arrive.",
|
|
324
|
-
"NEVER sleep
|
|
325
|
-
"If you must keep the turn for a result, call subagent_wait
|
|
324
|
+
"NEVER sleep or poll, and do NOT call subagent_wait to hold the turn — subagent ends the turn immediately and the result arrives as a message that wakes you automatically (even mid-turn). Ending your turn is the default and the only correct way to wait.",
|
|
325
|
+
"If you must keep the turn for a result, call subagent_wait with an explicit timeoutMs (non-blocking by default) — never bash sleep/timeout to wait for a sub-agent.",
|
|
326
326
|
],
|
|
327
327
|
parameters: SubagentParams,
|
|
328
328
|
|
|
@@ -863,13 +863,13 @@ export default function (pi: ExtensionAPI): void {
|
|
|
863
863
|
},
|
|
864
864
|
});
|
|
865
865
|
|
|
866
|
-
//
|
|
867
|
-
//
|
|
868
|
-
//
|
|
869
|
-
//
|
|
870
|
-
//
|
|
871
|
-
// for
|
|
872
|
-
const SUBAGENT_WAIT_DEFAULT_TIMEOUT_MS =
|
|
866
|
+
// In-turn result lookup. Dispatch already ended the turn and results arrive as
|
|
867
|
+
// wake-up messages, so the default must NOT block: a settled run returns its
|
|
868
|
+
// result immediately, a still-active run returns a "still running — end your
|
|
869
|
+
// turn" note and the model finishes (the completion then wakes it). Blocking
|
|
870
|
+
// is opt-in via an explicit timeoutMs — a long default would hold the turn
|
|
871
|
+
// hostage for nothing, since the result arrives on its own either way.
|
|
872
|
+
const SUBAGENT_WAIT_DEFAULT_TIMEOUT_MS = 0;
|
|
873
873
|
|
|
874
874
|
const SubagentWaitParams = Type.Object({
|
|
875
875
|
id: Type.Optional(
|
|
@@ -879,7 +879,7 @@ export default function (pi: ExtensionAPI): void {
|
|
|
879
879
|
),
|
|
880
880
|
timeoutMs: Type.Optional(
|
|
881
881
|
Type.Number({
|
|
882
|
-
|
|
882
|
+
description: `Block for up to this many milliseconds and report the still-running runs. Default ${SUBAGENT_WAIT_DEFAULT_TIMEOUT_MS}: no blocking — settled runs return their result immediately, active runs return a note telling the model to end its turn.`,
|
|
883
883
|
}),
|
|
884
884
|
),
|
|
885
885
|
});
|
|
@@ -888,18 +888,19 @@ export default function (pi: ExtensionAPI): void {
|
|
|
888
888
|
name: "subagent_wait",
|
|
889
889
|
label: "Subagent Wait",
|
|
890
890
|
description: [
|
|
891
|
-
"
|
|
892
|
-
"
|
|
893
|
-
"
|
|
891
|
+
"Look up background sub-agent run(s) and return their results.",
|
|
892
|
+
"PREFER NOT CALLING THIS: dispatching already ended your turn and results arrive as a message that wakes you automatically.",
|
|
893
|
+
"By default it does NOT block: a settled run returns its result immediately; a still-active run returns a 'still running — end your turn' note.",
|
|
894
|
+
"Pass an explicit timeoutMs ONLY when you must stay in the turn and need the result right now (sequential dependent steps).",
|
|
894
895
|
"NEVER sleep, poll, or wait with bash to get a sub-agent result: end the turn, or call this tool.",
|
|
895
896
|
"The same result is also delivered as a completion message that resumes the main agent, so you may see it twice (once here, once as a wake-up) — that is expected, not a duplicate.",
|
|
896
897
|
].join(" "),
|
|
897
|
-
promptSnippet: "
|
|
898
|
+
promptSnippet: "Look up a background subagent result in-turn (id: run id from the widget; omit for all). Non-blocking by default; pass timeoutMs to block.",
|
|
898
899
|
promptGuidelines: [
|
|
899
|
-
"
|
|
900
|
-
"
|
|
900
|
+
"Do NOT call subagent_wait to hold the turn: results arrive as wake-up messages automatically. The default call is a non-blocking lookup — settled results return immediately, active runs return a note telling you to end your turn.",
|
|
901
|
+
"Pass an explicit timeoutMs only when you must keep the turn AND the next step depends on the result right now — e.g. the user asked you to wait for it.",
|
|
901
902
|
"Never use bash sleep/timeout/polling to wait for a sub-agent — it blocks the turn and delays result delivery.",
|
|
902
|
-
"If subagent_wait times out,
|
|
903
|
+
"If subagent_wait times out, end the turn and wait for the wake-up message, or call it again with a longer timeoutMs.",
|
|
903
904
|
],
|
|
904
905
|
parameters: SubagentWaitParams,
|
|
905
906
|
|
|
@@ -999,7 +1000,10 @@ export default function (pi: ExtensionAPI): void {
|
|
|
999
1000
|
timer = setTimeout(
|
|
1000
1001
|
() =>
|
|
1001
1002
|
finish({
|
|
1002
|
-
note:
|
|
1003
|
+
note:
|
|
1004
|
+
timeoutMs === 0
|
|
1005
|
+
? `run #${runId} is still active — end your turn: the result will wake you (or call subagent_wait again with an explicit timeoutMs to block)`
|
|
1006
|
+
: `wait timed out after ${Math.round(timeoutMs / 1000)}s — run #${runId} is still active; call subagent_wait again or end the turn (the result will wake you when ready)`,
|
|
1003
1007
|
}),
|
|
1004
1008
|
Math.max(1, timeoutMs),
|
|
1005
1009
|
);
|
package/src/prompt.ts
CHANGED
|
@@ -41,9 +41,13 @@ It immediately ends the current main-agent turn so the user can keep working. Wh
|
|
|
41
41
|
finishes, its result is sent back as a message that automatically resumes the main agent;
|
|
42
42
|
if the main agent is busy, the result waits as a follow-up.
|
|
43
43
|
|
|
44
|
-
NEVER run sleep, wait, or polling commands (e.g. Start-Sleep, sleep, timeout)
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
NEVER run sleep, wait, or polling commands (e.g. Start-Sleep, sleep, timeout), and do NOT
|
|
45
|
+
call subagent_wait to hold the turn — dispatching already ended it, and results arrive as
|
|
46
|
+
messages that resume the main agent automatically (even mid-turn). Ending your turn is the
|
|
47
|
+
default and the only correct way to wait; subagent_wait blocks the turn so the user cannot
|
|
48
|
+
give you other work meanwhile. It is non-blocking by default: settled results return
|
|
49
|
+
immediately, active runs return a "still running — end your turn" note. Pass an explicit
|
|
50
|
+
timeoutMs only when you must stay in the turn (e.g. the user asked you to wait).
|
|
47
51
|
|
|
48
52
|
Available agents:
|
|
49
53
|
${catalog}
|