@arhen/pi-core-subagent 1.2.2 → 1.3.1

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.
Files changed (3) hide show
  1. package/README.md +18 -1
  2. package/package.json +1 -1
  3. package/src/index.ts +16 -17
package/README.md CHANGED
@@ -133,7 +133,7 @@ Background + intercom:
133
133
  | Tool | Purpose |
134
134
  |---|---|
135
135
  | `subagent` | single / `tasks` (parallel or graph via `needs`) / `chain` (`{previous}`); `background:true` fire-and-forget; `allowIntercom:true` enables child talk tools; `notifyPerTask: true` wakes you as each task completes (default off) |
136
- | `subagent_status` | live per-task snapshot (non-blocking) |
136
+ | `subagent_status` | live per-task snapshot (non-blocking), including each child's session file path |
137
137
  | `subagent_result` | full output of a run or one task |
138
138
  | `await_subagent` | block until a run finishes (optional `timeoutMs`) |
139
139
  | `reply_subagent` | answer a child's `ask_parent` question |
@@ -161,6 +161,23 @@ Read-only pane over the session's subagents:
161
161
  - `x` then `y` — abort ONE subagent (only mutation; `n`/any other key cancels)
162
162
  - `esc` — close
163
163
 
164
+ ## Watching a child from outside
165
+
166
+ `subagent_status` returns each running child's session file (JSONL). Children are `AgentSession`s in this process — they have no TTY — but their transcript is a real file, so any external viewer can follow one:
167
+
168
+ ```sh
169
+ tail -f /path/from/subagent_status.jsonl
170
+ ```
171
+
172
+ In a terminal multiplexer, that is a pane per agent — e.g. with [Herdr](https://herdr.dev):
173
+
174
+ ```sh
175
+ herdr pane split --current --direction right
176
+ herdr pane run w1:p2 "tail -f /path/from/subagent_status.jsonl"
177
+ ```
178
+
179
+ The extension has no multiplexer integration and does not want one: it exposes the path, your agent already knows how to drive its own terminal. For an in-pi view of the same stream, use [`/subagents peek`](#peek--subagents-peek-or-ctrlshifta).
180
+
164
181
  ## Context budget
165
182
 
166
183
  - Parent tools: 6 schemas with short descriptions. **No catalog, no context hook** — nothing injected per request.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arhen/pi-core-subagent",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
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/index.ts CHANGED
@@ -1252,12 +1252,7 @@ const TaskItem = Type.Object({
1252
1252
  cwd: Type.Optional(Type.String({ description: "Working directory for this task. Default: current project." })),
1253
1253
  tools: Type.Optional(Type.Array(Type.String(), { description: "Explicit tool allowlist (overrides the toolset)" })),
1254
1254
  maxRuntimeMs: Type.Optional(Type.Number({ description: "Per-task timeout (ms)" })),
1255
- needs: Type.Optional(
1256
- Type.Array(Type.String(), {
1257
- description:
1258
- "Task ids this task depends on (requires those tasks to declare id). It starts only after they finish, and their outputs are prepended to its prompt. Tasks with no unmet needs run together as a wave.",
1259
- }),
1260
- ),
1255
+ needs: Type.Optional(Type.Array(Type.String(), { description: "Ids of tasks this one waits for; their outputs are prepended to this prompt." })),
1261
1256
  });
1262
1257
 
1263
1258
  type SubagentParamsShape = {
@@ -1380,18 +1375,18 @@ export default function (pi: ExtensionAPI) {
1380
1375
  pi.registerTool<typeof SubagentParams, RunDetails>({
1381
1376
  name: "subagent",
1382
1377
  label: "Subagent",
1383
- description: "Define and run isolated subagents (own context, own session). You invent the agent: name, optional system prompt, toolset (read-only default, write:true for edits). Modes: single, parallel (tasks), chain ({previous}). Tasks with `needs` form a dependency graph: each wave of tasks with satisfied needs runs in parallel, and an upstream task's output is prepended to its dependents' prompts. background:true fire-and-forgets with completion notice. allowIntercom:true lets children ask you questions and message each other.\n\nExamples (copy these shapes):\nSingle: subagent({ agent: \"reviewer\", prompt: \"You review code for correctness\", task: \"Review src/auth.ts\" })\nParallel: subagent({ tasks: [{ agent: \"mapper\", task: \"Map all API routes\" }, { agent: \"critic\", task: \"Review auth for vulnerabilities\" }] })\nGraph: subagent({ tasks: [{ id: \"api\", agent: \"api-mapper\", task: \"Map API routes\" }, { id: \"db\", agent: \"db-mapper\", task: \"Map DB schema\" }, { id: \"doc\", agent: \"writer\", needs: [\"api\", \"db\"], write: true, task: \"Write ARCHITECTURE.md. Verify: test -s ARCHITECTURE.md\" }] })\nChain: subagent({ chain: [{ agent: \"planner\", task: \"Plan the change\" }, { agent: \"doer\", write: true, task: \"Execute: {previous}\" }] })\nBackground: subagent({ agent: \"auditor\", task: \"Audit deps\", background: true })",
1378
+ // ponytail: this string is billed on every request. One example the graph one
1379
+ // covers ids, needs, write and Verify; the simpler shapes are subsets of it.
1380
+ description:
1381
+ "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. background:true returns immediately; allowIntercom:true lets children talk to you and each other.\n\nsubagent({ tasks: [{ id: \"api\", agent: \"api-mapper\", task: \"Map API routes\" }, { id: \"db\", agent: \"db-mapper\", task: \"Map DB schema\" }, { id: \"doc\", agent: \"writer\", needs: [\"api\", \"db\"], write: true, task: \"Write ARCHITECTURE.md. Verify: test -s ARCHITECTURE.md\" }] })",
1384
1382
  promptSnippet: "Define and delegate work to specialized subagents.",
1385
1383
  promptGuidelines: [
1386
1384
  "Use subagent when independent review, testing, research, or parallel analysis improves quality.",
1387
- "Decompose parallelizable work: if the request has 2+ independent sub-tasks (separate files, separate concerns, independent research/review), spawn N agents with a SINGLE call: subagent({ tasks: [{agent, task}, ...] }). NEVER make multiple parallel subagent calls for parallel work — one call, one run, N tasks.",
1388
- "If independent sub-tasks are sequential (each builds on the previous one's output), use chain mode with {previous}.",
1389
- "When some tasks depend on others but not all do, give tasks an `id` and list `needs`. Independent tasks then still run in parallel while dependents wait, and each dependent receives its upstream outputs automatically — do not re-describe them in the prompt.",
1390
- "Give every task a way to check itself: end the task text with a runnable command, e.g. 'Verify: npx tsc --noEmit && bun test'. A subagent's own claim of success is not evidence.",
1391
- "Define each subagent yourself: an invented name, a focused system prompt (prompt:), and a toolset read-only (default) or write (write:true).",
1392
- "Prefer read-only subagents unless the task explicitly needs edits.",
1393
- "Use background:true for long-running work; you'll be notified on completion.",
1394
- "Use allowIntercom:true only when a child may need to ask you something; keep children autonomous otherwise.",
1385
+ "Put every sub-task in ONE call: subagent({ tasks: [...] }). Never make multiple parallel subagent calls — one call, one run, N tasks.",
1386
+ "Order comes from `needs`, not from separate calls: give tasks an `id`, list the ids each depends on. Tasks with no unmet needs run in parallel; dependents receive their upstream outputs automatically — do not restate them.",
1387
+ "End each task with a runnable check, e.g. 'Verify: npx tsc --noEmit && bun test'. A subagent's claim of success is not evidence.",
1388
+ "Define each agent yourself: invented name, focused system prompt, and read-only (default) or write:true. Prefer read-only.",
1389
+ "Use background:true for long work; allowIntercom:true only when a child may need to ask you something.",
1395
1390
  ],
1396
1391
  parameters: SubagentParams,
1397
1392
  executionMode: "parallel", // sibling subagent calls run concurrently, not serialized
@@ -1473,14 +1468,18 @@ export default function (pi: ExtensionAPI) {
1473
1468
  pi.registerTool<typeof RunIdParam, { run?: RunSnapshot }>({
1474
1469
  name: "subagent_status",
1475
1470
  label: "Subagent Status",
1476
- description: "Live status of a subagent run (non-blocking): per-task state.",
1471
+ description: "Live status of a subagent run (non-blocking): per-task state, plus each child's session file path (JSONL) so you can tail it from outside — e.g. in a terminal multiplexer pane.",
1477
1472
  promptSnippet: "Check progress of a subagent run.",
1478
1473
  parameters: RunIdParam,
1479
1474
  async execute(_id, params) {
1480
1475
  const { runId } = params as { runId: string };
1481
1476
  const run = manager.getRun(runId);
1482
1477
  if (!run) return { content: [{ type: "text", text: `Unknown runId: ${runId}` }], isError: true, details: {} };
1483
- return { content: [{ type: "text", text: compactLines(run).join("\n") }], details: { run: cloneRun(run) } };
1478
+ // Session file paths are the one primitive an outside tool needs: `tail -f` it in a
1479
+ // multiplexer pane, a log viewer, anything. Cheaper than owning a pane integration.
1480
+ const files = run.tasks.filter((t) => t.sessionFile).map((t) => `${t.id} (${t.agent}): ${t.sessionFile}`);
1481
+ const text = [compactLines(run).join("\n"), ...(files.length > 0 ? ["", "Live session files (tail -f to watch):", ...files] : [])].join("\n");
1482
+ return { content: [{ type: "text", text }], details: { run: cloneRun(run) } };
1484
1483
  },
1485
1484
  });
1486
1485