@ferris1225/pi-subagents 4.3.12 → 4.3.13

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/CHANGELOG.md CHANGED
@@ -3,6 +3,13 @@
3
3
  Release notes for `@ferris1225/pi-subagents`. Only the most recent releases
4
4
  are kept here; every published version is preserved as a GitHub Release.
5
5
 
6
+ ## 4.3.13
7
+
8
+ - Remove the `subagents N running · …` activity-count line from the footer.
9
+ Live progress stays visible in the above-editor widget, per-run completion
10
+ notifications, and `subagent_status`; the footer is reserved for the
11
+ per-model cost tally.
12
+
6
13
  ## 4.3.12
7
14
 
8
15
  - Replace pi's built-in consumption line with a per-model cost footer for the
package/README.md CHANGED
@@ -12,6 +12,10 @@ once and your main agent delegates on its own.
12
12
 
13
13
  ## What's new
14
14
 
15
+ **4.3.13** — the footer is reserved for the per-model cost tally: the
16
+ `subagents N running` activity-count line is gone, leaving the widget,
17
+ completion notifications, and `subagent_status` for live progress.
18
+
15
19
  **4.3.12** — per-model accounting: the main window's consumption line becomes a
16
20
  per-model cost footer (token flow, cost, context share, and live `tok/s` per
17
21
  `provider/model`), awaited children's usage is no longer folded into the parent
@@ -355,19 +359,6 @@ for shared-checkout write serialization, or `starting`. The widget is
355
359
  capped at ten lines: when many runs are live, extra runs collapse into a
356
360
  `… +N more` marker so the editor keeps its space.
357
361
 
358
- The widget is the detailed surface, but it only pays off while you are looking
359
- at it. A one-line roll-up in the always-visible footer answers "is anything
360
- still working?" without opening the widget or asking:
361
-
362
- ```text
363
- subagents 2 running · 1 repo lane · 3 done
364
- ```
365
-
366
- It is count-only, keeps the same wait vocabulary as the widget, and works in
367
- RPC hosts as well as the TUI. Settled counts stay on the line only while a
368
- sibling is still live (`2 running · 3 done`); the line disappears once nothing
369
- is active.
370
-
371
362
  ### Per-model cost footer
372
363
 
373
364
  In TUI sessions the extension replaces pi's built-in consumption line with a
package/index.ts CHANGED
@@ -8,7 +8,8 @@
8
8
  * - execution/ — process queue, RPC transport/control, and model handoff
9
9
  * - lifecycle/ — durable threads, restoration, controls, and delivery
10
10
  * - isolation/ — Git worktrees, recovery, and temporary-state hygiene
11
- * - presentation/ — announcements, formatting, monitor, status, and widget
11
+ * - presentation/ — announcements, cost footer/ledger, formatting, monitor,
12
+ * and the active-run widget
12
13
  *
13
14
  * Also registers the `/subagents-setup` command and a `before_agent_start` hook
14
15
  * that injects a delegation directive into the parent system prompt so the main
@@ -34,7 +35,6 @@ import { registerAnnouncements } from "./src/presentation/announcements.ts";
34
35
  import { registerMainCostTracking } from "./src/presentation/cost-ledger.ts";
35
36
  import { clearCostFooter } from "./src/presentation/cost-footer.ts";
36
37
  import { matchRunIds } from "./src/presentation/format.ts";
37
- import { clearActiveRunsStatus } from "./src/presentation/status.ts";
38
38
  import { clearActiveRunsWidget } from "./src/presentation/widget.ts";
39
39
 
40
40
  export { matchRunIds };
@@ -66,7 +66,6 @@ export default function (pi: ExtensionAPI): void {
66
66
  );
67
67
 
