@d3ara1n/pi-subagent 3.3.1 → 3.4.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 +2 -1
- package/package.json +2 -1
- package/src/activity.test.ts +3 -4
- package/src/index.ts +45 -33
- package/src/utils.ts +4 -1
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ Observations on how main models behave with this plugin, one family per subsecti
|
|
|
64
64
|
|
|
65
65
|
| Command | Description |
|
|
66
66
|
|---------|-------------|
|
|
67
|
-
| `/subagent:view` | Open the live view: a tabbed overlay with a per-run activity feed and a brief detail page (inputs, files, stats), plus modal steer input for the focused run — doubles as the session's run archive |
|
|
67
|
+
| `/subagent:view` | Open the live view: a tabbed overlay with a per-run activity feed and a brief detail page (inputs, files, stats), plus modal steer input for the focused run — doubles as the session's run archive. Also available as the native palette entry **Subagent: Activity View** (Ctrl+Shift+P via [`pi-command-palette`](../pi-command-palette)), which opens the view directly without needing an empty editor |
|
|
68
68
|
| `/subagent:doctor` | Diagnose pi invocation, model-role resolution, configuration, and role references |
|
|
69
69
|
| `/subagent:status` | List background runs and their current state |
|
|
70
70
|
| `/subagent:cancel <id\|all> [reason]` | Cancel a live background run (or every live run); the optional reason is recorded with the run |
|
|
@@ -82,6 +82,7 @@ Steer input is modal so keys never conflict with typing: in browse mode `s` open
|
|
|
82
82
|
## Dependencies
|
|
83
83
|
|
|
84
84
|
- [`@d3ara1n/pi-model-roles`](../pi-model-roles) — model role resolution
|
|
85
|
+
- [`@d3ara1n/pi-command-palette-core`](../pi-command-palette-core) — native command-palette registry (pure npm library, installed automatically; the palette entry appears when [`pi-command-palette`](../pi-command-palette) is installed)
|
|
85
86
|
|
|
86
87
|
## Installation
|
|
87
88
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d3ara1n/pi-subagent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Role-based subagent orchestration for pi — delegates tasks to specialized pi child processes with configurable model roles",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@d3ara1n/pi-command-palette-core": "*",
|
|
30
31
|
"@d3ara1n/pi-model-roles": "*"
|
|
31
32
|
},
|
|
32
33
|
"pi": {
|
package/src/activity.test.ts
CHANGED
|
@@ -42,11 +42,10 @@ test("queued items share the visible limit and consumption changes only the mark
|
|
|
42
42
|
assert.equal(buildDisplayItems(log).length, 7);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
test("queued rendering uses status for every display type and
|
|
45
|
+
test("queued rendering uses status for every display type and steer color follows delivery status", () => {
|
|
46
46
|
const color = (name: string, text: string) => `<${name}>${text}</${name}>`;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
47
|
+
assert.match(formatDisplayItem({ type: "steer", status: "queued", text: "input" }, color), /^<accent>/);
|
|
48
|
+
assert.match(formatDisplayItem({ type: "steer", status: "done", text: "input" }, color), /^<dim>/);
|
|
50
49
|
assert.equal(formatDisplayItem({ type: "steer", status: "done", text: "queued" }, plain), "\u21a9 steer: queued");
|
|
51
50
|
assert.match(formatDisplayItem({ type: "thinking", status: "queued" }, plain), /\(queued\)/);
|
|
52
51
|
assert.match(formatDisplayItem({ type: "toolCall", name: "read", args: {}, status: "queued" }, plain), /\(queued\)/);
|
package/src/index.ts
CHANGED
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
* - Accurate, concise output for the main model
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
16
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
17
17
|
import { Type } from "typebox";
|
|
18
18
|
import { getModelRolesAPI } from "@d3ara1n/pi-model-roles";
|
|
19
|
+
import { paletteCommandRegistry } from "@d3ara1n/pi-command-palette-core";
|
|
19
20
|
import type { SubagentConfig, SubagentResult, SubagentRole } from "./types.ts";
|
|
20
21
|
import { DEFAULT_CONFIG } from "./types.ts";
|
|
21
22
|
import { loadSubagentConfig } from "./config.ts";
|
|
@@ -713,8 +714,7 @@ export default function subagentExtension(pi: ExtensionAPI) {
|
|
|
713
714
|
parameters: Type.Object({
|
|
714
715
|
id: Type.String({ description: "Run id returned by a background delegate call" }),
|
|
715
716
|
message: Type.String({
|
|
716
|
-
description:
|
|
717
|
-
"The concrete correction or updated requirement for the child to follow.",
|
|
717
|
+
description: "The concrete correction or updated requirement for the child to follow.",
|
|
718
718
|
}),
|
|
719
719
|
}),
|
|
720
720
|
|
|
@@ -809,38 +809,50 @@ export default function subagentExtension(pi: ExtensionAPI) {
|
|
|
809
809
|
renderResult: renderCancelResult,
|
|
810
810
|
});
|
|
811
811
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
812
|
+
// ── Subagent activity view ─────────────────────────────────────────
|
|
813
|
+
// Shared by the /subagent:view command and the native command-palette
|
|
814
|
+
// entry — both open the same overlay.
|
|
815
|
+
//
|
|
816
|
+
// Union of every known run: the background registry — append-only for
|
|
817
|
+
// the whole session, the view doubles as the run archive and derives
|
|
818
|
+
// nothing from delivery state — plus live in-flight runs (foreground
|
|
819
|
+
// delegate calls included, visible only while in flight). Dedupe by
|
|
820
|
+
// id — background runs appear in both.
|
|
821
|
+
async function openSubagentView(ctx: ExtensionContext): Promise<void> {
|
|
822
|
+
const runsProvider = () => {
|
|
823
|
+
const seen = new Set<string>();
|
|
824
|
+
const out: RunHandle[] = [];
|
|
825
|
+
for (const r of [...backgroundRuns.values(), ...liveRuns]) {
|
|
826
|
+
if (!seen.has(r.id)) {
|
|
827
|
+
seen.add(r.id);
|
|
828
|
+
out.push(r);
|
|
828
829
|
}
|
|
829
|
-
return out;
|
|
830
|
-
};
|
|
831
|
-
if (runsProvider().length === 0) {
|
|
832
|
-
ctx.ui.notify("No subagent runs yet.", "info");
|
|
833
|
-
return;
|
|
834
830
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
831
|
+
return out;
|
|
832
|
+
};
|
|
833
|
+
await ctx.ui.custom(
|
|
834
|
+
(tui, theme, _keybindings, done) =>
|
|
835
|
+
createViewPanel(runsProvider, tui, theme, () => done(undefined)),
|
|
836
|
+
{
|
|
837
|
+
overlay: true,
|
|
838
|
+
overlayOptions: { anchor: "center", width: "90%", maxHeight: "85%" },
|
|
839
|
+
},
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
pi.registerCommand("subagent:view", {
|
|
844
|
+
description:
|
|
845
|
+
"Open the subagent activity view (watch runs, steer, browse the session's archive)",
|
|
846
|
+
handler: (_args, ctx) => openSubagentView(ctx),
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
// Native command-palette entry — opens the view directly, no editor
|
|
850
|
+
// round-trip, so it works mid-draft.
|
|
851
|
+
paletteCommandRegistry.register({
|
|
852
|
+
id: "subagent:view",
|
|
853
|
+
label: "Subagent: Activity View",
|
|
854
|
+
description: "Watch subagent runs, steer, browse the session's archive",
|
|
855
|
+
run: (_pi, ctx) => openSubagentView(ctx),
|
|
844
856
|
});
|
|
845
857
|
|
|
846
858
|
pi.registerCommand("subagent:doctor", {
|
package/src/utils.ts
CHANGED
|
@@ -288,7 +288,10 @@ export function formatDisplayItem(
|
|
|
288
288
|
const queued = item.status === "queued";
|
|
289
289
|
const marker = queued ? " (queued)" : "";
|
|
290
290
|
if (item.type === "steer") {
|
|
291
|
-
|
|
291
|
+
// Color follows delivery status like every other entry (queued = accent,
|
|
292
|
+
// consumed = dim); the ↩ glyph alone carries the external-origin marker.
|
|
293
|
+
const steerColor = queued ? "accent" : "dim";
|
|
294
|
+
return fg(steerColor, `\u21a9 steer${marker}: ${oneLine(item.text)}`);
|
|
292
295
|
}
|
|
293
296
|
if (queued) {
|
|
294
297
|
const body = item.type === "thinking" ? "thinking" : formatToolCall(item.name, item.args, (_c, text) => text);
|