@fradser/pi-agent-teams 0.5.0 → 0.5.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.
- package/package.json +4 -1
- package/src/index.ts +1 -1
- package/src/spawner.ts +2 -4
- package/src/ui.ts +8 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fradser/pi-agent-teams",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Multi-agent team system for Pi — DAG orchestration, leader inbox, and one-way worker reports",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -36,5 +36,8 @@
|
|
|
36
36
|
"extensions": [
|
|
37
37
|
"./src/index.ts"
|
|
38
38
|
]
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@fradser/pi-kit": "0.1.0"
|
|
39
42
|
}
|
|
40
43
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* pi-agent-teams-fradser — Pi extension for run-centric agent teams.
|
|
3
3
|
*
|
|
4
4
|
* The entry point is composition only: worker capability registration,
|
|
5
5
|
* session lifecycle, and delegation to tools.ts. Scheduling lives in
|
package/src/spawner.ts
CHANGED
|
@@ -12,6 +12,7 @@ import * as fs from "node:fs";
|
|
|
12
12
|
import * as os from "node:os";
|
|
13
13
|
import * as path from "node:path";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { extractTextContent } from "@fradser/pi-kit";
|
|
15
16
|
import type { WorkerUsage } from "./types";
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -307,10 +308,7 @@ function applyWorkerJsonLine(state: WorkerStreamState, line: string): boolean {
|
|
|
307
308
|
if (event.type !== "message_end" || event.message?.role !== "assistant") return false;
|
|
308
309
|
state.turns++;
|
|
309
310
|
if (event.message.stopReason === "stop") state.finalResponse = true;
|
|
310
|
-
const parts = (event.message.content
|
|
311
|
-
.filter((part) => part.type === "text" && typeof part.text === "string")
|
|
312
|
-
.map((part) => part.text as string)
|
|
313
|
-
.join("");
|
|
311
|
+
const parts = extractTextContent(event.message.content, "");
|
|
314
312
|
if (parts.trim()) state.text = parts;
|
|
315
313
|
const u = event.message.usage;
|
|
316
314
|
if (u) {
|
package/src/ui.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Passive teammate widget and interactive full-screen console. */
|
|
2
2
|
|
|
3
3
|
import { truncateToWidth, Key, matchesKey } from "@earendil-works/pi-tui";
|
|
4
|
+
import { createPiThemeStyle, PI_SPINNER_FRAMES, PI_SPINNER_INTERVAL_MS } from "@fradser/pi-kit";
|
|
4
5
|
import type { ExtensionUIContext, Theme, ThemeColor } from "@earendil-works/pi-coding-agent";
|
|
5
6
|
import { truncateTail, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES } from "@earendil-works/pi-coding-agent";
|
|
6
7
|
import {
|
|
@@ -23,8 +24,6 @@ function cap(text: string | undefined, maxBytes = DEFAULT_MAX_BYTES): string {
|
|
|
23
24
|
|
|
24
25
|
const TEAM_COLORS = ["accent", "success", "warning", "error", "toolTitle", "mdLink"] as const;
|
|
25
26
|
const PANEL_IDLE_COLLAPSE_MS = 30_000;
|
|
26
|
-
const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
27
|
-
const SPINNER_MS = 120;
|
|
28
27
|
|
|
29
28
|
let panelRequestRender: (() => void) | undefined;
|
|
30
29
|
let spinnerTimer: ReturnType<typeof setInterval> | undefined;
|
|
@@ -50,7 +49,7 @@ function buildPanelRows(): PanelRow[] {
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
function runningTeammateLabel(node: Node): string {
|
|
53
|
-
const frame =
|
|
52
|
+
const frame = PI_SPINNER_FRAMES[spinnerFrame];
|
|
54
53
|
const tool = node.spawn?.activeTool;
|
|
55
54
|
const thinking = (node.spawn?.liveThinking ?? "").split("\n").map((l) => l.trim()).find((l) => l.length > 0) ?? "";
|
|
56
55
|
const live = (node.spawn?.liveText ?? "").split("\n").map((l) => l.trim()).find((l) => l.length > 0) ?? "";
|
|
@@ -71,9 +70,9 @@ function ensureSpinner(): void {
|
|
|
71
70
|
const running = listNodes().some((node) => node.status === "running");
|
|
72
71
|
if (running && !spinnerTimer) {
|
|
73
72
|
spinnerTimer = setInterval(() => {
|
|
74
|
-
spinnerFrame = (spinnerFrame + 1) %
|
|
73
|
+
spinnerFrame = (spinnerFrame + 1) % PI_SPINNER_FRAMES.length;
|
|
75
74
|
panelRequestRender?.();
|
|
76
|
-
},
|
|
75
|
+
}, PI_SPINNER_INTERVAL_MS);
|
|
77
76
|
spinnerTimer.unref?.();
|
|
78
77
|
} else if (!running && spinnerTimer) {
|
|
79
78
|
clearInterval(spinnerTimer);
|
|
@@ -245,7 +244,7 @@ export function openTeamConsole(ctx: { ui: ExtensionUIContext }): Promise<void>
|
|
|
245
244
|
};
|
|
246
245
|
const startLiveRefresh = () => {
|
|
247
246
|
if (renderTimer) return;
|
|
248
|
-
renderTimer = setInterval(requestRender,
|
|
247
|
+
renderTimer = setInterval(requestRender, PI_SPINNER_INTERVAL_MS);
|
|
249
248
|
renderTimer.unref?.();
|
|
250
249
|
};
|
|
251
250
|
const stopLiveRefresh = () => {
|
|
@@ -255,15 +254,8 @@ export function openTeamConsole(ctx: { ui: ExtensionUIContext }): Promise<void>
|
|
|
255
254
|
};
|
|
256
255
|
startLiveRefresh();
|
|
257
256
|
|
|
258
|
-
// btw-style callbacks (same accent/muted/dim/border/success/error language as
|
|
259
|
-
const style =
|
|
260
|
-
accent: (s: string) => theme.fg("accent", s),
|
|
261
|
-
muted: (s: string) => theme.fg("muted", s),
|
|
262
|
-
dim: (s: string) => theme.fg("dim", s),
|
|
263
|
-
border: (s: string) => theme.fg("border", s),
|
|
264
|
-
success: (s: string) => theme.fg("success", s),
|
|
265
|
-
error: (s: string) => theme.fg("error", s),
|
|
266
|
-
};
|
|
257
|
+
// btw-style callbacks (same accent/muted/dim/border/success/error language as pi-btw-fradser).
|
|
258
|
+
const style = createPiThemeStyle(theme);
|
|
267
259
|
|
|
268
260
|
const windowLines = (full: string[], width: number): { lines: string[]; range: string } => {
|
|
269
261
|
const wrapped = wrapConsoleDetail(full, width);
|
|
@@ -341,7 +333,7 @@ export function openTeamConsole(ctx: { ui: ExtensionUIContext }): Promise<void>
|
|
|
341
333
|
}
|
|
342
334
|
const detail = wrapConsoleDetail(buildNodeDetail(detailKey), tui.terminal.columns);
|
|
343
335
|
const viewport = maxConsoleBody(tui.terminal.rows);
|
|
344
|
-
// Mouse-wheel scrolling (SGR wheel events, same as
|
|
336
|
+
// Mouse-wheel scrolling (SGR wheel events, same as pi-btw-fradser).
|
|
345
337
|
const sgrWheel = /^\x1b\[<(\d+);(\d+);(\d+)[Mm]$/.exec(data);
|
|
346
338
|
if (sgrWheel) {
|
|
347
339
|
const button = Number.parseInt(sgrWheel[1], 10);
|