@arhen/pi-core-subagent 1.3.46 → 1.3.47
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 +8 -10
- package/package.json +1 -1
- package/src/child.ts +1 -1
- package/src/index.ts +5 -6
- package/src/manager.ts +5 -10
- package/src/schemas.ts +0 -3
- package/src/types.ts +0 -1
package/README.md
CHANGED
|
@@ -93,11 +93,10 @@ Define agents inline per call, or reference a named agent file (see [Agent files
|
|
|
93
93
|
}
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
Parallel — mixed toolsets, siblings can talk via mailbox:
|
|
96
|
+
Parallel — mixed toolsets, siblings can talk via mailbox (intercom is always on):
|
|
97
97
|
|
|
98
98
|
```json
|
|
99
99
|
{
|
|
100
|
-
"allowIntercom": true,
|
|
101
100
|
"tasks": [
|
|
102
101
|
{ "agent": "researcher", "prompt": "You find facts. Cite paths.", "task": "Map the auth flow", "write": false },
|
|
103
102
|
{ "agent": "implementer", "prompt": "You make minimal changes.", "task": "Implement POST /api/upload", "write": true }
|
|
@@ -272,14 +271,13 @@ flowchart LR
|
|
|
272
271
|
|
|
273
272
|
And the rule that keeps this from becoming ceremony: **zero `needs` anywhere = plain parallel.** No waves, no gates, no graph vocabulary imposed on flat work.
|
|
274
273
|
|
|
275
|
-
Background (default) + intercom — the run returns a runId immediately; you stay steerable while it works:
|
|
274
|
+
Background (default) + intercom — the run returns a runId immediately; you stay steerable while it works. Children can always ask you questions and message each other:
|
|
276
275
|
|
|
277
276
|
```json
|
|
278
277
|
{
|
|
279
278
|
"agent": "auditor",
|
|
280
279
|
"prompt": "You audit dependencies.",
|
|
281
|
-
"task": "Audit package.json for outdated deps"
|
|
282
|
-
"allowIntercom": true
|
|
280
|
+
"task": "Audit package.json for outdated deps"
|
|
283
281
|
}
|
|
284
282
|
```
|
|
285
283
|
|
|
@@ -289,7 +287,7 @@ Background (default) + intercom — the run returns a runId immediately; you sta
|
|
|
289
287
|
|
|
290
288
|
| Tool | Purpose |
|
|
291
289
|
|---|---|
|
|
292
|
-
| `subagent` | single / `tasks` (parallel or graph via `needs`) / `chain` (`{previous}`); every run is background — returns a runId, completion notifies you; `autoAwait:true` parks the call until the run finishes and returns the final result inline;
|
|
290
|
+
| `subagent` | single / `tasks` (parallel or graph via `needs`) / `chain` (`{previous}`); every run is background — returns a runId, completion notifies you; `autoAwait:true` parks the call until the run finishes and returns the final result inline; children always carry talk tools (ask/notify/mailbox); `notifyPerTask` (default true) wakes you as each task completes |
|
|
293
291
|
| `subagent_status` | live per-task snapshot (non-blocking), including each child's session file path |
|
|
294
292
|
| `subagent_result` | full output of a run or one task |
|
|
295
293
|
| `await_subagent` | block until a run finishes (optional `timeoutMs`) |
|
|
@@ -299,9 +297,9 @@ Background (default) + intercom — the run returns a runId immediately; you sta
|
|
|
299
297
|
|
|
300
298
|
### Per-task fields
|
|
301
299
|
|
|
302
|
-
`agent` (name you invent — required), `task` (required), `prompt` (system prompt, optional — minimal default used), `write` (toolset, default read-only), plus optional `model` (`provider/model-id`), `thinking` (validated enum: `off|minimal|low|medium|high|xhigh|max`), `tools` (explicit allowlist), `cwd`, `maxRuntimeMs`, `id`, `needs` (dependency edges — see [Graph mode](#graph-mode--needs)). Top-level only: `autoAwait`, `notifyPerTask`, `
|
|
300
|
+
`agent` (name you invent — required), `task` (required), `prompt` (system prompt, optional — minimal default used), `write` (toolset, default read-only), plus optional `model` (`provider/model-id`), `thinking` (validated enum: `off|minimal|low|medium|high|xhigh|max`), `tools` (explicit allowlist), `cwd`, `maxRuntimeMs`, `id`, `needs` (dependency edges — see [Graph mode](#graph-mode--needs)). Top-level only: `autoAwait`, `notifyPerTask`, `concurrency`.
|
|
303
301
|
|
|
304
|
-
### Child talk tools (
|
|
302
|
+
### Child talk tools (always on)
|
|
305
303
|
|
|
306
304
|
| Tool | Meaning |
|
|
307
305
|
|---|---|
|
|
@@ -315,7 +313,7 @@ Background (default) + intercom — the run returns a runId immediately; you sta
|
|
|
315
313
|
## Commands
|
|
316
314
|
|
|
317
315
|
- `/subagents` — list runs; `/subagents peek` (or `ctrl+shift+a`) — browsable pane
|
|
318
|
-
- `/subagents auto-limit on|off` — toggle leader-imposed `maxRuntimeMs` caps (persists to `~/.pi/agent/subagents-config.json`; default
|
|
316
|
+
- `/subagents auto-limit on|off` — toggle leader-imposed `maxRuntimeMs` caps (persists to `~/.pi/agent/subagents-config.json`; default **off**). `on` gives tasks without an explicit `maxRuntimeMs` the 1 h default ceiling; `off` raises the ceiling to 6 h (still a ceiling — an unbounded child would pin the run forever). Bare `/subagents auto-limit` shows the current state.
|
|
319
317
|
|
|
320
318
|
## Peek — `/subagents peek` or `ctrl+shift+a`
|
|
321
319
|
|
|
@@ -356,7 +354,7 @@ The extension has no multiplexer integration and does not want one: it exposes t
|
|
|
356
354
|
|
|
357
355
|
- Parent tools: 6 schemas with short descriptions. **No catalog, no context hook** — nothing injected per request.
|
|
358
356
|
- Background completion: 3-line notice. Full text only via `subagent_result`.
|
|
359
|
-
- Children: isolated sessions; talk tools injected
|
|
357
|
+
- Children: isolated sessions; talk tools always injected; each child's prompt states its own task id and its siblings' so mailbox addressing works. Model resolution: explicit `provider/model-id` or bare id via the pi model registry → the parent's current model → settings default. Thinking levels validated against the resolved model's `thinkingLevelMap`.
|
|
360
358
|
|
|
361
359
|
## What this is built on
|
|
362
360
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arhen/pi-core-subagent",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.47",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "pi extension: fast in-process subagents with a dependency-graph scheduler (needs edges gate tasks and carry upstream output into dependent prompts), plus background runs, intercom and agent-to-agent mailbox. Leader defines agents inline.",
|
|
6
6
|
"license": "MIT",
|
package/src/child.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Child-session tools.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Every child gets four talk tools:
|
|
5
5
|
* - ask_parent blocking Q&A with the leader (parent)
|
|
6
6
|
* - notify_parent one-way message to the leader
|
|
7
7
|
* - send_agent_message one-way message to another subagent's mailbox
|
package/src/index.ts
CHANGED
|
@@ -81,12 +81,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
81
81
|
if (value === "on" || value === "off") {
|
|
82
82
|
const next = manager.setAutoLimit(value === "on");
|
|
83
83
|
ctx.ui.notify(
|
|
84
|
-
`auto-limit ${next ? "on" : "off"} — ${next ? "
|
|
84
|
+
`auto-limit ${next ? "on" : "off"} — ${next ? "tasks without an explicit maxRuntimeMs get the 1 h default ceiling" : "raised 6 h ceiling applies (no 1 h cap)"}.`,
|
|
85
85
|
"info",
|
|
86
86
|
);
|
|
87
87
|
} else {
|
|
88
88
|
ctx.ui.notify(
|
|
89
|
-
`auto-limit is ${manager.autoLimitOn ? "on" : "off"} — use \`/subagents auto-limit on|off
|
|
89
|
+
`auto-limit is ${manager.autoLimitOn ? "on (1 h default ceiling)" : "off (6 h ceiling)"} — use \`/subagents auto-limit on|off\`.`,
|
|
90
90
|
"info",
|
|
91
91
|
);
|
|
92
92
|
}
|
|
@@ -157,7 +157,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
157
157
|
// ponytail: this string is billed on every request. No example block — an example
|
|
158
158
|
// biases the model toward one shape; guidelines + JSON schema describe all of them.
|
|
159
159
|
description:
|
|
160
|
-
"Run isolated subagents (own context, own session). You invent each agent: name, optional system prompt, toolset (read-only default, write:true to edit). Use `agent`+`task` for one, `tasks` for many. `needs` declares dependency edges: a task waits for its needs and receives their outputs prepended to its prompt. If a user agent file in `.agents/agents`, `.claude/agents`, or `.pi/agents` (project dirs, then home) has a `description` matching the spawn goal (name + task), that file is authoritative: body = system prompt, frontmatter `model`/`tools` apply, inline prompt/model/tools ignored. No match → the inline definition stands. Write agents run in an isolated git worktree: on completion the result reports the branch + changed files — review, then merge with `git merge --no-ff <branch>` (merged branches are cleaned automatically). Every run is background: the call returns a runId immediately and completion notifies you — do NOT park waiting on it. If you have no other work, end your turn; the completion notice wakes you with the results. Set autoAwait:true only when the very next step in the SAME turn consumes the result.
|
|
160
|
+
"Run isolated subagents (own context, own session). You invent each agent: name, optional system prompt, toolset (read-only default, write:true to edit). Use `agent`+`task` for one, `tasks` for many. `needs` declares dependency edges: a task waits for its needs and receives their outputs prepended to its prompt. If a user agent file in `.agents/agents`, `.claude/agents`, or `.pi/agents` (project dirs, then home) has a `description` matching the spawn goal (name + task), that file is authoritative: body = system prompt, frontmatter `model`/`tools` apply, inline prompt/model/tools ignored. No match → the inline definition stands. Write agents run in an isolated git worktree: on completion the result reports the branch + changed files — review, then merge with `git merge --no-ff <branch>` (merged branches are cleaned automatically). Every run is background: the call returns a runId immediately and completion notifies you — do NOT park waiting on it. If you have no other work, end your turn; the completion notice wakes you with the results. Set autoAwait:true only when the very next step in the SAME turn consumes the result. Children always carry talk tools: they can ask you questions, notify you, and message siblings.",
|
|
161
161
|
promptSnippet: "Define and delegate work to specialized subagents.",
|
|
162
162
|
promptGuidelines: [
|
|
163
163
|
"Use subagent when independent review, testing, research, or parallel analysis improves quality.",
|
|
@@ -172,7 +172,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
172
172
|
"Never block with nothing to do: if you have no work left after spawning, end your turn. Task completion notifies you and wakes a fresh turn with the results — await_subagent/autoAwait in that situation only burns time and tokens.",
|
|
173
173
|
"autoAwait:true only when the same turn must consume the result immediately (e.g. you spawn a reviewer and then must act on its verdict before replying). Otherwise spawn background and read results from the completion notice, or subagent_result when you come back.",
|
|
174
174
|
"await_subagent is for the rare case where you have parallel work of your own and need to sync at a specific point — not the default follow-up to a spawn.",
|
|
175
|
-
"allowIntercom:true only when a child may need to ask you something.",
|
|
176
175
|
],
|
|
177
176
|
parameters: SubagentParams,
|
|
178
177
|
executionMode: "parallel", // sibling subagent calls run concurrently, not serialized
|
|
@@ -237,7 +236,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
237
236
|
: args.agent
|
|
238
237
|
? `single ${args.agent}`
|
|
239
238
|
: "preparing…";
|
|
240
|
-
const flags =
|
|
239
|
+
const flags = args.autoAwait ? "await" : "bg";
|
|
241
240
|
// Params used, dimmed: model, thinking, toolset, per-task write count.
|
|
242
241
|
const tasks = args.tasks ?? args.chain ?? [];
|
|
243
242
|
const writeCount = tasks.filter((t) => t.write).length;
|
|
@@ -269,7 +268,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
269
268
|
})
|
|
270
269
|
.join("");
|
|
271
270
|
return new Text(
|
|
272
|
-
`${theme.fg("toolTitle", theme.bold("subagent"))} ${theme.fg("accent", mode)}
|
|
271
|
+
`${theme.fg("toolTitle", theme.bold("subagent"))} ${theme.fg("accent", mode)} ${theme.fg("muted", `[${flags}]`)}${params}${graphLine}${plan}`,
|
|
273
272
|
0,
|
|
274
273
|
0,
|
|
275
274
|
);
|
package/src/manager.ts
CHANGED
|
@@ -321,8 +321,8 @@ export class SubagentManager {
|
|
|
321
321
|
/** Set by clearRuns — blocks late persists from erasing the sidecar. */
|
|
322
322
|
private cleared = false;
|
|
323
323
|
|
|
324
|
-
/** When
|
|
325
|
-
private autoLimit =
|
|
324
|
+
/** When true, tasks without an explicit maxRuntimeMs get the 1 h default ceiling; when false (default) the raised 6 h ceiling applies — toggle via `/subagents auto-limit on|off`. */
|
|
325
|
+
private autoLimit = false;
|
|
326
326
|
|
|
327
327
|
turnActivity = false;
|
|
328
328
|
|
|
@@ -850,7 +850,7 @@ export class SubagentManager {
|
|
|
850
850
|
const allowedTools = input.write ? WRITE_TOOLS : READONLY_TOOLS;
|
|
851
851
|
const fileTools = file?.tools?.filter((t) => allowedTools.includes(t));
|
|
852
852
|
const baseTools = fileTools?.length ? fileTools : (input.tools ?? allowedTools);
|
|
853
|
-
const tools = [...baseTools, ...
|
|
853
|
+
const tools = [...baseTools, ...CHILD_TALK_TOOLS];
|
|
854
854
|
// Isolation follows the DELIVERED toolset, never the raw request: explicit
|
|
855
855
|
// tools: [bash] without write:true still gets a worktree, and a file that
|
|
856
856
|
// narrowed the child to read-only never gets the commit/merge ceremony.
|
|
@@ -990,9 +990,7 @@ export class SubagentManager {
|
|
|
990
990
|
const worktreeNote = wt
|
|
991
991
|
? ` You work in an isolated git worktree (branch ${wt.branch})${task.stackedOn ? `, stacked on ${task.stackedOn} (its changes are already in your tree)` : ""}. Never run git commands that switch branches, create branches, or move the worktree (git switch/checkout/branch/worktree). The extension commits your changes when you finish. git status/diff are fine for inspecting your own changes. node_modules is a SHARED symlink to the main checkout: never install, upgrade, or delete dependencies (no npm/bun/yarn/pnpm install, no \`rm -rf node_modules\`) — those writes escape your worktree and damage the user's project. If the task truly needs a dependency change, edit the manifest only and say so in your answer.`
|
|
992
992
|
: "";
|
|
993
|
-
const subagentInstruction = run.
|
|
994
|
-
? `You are running as a subagent. Your bash tool already executes in the project working directory — never prefix commands with \`cd\`. Do not call subagent/delegation tools unless the parent explicitly asks. Return a concise final answer. You MAY use ask_parent only when truly blocked on information only the parent has; notify_parent for one-way updates; send_agent_message/poll_agent_messages to coordinate with siblings. Your mailbox address and siblings: ${task.roster ?? "(none)"}. Use the exact task ids (e.g. task_2) as send_agent_message targets. Siblings run independently and may start late or finish early — never block indefinitely on their replies: poll at most 5 times, then proceed with your best judgment. A gated sibling (marked ↳ waits in the graph) may not be running yet; do not wait for it. Stalled waits get the whole run killed. When your work is done, call notify_parent ONCE with a concise result summary — key findings, verdicts, file:line evidence — so the leader can start consuming your output before the run finishes.${worktreeNote}`
|
|
995
|
-
: `You are running as a subagent. Your bash tool already executes in the project working directory — never prefix commands with \`cd\`. Do not call subagent/delegation tools unless the parent explicitly asks. Return a concise final answer for the parent agent.${worktreeNote}`;
|
|
993
|
+
const subagentInstruction = `You are running as a subagent. Your bash tool already executes in the project working directory — never prefix commands with \`cd\`. Do not call subagent/delegation tools unless the parent explicitly asks. Return a concise final answer. You MAY use ask_parent only when truly blocked on information only the parent has; notify_parent for one-way updates; send_agent_message/poll_agent_messages to coordinate with siblings. Your mailbox address and siblings: ${task.roster ?? "(none)"}. Use the exact task ids (e.g. task_2) as send_agent_message targets. Siblings run independently and may start late or finish early — never block indefinitely on their replies: poll at most 5 times, then proceed with your best judgment. A gated sibling (marked ↳ waits in the graph) may not be running yet; do not wait for it. Stalled waits get the whole run killed. When your work is done, call notify_parent ONCE with a concise result summary — key findings, verdicts, file:line evidence — so the leader can start consuming your output before the run finishes.${worktreeNote}`;
|
|
996
994
|
|
|
997
995
|
const loader = new DefaultResourceLoader({
|
|
998
996
|
cwd: childCwd,
|
|
@@ -1005,9 +1003,7 @@ export class SubagentManager {
|
|
|
1005
1003
|
});
|
|
1006
1004
|
await loader.reload();
|
|
1007
1005
|
|
|
1008
|
-
const customTools: ToolDefinition[] = run
|
|
1009
|
-
? createChildTools(task.id, this.makeChildHandlers(run, task, ctx))
|
|
1010
|
-
: [];
|
|
1006
|
+
const customTools: ToolDefinition[] = createChildTools(task.id, this.makeChildHandlers(run, task, ctx));
|
|
1011
1007
|
|
|
1012
1008
|
const created = await createAgentSession({
|
|
1013
1009
|
cwd: childCwd,
|
|
@@ -1324,7 +1320,6 @@ export class SubagentManager {
|
|
|
1324
1320
|
id: newId("run"),
|
|
1325
1321
|
mode,
|
|
1326
1322
|
status: "queued",
|
|
1327
|
-
allowIntercom: Boolean(params.allowIntercom),
|
|
1328
1323
|
notifyPerTask: params.notifyPerTask ?? true,
|
|
1329
1324
|
createdAt: Date.now(),
|
|
1330
1325
|
concurrency: Math.max(1, Math.min(params.concurrency ?? DEFAULT_CONCURRENCY, MAX_CONCURRENCY)),
|
package/src/schemas.ts
CHANGED
|
@@ -67,9 +67,6 @@ export const SubagentParams = Type.Object({
|
|
|
67
67
|
default: true,
|
|
68
68
|
}),
|
|
69
69
|
),
|
|
70
|
-
allowIntercom: Type.Optional(
|
|
71
|
-
Type.Boolean({ description: "Let children ask you questions, notify you, and message sibling subagents" }),
|
|
72
|
-
),
|
|
73
70
|
});
|
|
74
71
|
|
|
75
72
|
/** Derived from the schemas — single source of truth, no hand-maintained mirror. */
|