@arhen/pi-core-subagent 1.1.7 → 1.1.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +24 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arhen/pi-core-subagent",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "type": "module",
5
5
  "description": "pi extension: fast in-process subagents with single/parallel/chain, background runs, intercom and agent-to-agent mailbox. Leader defines agents inline.",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -253,8 +253,6 @@ function compactLines(run: RunSnapshot): string[] {
253
253
  * └─ ✓ reviewer · 6 tools · 44s
254
254
  * Static icons (no animation); latest activity + tool count + runtime per agent.
255
255
  */
256
- const WIDGET_MAX_RUNS = 3;
257
- const WIDGET_MAX_TASKS_PER_RUN = 4;
258
256
  const WIDGET_MAX_LINES = 10;
259
257
 
260
258
  class SubagentsWidget implements Component {
@@ -268,38 +266,39 @@ class SubagentsWidget implements Component {
268
266
  }
269
267
 
270
268
  render(width: number): string[] {
271
- const runs = this.getRuns();
269
+ // ONE flat tree: every run's tasks concatenated under a single heading.
270
+ // Whether the model spawned N runs or one tasks[] call, the pane reads the same.
271
+ const runs = this.getRuns().filter((r) => r.tasks.length > 0);
272
272
  if (runs.length === 0) return [];
273
- const lines: string[] = [];
274
- let renderedRuns = 0;
275
- for (const run of runs.slice(0, WIDGET_MAX_RUNS)) {
276
- if (run.tasks.length === 0) continue;
277
- if (lines.length > 0) lines.push("");
278
- const done = run.tasks.filter((t) => TERMINAL.includes(t.status)).length;
279
- const active = !TERMINAL.includes(run.status);
280
- const head = active ? "accent" : "dim";
281
- lines.push(truncateToWidth(`${this.theme.fg(head, active ? "●" : "○")} ${this.theme.fg(head, `Subagents (${done}/${run.tasks.length})`)}`, width, "…"));
273
+ const total = runs.reduce((n, r) => n + r.tasks.length, 0);
274
+ const done = runs.reduce((n, r) => n + r.tasks.filter((t) => TERMINAL.includes(t.status)).length, 0);
275
+ const live = total - done;
276
+ const head = live > 0 ? "accent" : "dim";
277
+ const lines = [truncateToWidth(`${this.theme.fg(head, live > 0 ? "●" : "○")} ${this.theme.fg(head, `Subagents (${done}/${total})`)}`, width, "")];
278
+ const budget = WIDGET_MAX_LINES - 1;
279
+ let shown = 0;
280
+ outer: for (const run of runs) {
282
281
  const allDone = TERMINAL.includes(run.status);
283
- const visible = run.tasks.slice(0, WIDGET_MAX_TASKS_PER_RUN);
284
- visible.forEach((task, i) => {
285
- const last = i === visible.length - 1 && run.tasks.length <= WIDGET_MAX_TASKS_PER_RUN;
286
- const conn = this.theme.fg("dim", last ? "└─" : "├─");
282
+ for (const task of run.tasks) {
283
+ if (shown >= budget) break outer;
284
+ shown += 1;
287
285
  const activity =
288
286
  !TERMINAL.includes(task.status) && task.lastActivity
289
287
  ? `${this.theme.fg("dim", `→ ${task.lastActivity}`)} · `
290
288
  : "";
291
- // Finished run: dim everything except the agent name.
289
+ // Tasks of a finished run: dim everything except the agent name.
292
290
  const line = allDone
293
291
  ? `${this.theme.fg("dim", `${statusIcon(task.status)} `)}${task.agent} ${this.theme.fg("dim", `· ${taskStatsWithUsage(task)} · ${taskTimer(task)}`)}`
294
292
  : `${statusIcon(task.status)} ${task.agent} · ${activity}${taskStatsWithUsage(task)} · ${taskTimer(task)}`;
295
- lines.push(truncateToWidth(`${conn} ${line}`, width, "…"));
296
- });
297
- if (run.tasks.length > WIDGET_MAX_TASKS_PER_RUN) lines.push(`${this.theme.fg("dim", "└─")} ${this.theme.fg("dim", `+${run.tasks.length - WIDGET_MAX_TASKS_PER_RUN} more tasks`)}`);
298
- renderedRuns += 1;
299
- if (lines.length >= WIDGET_MAX_LINES) break; // keep the editor visible
293
+ lines.push(truncateToWidth(`${this.theme.fg("dim", "├─")} ${line}`, width, "…"));
294
+ }
295
+ }
296
+ const hidden = total - shown;
297
+ if (hidden > 0) {
298
+ lines.push(`${this.theme.fg("dim", "└─")} ${this.theme.fg("dim", `+${hidden} more`)}`);
299
+ } else if (lines.length > 1) {
300
+ lines[lines.length - 1] = lines[lines.length - 1]!.replace("├─", "└─");
300
301
  }
301
- const hiddenRuns = runs.length - renderedRuns;
302
- if (hiddenRuns > 0) lines.push(`${this.theme.fg("dim", "└─")} ${this.theme.fg("dim", `+${hiddenRuns} more run${hiddenRuns > 1 ? "s" : ""}`)}`);
303
302
  return lines;
304
303
  }
305
304
  }
@@ -1164,7 +1163,7 @@ export default function (pi: ExtensionAPI) {
1164
1163
  promptSnippet: "Define and delegate work to specialized subagents.",
1165
1164
  promptGuidelines: [
1166
1165
  "Use subagent when independent review, testing, research, or parallel analysis improves quality.",
1167
- "Decompose parallelizable work: if the request has 2+ independent sub-tasks (separate files, separate concerns, independent research/review), delegate each to its own subagent in ONE call with tasks[] (single shot), not multiple parallel subagent calls.",
1166
+ "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.",
1168
1167
  "If independent sub-tasks are sequential (each builds on the previous one's output), use chain mode with {previous}.",
1169
1168
  "Define each subagent yourself: an invented name, a focused system prompt (prompt:), and a toolset — read-only (default) or write (write:true).",
1170
1169
  "Prefer read-only subagents unless the task explicitly needs edits.",