@ferris1225/pi-subagents 0.22.0 → 0.24.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 +7 -15
- package/package.json +1 -1
- package/src/index.ts +68 -49
package/README.md
CHANGED
|
@@ -459,25 +459,17 @@ The package has no runtime dependencies beyond pi peer dependencies.
|
|
|
459
459
|
## Acknowledgments
|
|
460
460
|
|
|
461
461
|
- The official [pi subagent example](https://github.com/earendil-works/pi)
|
|
462
|
-
(`examples/extensions/subagent`) —
|
|
463
|
-
event-stream handling
|
|
464
|
-
- [
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
- [tintinweb/pi-subagents](https://github.com/tintinweb/pi-subagents) — Claude Code-
|
|
468
|
-
style sub-agents for pi with parallel execution and a live widget; this project's
|
|
469
|
-
widget and parallel fan-out follow the same ideas.
|
|
470
|
-
- [amosblomqvist/pi-subagents](https://github.com/amosblomqvist/pi-subagents) — a
|
|
471
|
-
clean, minimal reference for markdown-defined agents in pi.
|
|
472
|
-
- [edxeth/pi-subagents](https://github.com/edxeth/pi-subagents) — multi-agent
|
|
473
|
-
coordination patterns (background agents, child-to-parent messaging) that are
|
|
474
|
-
worth borrowing from.
|
|
462
|
+
(`examples/extensions/subagent`) — the child-process dispatch and
|
|
463
|
+
event-stream handling build on it.
|
|
464
|
+
- [tintinweb/pi-subagents](https://github.com/tintinweb/pi-subagents) — the
|
|
465
|
+
live widget (two lines per run: header + quiet gray activity row) and
|
|
466
|
+
parallel fan-out follow its design.
|
|
475
467
|
- The sub-agent pattern itself, popularized by
|
|
476
468
|
[Claude Code](https://github.com/anthropics/claude-code): role-specialized
|
|
477
469
|
agents that receive self-contained briefs.
|
|
478
470
|
|
|
479
|
-
The agent prompts and extension code are written independently for this
|
|
480
|
-
the projects above served as design references.
|
|
471
|
+
The agent prompts and extension code are written independently for this
|
|
472
|
+
project; the projects above served as design references.
|
|
481
473
|
|
|
482
474
|
## License
|
|
483
475
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ferris1225/pi-subagents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.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
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { getAgentDir, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
16
|
-
import { Text } from "@earendil-works/pi-tui";
|
|
16
|
+
import { Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
17
17
|
import { Type } from "typebox";
|
|
18
18
|
import { discoverAgents, type AgentConfig } from "./agents.ts";
|
|
19
19
|
import { BackgroundTaskQueue } from "./background.ts";
|
|
@@ -52,7 +52,6 @@ import {
|
|
|
52
52
|
formatToolActivity,
|
|
53
53
|
formatUsageCompact,
|
|
54
54
|
monitor,
|
|
55
|
-
rightAlign,
|
|
56
55
|
statusIcon,
|
|
57
56
|
statusLabel,
|
|
58
57
|
type RunChainMeta,
|
|
@@ -776,54 +775,74 @@ export default function (pi: ExtensionAPI): void {
|
|
|
776
775
|
}
|
|
777
776
|
}, 1000);
|
|
778
777
|
return {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
//
|
|
787
|
-
//
|
|
788
|
-
//
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
778
|
+
render(width: number): string[] {
|
|
779
|
+
const runs = monitor.getRuns();
|
|
780
|
+
if (runs.length === 0) return [];
|
|
781
|
+
const now = Date.now();
|
|
782
|
+
const lines: string[] = [];
|
|
783
|
+
// Tree layout: each top-level agent is a root whose title/activity hang
|
|
784
|
+
// off it as branches; auto-fix chain runs (groupId) become child nodes
|
|
785
|
+
// under their parent root, with a "│" continuation while more siblings
|
|
786
|
+
// follow. Blank lines separate agent blocks so parallel runs don't blur
|
|
787
|
+
// into one wall of text.
|
|
788
|
+
const dim = (t: string): string => theme.fg("dim", t);
|
|
789
|
+
for (let idx = 0; idx < runs.length; idx++) {
|
|
790
|
+
const r = runs[idx];
|
|
791
|
+
const isChain = Boolean(r.groupId);
|
|
792
|
+
const chainContinues = isChain && runs[idx + 1]?.groupId === r.groupId;
|
|
793
|
+
const activity =
|
|
794
|
+
r.activity && (r.status === "running" || r.status === "queued") ? r.activity : undefined;
|
|
795
|
+
const hasActivity = activity !== undefined;
|
|
796
|
+
const icon = statusIcon(r.status, theme);
|
|
797
|
+
// Chain-internal runs (auto-fix worker/reviewer) are child nodes under
|
|
798
|
+
// their parent reviewer. Their relationLabel ("fix round 1") is more
|
|
799
|
+
// distinguishing than the repeated worker/reviewer name.
|
|
800
|
+
const name = isChain ? (r.relationLabel ?? r.agent) : r.agent;
|
|
801
|
+
// Two lines per run: the header row (icon, run id, agent name) and the
|
|
802
|
+
// live activity branch below. The task summary is deliberately not
|
|
803
|
+
// shown — the task lives in the tool result, and the agent name plus
|
|
804
|
+
// what it is doing right now is enough to tell runs apart. The header
|
|
805
|
+
// stays exactly as it was (accent name, dim stats), matching the
|
|
806
|
+
// referenced sub-agent widgets (tintinweb): the running indicator
|
|
807
|
+
// uses the accent color, everything else is quiet.
|
|
808
|
+
if (!isChain && lines.length > 0) lines.push("");
|
|
809
|
+
const nodeBranch = isChain ? (chainContinues ? "├─ " : "└─ ") : "";
|
|
810
|
+
const left = `${dim(nodeBranch)}${icon} ${dim(`#${r.id}`)} ${isChain ? name : theme.fg("accent", theme.bold(name))}`;
|
|
811
|
+
|
|
812
|
+
// Right side: full model ref (provider/model), token usage (in/out +
|
|
813
|
+
// cache read/write), tool count, elapsed, and the soft activity-state
|
|
814
|
+
// annotation (idle / long-running). Trailing the header with a single
|
|
815
|
+
// " · " chain keeps the row compact (no center gap); compactLine
|
|
816
|
+
// clips on overflow, never the right side on its own.
|
|
817
|
+
const model = r.model ?? "?";
|
|
818
|
+
const usage = formatUsageCompact(r.usage);
|
|
819
|
+
const tools = r.toolCount ? `${r.toolCount} tool${r.toolCount === 1 ? "" : "s"}` : "";
|
|
820
|
+
const elapsed = formatElapsed(r, now);
|
|
821
|
+
const metaParts = [model, usage, tools, elapsed].filter(Boolean);
|
|
822
|
+
// Running is conveyed by the icon + elapsed; spell out the label only for
|
|
823
|
+
// the other states (ready / done / stopped) so they are unambiguous.
|
|
824
|
+
if (r.status !== "running") metaParts.push(statusLabel(r.status));
|
|
825
|
+
const state = deriveActivityState(r, now);
|
|
826
|
+
if (state) metaParts.push(activityStateLabel(state));
|
|
827
|
+
if (r.annotation) metaParts.push(r.annotation);
|
|
828
|
+
// Metadata trails the header in dim — quiet, never competing with the
|
|
829
|
+
// accent agent name (the same restraint the referenced widgets use).
|
|
830
|
+
// Trailing with a single " · " chain keeps the row compact (no center
|
|
831
|
+
// gap); compactLine clips on overflow, never the right side on its own.
|
|
832
|
+
const right = metaParts.length ? dim(` · ${metaParts.join(" · ")}`) : "";
|
|
833
|
+
lines.push(compactLine(left, right, width));
|
|
834
|
+
|
|
835
|
+
// Current activity ("read src/index.ts", "bash npm test") is the only
|
|
836
|
+
// branch: gray, so it never competes with the agent name or pi's own
|
|
837
|
+
// UI. Chain nodes that still have siblings carry a "│" continuation
|
|
838
|
+
// down to the last one.
|
|
839
|
+
if (hasActivity) {
|
|
840
|
+
const continuation = isChain ? (chainContinues ? "│ " : " ") : "";
|
|
841
|
+
lines.push(truncateToWidth(`${continuation}${dim("└─ ")}${dim(activity)}`, width));
|
|
842
|
+
}
|
|
823
843
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
},
|
|
844
|
+
return lines;
|
|
845
|
+
},
|
|
827
846
|
invalidate() {},
|
|
828
847
|
dispose() {
|
|
829
848
|
unsub();
|