@wolido/async-subagent-isolation 1.0.0 → 1.0.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 +1 -1
- package/src/index.ts +25 -2
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
getAgentDir,
|
|
28
28
|
parseFrontmatter,
|
|
29
29
|
} from "@earendil-works/pi-coding-agent";
|
|
30
|
-
import { Box, Container, Key, Markdown, matchesKey, Spacer, Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
30
|
+
import { Box, Container, Key, Markdown, matchesKey, Spacer, Text, truncateToWidth, visibleWidth, sliceByColumn } from "@earendil-works/pi-tui";
|
|
31
31
|
import { Type } from "typebox";
|
|
32
32
|
|
|
33
33
|
// ===== UUID v7 helper =====
|
|
@@ -545,6 +545,10 @@ interface AgentProgress {
|
|
|
545
545
|
const PROGRESS_WIDGET_KEY = "async-subagent-isolation-progress";
|
|
546
546
|
const MAX_WIDGET_LINES = 20;
|
|
547
547
|
const MAX_RECENT_TOOLS = 3;
|
|
548
|
+
// Cap for the dynamic name column: wide enough for typical agent names
|
|
549
|
+
// (existing tests require a 20-char name to render in full), small enough
|
|
550
|
+
// to leave room for the phase/elapsed columns on narrow terminals.
|
|
551
|
+
const MAX_NAME_WIDTH = 30;
|
|
548
552
|
|
|
549
553
|
/** Plain-text one-line summary of a tool call for the progress widget (no theme colors). */
|
|
550
554
|
function summarizeToolCall(toolName: string, args: Record<string, any>): string {
|
|
@@ -561,6 +565,22 @@ function getRecentToolSummaries(messages: Message[]): string[] {
|
|
|
561
565
|
.map((item) => summarizeToolCall(item.name, item.args));
|
|
562
566
|
}
|
|
563
567
|
|
|
568
|
+
/**
|
|
569
|
+
* Fit an agent name into a fixed-width column: pad short names with spaces,
|
|
570
|
+
* truncate over-long names with a "..." suffix. Unlike truncateToWidth this
|
|
571
|
+
* never injects ANSI reset codes around the ellipsis (agent names carry no
|
|
572
|
+
* styling), so every row keeps the phase/elapsed columns at the same raw
|
|
573
|
+
* string offset as well as the same display column. Callers must pass
|
|
574
|
+
* width >= 4 so the ellipsis fits.
|
|
575
|
+
*/
|
|
576
|
+
function fitNameColumn(name: string, width: number): string {
|
|
577
|
+
const nameWidth = visibleWidth(name);
|
|
578
|
+
if (nameWidth <= width) return name + " ".repeat(width - nameWidth);
|
|
579
|
+
// strict: never keep a wide char that would straddle the cut boundary
|
|
580
|
+
const cut = sliceByColumn(name, 0, width - 3, true);
|
|
581
|
+
return cut + "..." + " ".repeat(Math.max(0, width - 3 - visibleWidth(cut)));
|
|
582
|
+
}
|
|
583
|
+
|
|
564
584
|
export function formatElapsed(startedAt: number): string {
|
|
565
585
|
const totalSec = Math.max(0, Math.floor((Date.now() - startedAt) / 1000));
|
|
566
586
|
const mm = String(Math.floor(totalSec / 60)).padStart(2, "0");
|
|
@@ -622,6 +642,9 @@ export class SubagentProgressManager {
|
|
|
622
642
|
const maxAgentRows = Math.max(1, Math.min(process.stdout.rows || MAX_WIDGET_LINES, MAX_WIDGET_LINES));
|
|
623
643
|
const visible = sorted.slice(-maxAgentRows);
|
|
624
644
|
const total = sorted.length;
|
|
645
|
+
// Name column width adapts to the longest visible agent name (capped),
|
|
646
|
+
// so the phase and elapsed columns start at the same offset on every row.
|
|
647
|
+
const nameColWidth = Math.min(MAX_NAME_WIDTH, Math.max(...visible.map((a) => visibleWidth(a.name))));
|
|
625
648
|
// Note: the factory closes over `theme`; between a theme change and the next
|
|
626
649
|
// refresh (≤1s) the widget may briefly use the stale theme. The 1Hz timer
|
|
627
650
|
// replaces the factory on every tick, so this self-heals.
|
|
@@ -640,7 +663,7 @@ export class SubagentProgressManager {
|
|
|
640
663
|
return borderColor("─") + theme.fg("accent", label) + borderColor("─".repeat(width - labelWidth - 1));
|
|
641
664
|
};
|
|
642
665
|
const renderRow = (a: AgentProgress, width: number): string => {
|
|
643
|
-
const nameCol = a.name;
|
|
666
|
+
const nameCol = fitNameColumn(a.name, nameColWidth);
|
|
644
667
|
const phaseCol = truncateToWidth(formatPhase(a.phase), 20, "...", true);
|
|
645
668
|
const toolHint = a.recentTools.length > 0 ? ` → ${a.recentTools[a.recentTools.length - 1]}` : "";
|
|
646
669
|
const line =
|