pi-claude-code-ui 1.0.71 → 1.0.72

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,12 @@
3
3
  > [!IMPORTANT]
4
4
  > **1.0.69 — package rename (permanent).** Canonical npm name is now [`pi-claude-code-ui`](https://www.npmjs.com/package/pi-claude-code-ui). `pi-claude-style-tools` is legacy and will not receive further releases. Install with `pi install npm:pi-claude-code-ui` or `npm i pi-claude-code-ui`.
5
5
 
6
+ ## 1.0.72 — 2026-07-18
7
+
8
+ ### Changed
9
+
10
+ - **Agent tools breathe** — `Agent` / subagent tools use a size cycle while pending (`⬤ → ● → • → (invisible) → • → ●`) instead of the ordinary on/off `●` blink, so agent work reads as a different kind of tool.
11
+
6
12
  ## 1.0.71 — 2026-07-18
7
13
 
8
14
  ### Fixed
@@ -434,10 +434,16 @@ function isToolExecutionLike(value: unknown): value is { toolName: string; toolC
434
434
  return typeof candidate.toolName === "string" && typeof candidate.toolCallId === "string";
435
435
  }
436
436
 
437
+ const AGENT_FAMILY_TOOL_NAMES = new Set(["Agent", "Agents", "get_subagent_result", "steer_subagent"]);
438
+
439
+ function isAgentFamilyToolName(name: unknown): boolean {
440
+ return typeof name === "string" && AGENT_FAMILY_TOOL_NAMES.has(name);
441
+ }
442
+
437
443
  function shouldIndentToolExecution(value: unknown): boolean {
438
444
  if (!value || typeof value !== "object") return false;
439
445
  const toolName = (value as Record<string, unknown>).toolName;
440
- return typeof toolName === "string" && ["Agent", "Agents", "get_subagent_result", "steer_subagent"].includes(toolName);
446
+ return isAgentFamilyToolName(toolName);
441
447
  }
442
448
 
443
449
  function isTerminalImageLine(line: string): boolean {
@@ -541,9 +547,11 @@ function getToolGroupOverallStatus(tools: any[]): ToolStatus {
541
547
 
542
548
  // Claude Code: solid filled circle that is either fully present or fully gone
543
549
  // while pending — never a hollow outlined ○. Classic ● + bold is the sweet
544
- // spot (⬤ was too large in most mono fonts).
550
+ // spot for ordinary tools. Agent-family tools use a breathing size cycle.
545
551
  const STATUS_DOT_FILLED = "●";
546
552
  const STATUS_DOT_BOLD = "\x1b[1m";
553
+ // big → medium → small → invisible → small → medium (then back to big)
554
+ const AGENT_BREATHE_GLYPHS = ["⬤", "●", "•", " ", "•", "●"] as const;
547
555
 
548
556
  function paintStatusDot(colorAnsi: string): string {
549
557
  return `${colorAnsi}${STATUS_DOT_BOLD}${STATUS_DOT_FILLED}${TRANSPARENT_RESET}`;
@@ -554,6 +562,12 @@ function themeStatusDot(theme: Theme, colorKey: "success" | "error" | "dim" | "m
554
562
  return theme.fg(colorKey, `${STATUS_DOT_BOLD}${STATUS_DOT_FILLED}`);
555
563
  }
556
564
 
565
+ function agentBreatheDot(theme: Theme): string {
566
+ const glyph = AGENT_BREATHE_GLYPHS[_globalBlinkPhaseIndex % AGENT_BREATHE_GLYPHS.length];
567
+ if (glyph === " ") return " ";
568
+ return theme.fg("success", `${STATUS_DOT_BOLD}${glyph}`);
569
+ }
570
+
557
571
  function groupStatusLight(status: ToolStatus): string {
558
572
  const color = status === "success" ? TOOL_STATUS_SUCCESS : status === "error" ? TOOL_STATUS_ERROR : TOOL_STATUS_PENDING;
559
573
  if (status === "pending") {
@@ -2606,6 +2620,9 @@ type BlinkEntry = { key: any; order: number; invalidate: () => void };
2606
2620
  const _blinkContexts = new Map<any, BlinkEntry>();
2607
2621
  let _globalBlinkTimer: ReturnType<typeof setTimeout> | null = null;
2608
2622
  let _blinkOrder = 0;
2623
+ // Shared phase for all blinkers. Ordinary tools use even/odd (on/off ●).
2624
+ // Agent-family tools map the index onto a 6-step size breath cycle.
2625
+ let _globalBlinkPhaseIndex = 0;
2609
2626
  let _globalBlinkPhase = true;
2610
2627
 
2611
2628
  function getBlinkIntervalMs(): number {
@@ -2664,7 +2681,8 @@ function _scheduleGlobalBlinkTimer(): void {
2664
2681
  _clearAllBlinkContexts();
2665
2682
  return;
2666
2683
  }
2667
- _globalBlinkPhase = !_globalBlinkPhase;
2684
+ _globalBlinkPhaseIndex = (_globalBlinkPhaseIndex + 1) % AGENT_BREATHE_GLYPHS.length;
2685
+ _globalBlinkPhase = _globalBlinkPhaseIndex % 2 === 0;
2668
2686
  for (const entry of getBlinkingEntries()) {
2669
2687
  try { entry.invalidate(); } catch { /* noop */ }
2670
2688
  }
@@ -2726,9 +2744,13 @@ function blinkDot(ctx: any, theme: Theme): string {
2726
2744
  }
2727
2745
  setupBlinkTimer(ctx);
2728
2746
  const key = getBlinkKey(ctx);
2747
+ if (key?._blinkActive !== true) return " ";
2748
+ // Agent-family tools breathe through sizes; ordinary tools still on/off ●.
2749
+ if (ctx?.state?._agentBreathe === true) {
2750
+ return agentBreatheDot(theme);
2751
+ }
2729
2752
  // Claude Code: solid filled circle that either shows or fully disappears —
2730
2753
  // never a hollow outlined ○ in the off phase.
2731
- if (key?._blinkActive !== true) return " ";
2732
2754
  return _globalBlinkPhase ? themeStatusDot(theme, "success") : " ";
2733
2755
  }
2734
2756
 
@@ -4922,6 +4944,8 @@ function genericToolLabel(name: string): string {
4922
4944
  function renderGenericToolCall(name: string, args: any, theme: Theme, ctx: any): Text {
4923
4945
  syncToolCallStatus(ctx);
4924
4946
  ctx.state._openAiPatchFiles = [];
4947
+ // Agent / subagent tools get a size-breathing pending marker, not on/off ●.
4948
+ if (isAgentFamilyToolName(name)) ctx.state._agentBreathe = true;
4925
4949
  const sp = (path: string) => shortPath(ctx.cwd ?? process.cwd(), path);
4926
4950
  const summary = stableCallSummary(ctx, "_callSummary", () => summarizeGenericToolCall(name, args, theme, sp));
4927
4951
  return makeText(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-claude-code-ui",
3
- "version": "1.0.71",
3
+ "version": "1.0.72",
4
4
  "description": "Claude Code-style grouped tool rows for pi with Ctrl+O/Ctrl+Shift+O previews, math rendering, and consistent built-in, MCP, and custom tool rendering",
5
5
  "keywords": [
6
6
  "pi-package",