pi-better-subagents 0.1.19 → 0.1.20

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-better-subagents",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Pi extension for detached, sandboxed subagent runs that keep the foreground session free.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -83,6 +83,7 @@ type NavigatorState = {
83
83
  deps?: HostDeps;
84
84
  lastHint?: string | null;
85
85
  lastMainListLines?: string[];
86
+ lastMainListSignature?: string;
86
87
  mainListWidgetInstalled?: boolean;
87
88
  mainListRequestRender?: () => void;
88
89
  mainListSelectedId?: string;
@@ -110,7 +111,6 @@ const MAIN_LIST_FALLBACK_WIDTH = 100;
110
111
  const DETAIL_OVERLAY_FOOTER_ROWS = 3;
111
112
  const EVIDENCE_SECTION_ID = "__evidence__";
112
113
  const RUNNING_DOT_GLYPH = "●";
113
- const RUNNING_DOT_FRAMES = ["dim", "accent", "accent", "dim"] as const;
114
114
 
115
115
  function state(): NavigatorState {
116
116
  const g = globalThis as typeof globalThis & { [GLOBAL_KEY]?: NavigatorState };
@@ -199,6 +199,7 @@ export function disposeBackgroundWorkNavigator(ctx?: ExtensionContext): void {
199
199
  }
200
200
  s.lastHint = undefined;
201
201
  s.lastMainListLines = undefined;
202
+ s.lastMainListSignature = undefined;
202
203
  s.mainListDeadlineScheduler?.dispose();
203
204
  s.mainListDeadlineScheduler = undefined;
204
205
  s.mainListWidgetInstalled = false;
@@ -263,6 +264,12 @@ function refreshMainListWidget(): void {
263
264
  s.mainListDeadlineScheduler?.schedule(nextExpiry - now);
264
265
  }
265
266
  syncMainListSelection(rows);
267
+ const nextSignature = rows.length ? mainListSignature(rows, {
268
+ selectedId: s.mainListFocused ? s.mainListSelectedId : undefined,
269
+ focused: s.mainListFocused === true,
270
+ }) : undefined;
271
+ const changed = nextSignature !== s.lastMainListSignature;
272
+ s.lastMainListSignature = nextSignature;
266
273
  s.lastMainListLines = rows.length ? buildMainListLines(rows, MAIN_LIST_FALLBACK_WIDTH, deps.truncate, themeFg(ctx), {
267
274
  selectedId: s.mainListFocused ? s.mainListSelectedId : undefined,
268
275
  focused: s.mainListFocused === true,
@@ -272,6 +279,7 @@ function refreshMainListWidget(): void {
272
279
  try { (ctx.ui as any).setWidget?.(MAIN_LIST_WIDGET_KEY, undefined); } catch { /* ignore */ }
273
280
  s.mainListWidgetInstalled = false;
274
281
  s.mainListRequestRender = undefined;
282
+ s.lastMainListSignature = undefined;
275
283
  return;
276
284
  }
277
285
  if (!s.mainListWidgetInstalled) {
@@ -280,7 +288,9 @@ function refreshMainListWidget(): void {
280
288
  s.mainListWidgetInstalled = true;
281
289
  } catch { /* ignore */ }
282
290
  }
283
- try { s.mainListRequestRender?.(); } catch { /* ignore */ }
291
+ if (changed) {
292
+ try { s.mainListRequestRender?.(); } catch { /* ignore */ }
293
+ }
284
294
  }
285
295
 
286
296
  function themeFg(ctx: ExtensionContext): (color: string, value: string) => string {
@@ -481,9 +491,40 @@ function statusGlyph(row: InternalRow): string {
481
491
  }
482
492
 
483
493
  function statusIndicator(row: InternalRow, now = Date.now()): { glyph: string; color: string } {
494
+ void now;
484
495
  if (row.statusTone !== "running") return { glyph: statusGlyph(row), color: toneColor(row.statusTone, row.status) };
485
- const frame = Math.floor(now / DETAIL_TICK_MS) % RUNNING_DOT_FRAMES.length;
486
- return { glyph: RUNNING_DOT_GLYPH, color: RUNNING_DOT_FRAMES[frame]! };
496
+ return { glyph: RUNNING_DOT_GLYPH, color: "accent" };
497
+ }
498
+
499
+ function mainListSignature(rows: InternalRow[], options: { selectedId?: string; focused?: boolean } = {}): string {
500
+ return JSON.stringify({
501
+ focused: options.focused === true,
502
+ selectedId: options.focused === true ? options.selectedId ?? null : null,
503
+ rows: rows.map((row) => ({
504
+ navigatorId: row.navigatorId,
505
+ providerLabel: row.providerLabel,
506
+ parentRow: row.parentRow === true,
507
+ providerId: row.providerId,
508
+ id: row.id,
509
+ name: row.name ?? null,
510
+ model: row.model ?? null,
511
+ effort: row.effort ?? null,
512
+ tool: row.tool ?? null,
513
+ tokens: row.tokens ?? null,
514
+ command: row.command ?? null,
515
+ status: row.status,
516
+ statusTone: row.statusTone,
517
+ kind: row.kind,
518
+ primary: row.primary,
519
+ secondary: row.secondary ?? null,
520
+ facts: stableFacts(row.facts),
521
+ sortStartedAt: row.sortStartedAt,
522
+ })),
523
+ });
524
+ }
525
+
526
+ function stableFacts(facts: string[] | undefined): string[] {
527
+ return (facts ?? []).filter((fact) => !/\bleft$/.test(singleLine(fact)));
487
528
  }
488
529
 
489
530
  function rowSummary(row: InternalRow): string {