@ferris1225/pi-subagents 0.31.0 → 0.32.2

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/src/widget.ts CHANGED
@@ -14,10 +14,12 @@ import {
14
14
  deriveActivityState,
15
15
  formatElapsed,
16
16
  formatUsageCompact,
17
+ isRunActiveStatus,
17
18
  monitor,
18
19
  statusIcon,
19
20
  statusLabel,
20
21
  } from "./monitor.ts";
22
+ import { announceRecoveryRecords } from "./recovery.ts";
21
23
  import type { SubagentRuntime } from "./runtime.ts";
22
24
 
23
25
  /** Features whose one-time announcement is still pending (keyed by config
@@ -80,6 +82,9 @@ async function announceNewFeatures(
80
82
 
81
83
  export function registerWidget(pi: ExtensionAPI, runtime: SubagentRuntime): void {
82
84
  pi.on("session_start", async (_e, ctx) => {
85
+ // Recovery paths survive the old runtime and are shown again in the next
86
+ // UI-capable session before any transient widget state is rebuilt.
87
+ await announceRecoveryRecords(runtime.configPath, ctx);
83
88
  if (ctx.mode !== "tui") return;
84
89
  await announceNewFeatures(ctx, runtime);
85
90
 
@@ -89,7 +94,7 @@ export function registerWidget(pi: ExtensionAPI, runtime: SubagentRuntime): void
89
94
  const unsub = monitor.subscribe(() => tui.requestRender());
90
95
  // Tick once a second so elapsed time stays live while runs are active.
91
96
  const timer = setInterval(() => {
92
- if (monitor.getRuns().some((r) => r.status === "queued" || r.status === "running")) {
97
+ if (monitor.getRuns().some((r) => isRunActiveStatus(r.status))) {
93
98
  tui.requestRender();
94
99
  }
95
100
  }, 1000);
@@ -110,7 +115,7 @@ export function registerWidget(pi: ExtensionAPI, runtime: SubagentRuntime): void
110
115
  const isChain = Boolean(r.groupId);
111
116
  const chainContinues = isChain && runs[idx + 1]?.groupId === r.groupId;
112
117
  const activity =
113
- r.activity && (r.status === "running" || r.status === "queued") ? r.activity : undefined;
118
+ r.activity && isRunActiveStatus(r.status) ? r.activity : undefined;
114
119
  const hasActivity = activity !== undefined;
115
120
  const icon = statusIcon(r.status, theme);
116
121
  // Chain-internal runs (auto-fix worker/reviewer) are child nodes under
@@ -137,14 +142,22 @@ export function registerWidget(pi: ExtensionAPI, runtime: SubagentRuntime): void
137
142
  // annotation (idle / long-running). Trailing the header with a single
138
143
  // " · " chain keeps the row compact (no center gap); compactLine
139
144
  // clips on overflow, never the right side on its own.
140
- const model = r.model ?? "?";
145
+ const model = r.modelFallbackFrom
146
+ ? `${r.model ?? "?"} (pool fallback from ${r.modelFallbackFrom})`
147
+ : (r.model ?? "?");
141
148
  const usage = formatUsageCompact(r.usage);
142
149
  const tools = r.toolCount ? `${r.toolCount} tool${r.toolCount === 1 ? "" : "s"}` : "";
143
150
  const elapsed = formatElapsed(r, now);
144
151
  // The round outcome summary leads the metadata so a finished chain
145
152
  // row reads as what it did ("fail · src/index.ts · render()",
146
153
  // "pass", "src/index.ts · tests/monitor.test.ts").
147
- const metaParts = [r.summary, model, usage, tools, elapsed].filter(Boolean);
154
+ const isolation = r.isolation === "worktree" ? `worktree ${r.integrationStatus ?? "active"}` : undefined;
155
+ const relation = r.forkedFromRunId !== undefined
156
+ ? `fork of #${r.forkedFromRunId}`
157
+ : (r.forkChildRunIds?.length ?? 0) > 0
158
+ ? `forks ${r.forkChildRunIds!.map((id) => `#${id}`).join(",")}`
159
+ : undefined;
160
+ const metaParts = [r.summary, relation, isolation, model, usage, tools, elapsed].filter(Boolean);
148
161
  // Running is conveyed by the icon + elapsed; spell out the label only for
149
162
  // the other states (ready / done / stopped) so they are unambiguous.
150
163
  if (r.status !== "running") metaParts.push(statusLabel(r.status));