68
68
  pi.on("session_shutdown", async (_event, ctx) => {
69
- clearActiveRunsStatus(ctx);
70
69
  clearActiveRunsWidget(ctx);
71
70
  clearCostFooter(ctx);
72
71
  await runtime.shutdown();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ferris1225/pi-subagents",
3
- "version": "4.3.12",
3
+ "version": "4.3.13",
4
4
  "description": "A managed sub-agent team for pi: scout, artisan, steward, and sentinel roles, one-shot runs, read-only status, and Git worktree isolation.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -8,7 +8,6 @@ import { announceRecoveryRecords, relocateRecoveryManifest } from "../isolation/
8
8
  import type { SubagentRuntime } from "../lifecycle/runtime.ts";
9
9
  import { seedCostLedgerFromSession } from "./cost-ledger.ts";
10
10
  import { installCostFooter } from "./cost-footer.ts";
11
- import { installActiveRunsStatus } from "./status.ts";
12
11
  import { installActiveRunsWidget } from "./widget.ts";
13
12
 
14
13
  /** Drop unavailable model overrides back to dynamic main-model routing. */
@@ -52,10 +51,9 @@ export function registerAnnouncements(pi: ExtensionAPI, runtime: SubagentRuntime
52
51
  "info",
53
52
  );
54
53
  }
55
- // The footer status works in every UI host (TUI and RPC); the widget and
56
- // the per-model cost footer are TUI-only. Seeding first means the first
57
- // footer render already carries the reloaded session's per-model spend.
58
- installActiveRunsStatus(ctx);
54
+ // The widget and the per-model cost footer are TUI-only. Seeding first
55
+ // means the first footer render already carries the reloaded session's
56
+ // per-model spend.
59
57
  if (ctx.mode !== "tui") return;
60
58
  seedCostLedgerFromSession(ctx);
61
59
  installActiveRunsWidget(ctx);
@@ -1,67 +0,0 @@
1
- /**
2
- * Persistent footer status line for sub-agent progress.
3
- *
4
- * The above-editor widget is the detailed surface, but it only pays off when
5
- * the user is looking at it: a parent turn that dispatches children and then
6
- * keeps streaming leaves no trace that anything is still running. The footer
7
- * is always visible, so one compact roll-up there answers "is anything still
8
- * working?" without opening the widget or querying runs.
9
- *
10
- * It stays deliberately count-only — no elapsed time, no per-run detail — so
11
- * it carries no time-varying field and needs no refresh timer: every monitor
12
- * transition already pushes an update. Queued runs keep their wait word
13
- * (`queued` for a process slot vs `repo lane` for write serialization) because
14
- * a capacity wait and a serialization wait call for different reactions.
15
- */
16
-
17
- import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
18
- import { isRunActiveStatus, monitor, statusLabel, type RunView } from "./monitor.ts";
19
- import { waitWord } from "./widget.ts";
20
-
21
- export const SUBAGENTS_STATUS_ID = "pi-subagents";
22
-
23
- const SEPARATOR = " · ";
24
-
25
- /** Display order of the count segments: live work first, settled last. */
26
- const SEGMENT_ORDER = ["running", "interrupting", "starting", "queued", "repo lane", "done", "stopped"];
27
-
28
- type StatusContext = Pick<ExtensionContext, "hasUI" | "ui">;
29
-
30
- /** One-line roll-up of live runs plus anything that settled during this turn.
31
- * Returns undefined when nothing is still active — a done-only leftover must
32
- * not keep the footer up after the last sibling finishes. */
33
- export function formatRunStatusLine(runs: readonly RunView[]): string | undefined {
34
- if (!runs.some((run) => isRunActiveStatus(run.status))) return undefined;
35
- const counts = new Map<string, number>();
36
- for (const run of runs) {
37
- const word = run.status === "queued"
38
- ? waitWord(run)
39
- : isRunActiveStatus(run.status) || run.status === "done" || run.status === "failed"
40
- ? statusLabel(run.status)
41
- : undefined;
42
- if (word) counts.set(word, (counts.get(word) ?? 0) + 1);
43
- }
44
- const segments = SEGMENT_ORDER.filter((word) => counts.has(word)).map((word) => `${counts.get(word)} ${word}`);
45
- return segments.length > 0 ? `subagents ${segments.join(SEPARATOR)}` : undefined;
46
- }
47
-
48
- /** Subscription of the currently installed status line; module-level because
49
- * the monitor it follows is itself a singleton. */
50
- let unsubscribe: (() => void) | undefined;
51
-
52
- /** Install the footer status line. Not installed without a UI host (print and
53
- * json modes), where setStatus has nowhere to render. */
54
- export function installActiveRunsStatus(ctx: StatusContext): void {
55
- if (!ctx.hasUI) return;
56
- // A second install must not orphan the first subscription.
57
- clearActiveRunsStatus(ctx);
58
- const render = (): void => ctx.ui.setStatus(SUBAGENTS_STATUS_ID, formatRunStatusLine(monitor.getRuns()));
59
- unsubscribe = monitor.subscribe(render);
60
- render();
61
- }
62
-
63
- export function clearActiveRunsStatus(ctx: StatusContext): void {
64
- unsubscribe?.();
65
- unsubscribe = undefined;
66
- if (ctx.hasUI) ctx.ui.setStatus(SUBAGENTS_STATUS_ID, undefined);
67
- }