@pi-kaush/pi-tool-call-markers 0.3.3 → 0.3.5
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/README.md +18 -13
- package/package.json +1 -1
- package/src/index.ts +102 -99
- package/src/muted.ts +4 -8
package/README.md
CHANGED
|
@@ -15,20 +15,16 @@ Restart Pi or run `/reload`.
|
|
|
15
15
|
Collapsed tool rows use semantic theme colors with no gear, background fill, box padding, or filled blank rows:
|
|
16
16
|
|
|
17
17
|
```text
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
% Bash
|
|
23
|
-
│ $: npm test → done
|
|
18
|
+
│ ●: src/a.ts 42 lines
|
|
19
|
+
│ ●: src/b.ts 18 lines
|
|
20
|
+
│ $: npm test → done
|
|
24
21
|
```
|
|
25
22
|
|
|
26
23
|
- **Two-column outer inset.** Tool markers and image output align with an inset conversation surface. Very narrow terminals reduce the decoration before useful content.
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
- **Semantic, low-contrast status.** Tool names are emphasized, summaries and settled metadata are muted, pending state is warning-colored, and failures remain error-colored. Ordinary tool states have no background.
|
|
24
|
+
- **`│` tool-call rail.** Every collapsed call anchors on a glyph instead of its tool name: `●` read, `+` write, `±` edit, `○` local search, `≡` ls, `↗` web search and fetch, and `$` bash; unmapped tools fall back to `*`. Grouped rows flow directly across tool types.
|
|
25
|
+
- **Semantic, low-contrast status.** The anchor and the call content share the collapsed mute, pending state is warning-colored, and failures remain error-colored. Ordinary tool states have no background.
|
|
30
26
|
- **Width-safe outcome tails.** Long summaries truncate before useful tails such as `→ done`, `→ 42 lines`, `→ +2/-1`, or a `bash` duration.
|
|
31
|
-
- **Stable running groups.** Adjacent calls group as they appear. Pending state and elapsed `bash` time settle into the final outcome without changing the row count.
|
|
27
|
+
- **Stable running groups.** Adjacent calls group as they appear, including settled failures, which stay error-colored inside the group. Pending state and elapsed `bash` time settle into the final outcome without changing the row count.
|
|
32
28
|
- **Quiet-turn grouping.** Sequential calls can join across an assistant row with no visible prose or thinking. Visible assistant content remains a boundary.
|
|
33
29
|
- **MCP and self-rendered tools.** Their stable call labels, compact arguments, pending state, success, and first error line use the same collapsed shell. Native self-rendered details return when expanded.
|
|
34
30
|
- **Images remain visible.** Image fallback text and terminal image components render below the corresponding marker with the same inset.
|
|
@@ -37,7 +33,7 @@ Collapsed tool rows use semantic theme colors with no gear, background fill, box
|
|
|
37
33
|
|
|
38
34
|
## Subagent plans
|
|
39
35
|
|
|
40
|
-
A recognized `subagent` call renders as an unboxed plan in the shared tool aesthetic, marked with `↪` instead of the ordinary
|
|
36
|
+
A recognized `subagent` call renders as an unboxed plan in the shared tool aesthetic, marked with `↪` instead of the ordinary `│` tool-call rail:
|
|
41
37
|
|
|
42
38
|
```text
|
|
43
39
|
↪ subagent chain (3 steps) [repo-review]
|
|
@@ -53,7 +49,7 @@ Malformed, ambiguous, future, or too-narrow shapes fall back to the generic `↪
|
|
|
53
49
|
|
|
54
50
|
## Edit diffs
|
|
55
51
|
|
|
56
|
-
Settled `edit` calls
|
|
52
|
+
Settled `edit` calls collapse like every other row: the call line keeps its path and a `+added/-removed` outcome stat, and the hunk itself stays out of the collapsed row. `Ctrl+O` restores Pi's full native diff, including line numbers and intra-line word highlights. To keep edits expanded without pressing `Ctrl+O`, list `edit` in `PI_ALWAYS_EXPANDED_TOOL_CALL_MARKERS` (see Configuration).
|
|
57
53
|
|
|
58
54
|
Files and paths in collapsed rows are preserved as displayed by Pi: hyperlink-wrapped paths (Pi wraps `read` call paths in OSC 8 hyperlinks) keep their visible text when sanitized for one-line rows.
|
|
59
55
|
|
|
@@ -103,9 +99,18 @@ pi
|
|
|
103
99
|
|
|
104
100
|
`0`, `false`, `no`, and `off` disable parallel grouping. `1`, `true`, `yes`, and `on` enable it. The value is read when the extension loads.
|
|
105
101
|
|
|
102
|
+
To render chosen tools as Pi's native expanded block by default — full result and diff without `Ctrl+O` — list their names:
|
|
103
|
+
|
|
104
|
+
```fish
|
|
105
|
+
set -lx PI_ALWAYS_EXPANDED_TOOL_CALL_MARKERS edit,write
|
|
106
|
+
pi
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Names are comma-separated and matched exactly. Listed rows never join a group, and the list stays authoritative: collapsing the transcript with `Ctrl+O` re-expands them. The value is read when the extension loads.
|
|
110
|
+
|
|
106
111
|
### Collapsed-row colors
|
|
107
112
|
|
|
108
|
-
Collapsed rows (tool calls, `+ Thought`, subagents) default to the theme's `syntaxComment` color — it ships with every Pi theme and reads as a muted tone — with the
|
|
113
|
+
Collapsed rows (tool calls, `+ Thought`, subagents) default to the theme's `syntaxComment` color — it ships with every Pi theme and reads as a muted tone — with the row's anchor and the call content sharing it. Failures stay error-colored and live spinners keep their existing tints.
|
|
109
114
|
|
|
110
115
|
A theme can override each collapsed kind independently with optional color tokens:
|
|
111
116
|
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -19,14 +19,30 @@ import { installInfoVisibility } from "./info-visibility.ts";
|
|
|
19
19
|
import { fgCollapsed, fgCollapsedRail } from "./muted.ts";
|
|
20
20
|
|
|
21
21
|
const OUTER_INSET = 2;
|
|
22
|
-
const GROUP_MARKER = "%";
|
|
23
22
|
const SUBAGENT_MARKER = "↪";
|
|
24
23
|
const GROUP_CALL_MARKER = "│";
|
|
24
|
+
// Collapsed rows anchor with a glyph instead of repeating the tool name;
|
|
25
|
+
// tools that read as one family share a glyph, and unmapped tools fall back
|
|
26
|
+
// to `*`.
|
|
27
|
+
const TOOL_CALL_GLYPHS: ReadonlyMap<string, string> = new Map([
|
|
28
|
+
["read", "●"],
|
|
29
|
+
["write", "+"],
|
|
30
|
+
["edit", "±"],
|
|
31
|
+
["grep", "○"],
|
|
32
|
+
["ffgrep", "○"],
|
|
33
|
+
["find", "○"],
|
|
34
|
+
["fffind", "○"],
|
|
35
|
+
["ls", "≡"],
|
|
36
|
+
["web_search", "↗"],
|
|
37
|
+
["fetch_content", "↗"],
|
|
38
|
+
["get_search_content", "↗"],
|
|
39
|
+
]);
|
|
25
40
|
const PRESENTATION_PATCHED = Symbol.for("kg.pi.toolPresentation.v3");
|
|
26
41
|
const LEGACY_PRESENTATION_PATCHED = Symbol.for("kg.pi.toolPresentation.v2");
|
|
27
42
|
const GROUPING_PATCHED = Symbol.for("kg.pi.toolGrouping.v1");
|
|
28
43
|
const ANSI_RE = /\u001b\[[0-9;]*m/g;
|
|
29
44
|
const COLLAPSE_PARALLEL_ENV = "PI_TOOL_CALL_MARKERS_COLLAPSE_PARALLEL";
|
|
45
|
+
const EXPANDED_TOOLS_ENV = "PI_ALWAYS_EXPANDED_TOOL_CALL_MARKERS";
|
|
30
46
|
|
|
31
47
|
type ThemeLike = {
|
|
32
48
|
bold(text: string): string;
|
|
@@ -73,6 +89,7 @@ type PresentationPatchState = {
|
|
|
73
89
|
owners: number;
|
|
74
90
|
theme?: ThemeLike;
|
|
75
91
|
collapseParallel: boolean;
|
|
92
|
+
expandedTools: ReadonlySet<string>;
|
|
76
93
|
groupCache: WeakMap<ToolExecutionRow, GroupRenderCache>;
|
|
77
94
|
collapsedCache: WeakMap<ToolExecutionRow, CollapsedRenderCache>;
|
|
78
95
|
rowVersions: WeakMap<ToolExecutionRow, number>;
|
|
@@ -95,9 +112,7 @@ type GroupingPatchState = {
|
|
|
95
112
|
|
|
96
113
|
type GroupRenderCache = {
|
|
97
114
|
lines: string[];
|
|
98
|
-
//
|
|
99
|
-
// member absorbs the leading blank and the tool-name header, later
|
|
100
|
-
// members carry their own line (plus edit diffs).
|
|
115
|
+
// The first member absorbs the leading blank; each member owns its line.
|
|
101
116
|
heights: Array<{ component: ToolExecutionRow; height: number }>;
|
|
102
117
|
members: ToolExecutionRow[];
|
|
103
118
|
memberVersions: number[];
|
|
@@ -121,6 +136,19 @@ function envEnabled(name: string, defaultValue: boolean): boolean {
|
|
|
121
136
|
return defaultValue;
|
|
122
137
|
}
|
|
123
138
|
|
|
139
|
+
// Comma-separated tool names, e.g. `edit,write`. Blank entries and padding
|
|
140
|
+
// are ignored; an unset or empty variable yields no names.
|
|
141
|
+
function envToolNames(name: string): ReadonlySet<string> {
|
|
142
|
+
const value = process.env[name]?.trim();
|
|
143
|
+
if (!value) return new Set();
|
|
144
|
+
return new Set(
|
|
145
|
+
value
|
|
146
|
+
.split(",")
|
|
147
|
+
.map((entry) => entry.trim())
|
|
148
|
+
.filter(Boolean),
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
124
152
|
function stripAnsi(text: string): string {
|
|
125
153
|
return text.replace(ANSI_RE, "");
|
|
126
154
|
}
|
|
@@ -498,6 +526,18 @@ function isCollapsibleSuccess(row: ToolExecutionRow): boolean {
|
|
|
498
526
|
);
|
|
499
527
|
}
|
|
500
528
|
|
|
529
|
+
// Settled failures join groups like settled successes; the row's error
|
|
530
|
+
// color carries the failure, so the group stays visually unbroken.
|
|
531
|
+
function isCollapsibleFailure(row: ToolExecutionRow): boolean {
|
|
532
|
+
return (
|
|
533
|
+
row.expanded === false &&
|
|
534
|
+
row.isPartial === false &&
|
|
535
|
+
!!row.result &&
|
|
536
|
+
rowHasFailed(row) &&
|
|
537
|
+
!hasImageResult(row)
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
501
541
|
function hasToolSiblingInAssistantBatch(
|
|
502
542
|
children: unknown[],
|
|
503
543
|
index: number,
|
|
@@ -526,7 +566,12 @@ function isGroupableToolRow(
|
|
|
526
566
|
state: PresentationPatchState,
|
|
527
567
|
): boolean {
|
|
528
568
|
if (row.toolName === "subagent") return false;
|
|
529
|
-
if (
|
|
569
|
+
if (
|
|
570
|
+
!isLiveRow(row) &&
|
|
571
|
+
!isCollapsibleSuccess(row) &&
|
|
572
|
+
!isCollapsibleFailure(row)
|
|
573
|
+
)
|
|
574
|
+
return false;
|
|
530
575
|
return (
|
|
531
576
|
state.collapseParallel ||
|
|
532
577
|
!hasToolSiblingInAssistantBatch(children, index, renderAt)
|
|
@@ -613,15 +658,8 @@ function diffCounts(diff: string): { added: number; removed: number } {
|
|
|
613
658
|
}
|
|
614
659
|
|
|
615
660
|
// Pi's edit tool (renderShell "self") stores its display diff in
|
|
616
|
-
// result.details.diff
|
|
617
|
-
//
|
|
618
|
-
// normally keep only their one-line call label; edits additionally show
|
|
619
|
-
// the change as a bounded diff block under the summary and a +a/-b stat in
|
|
620
|
-
// the outcome tail, so the hunk stays visible without Ctrl+O while
|
|
621
|
-
// expanded rows keep Pi's native rendering.
|
|
622
|
-
const EDIT_DIFF_LINE_RE = /^([+\-\s])(\s*\d*)(.*)$/;
|
|
623
|
-
const MAX_EDIT_DIFF_LINES = 12;
|
|
624
|
-
|
|
661
|
+
// result.details.diff; collapsed rows show only its +a/-b stat, while the
|
|
662
|
+
// full hunk returns with Ctrl+O.
|
|
625
663
|
function editDiffText(row: ToolExecutionRow): string | undefined {
|
|
626
664
|
if (row.toolName !== "edit") return undefined;
|
|
627
665
|
if (!row.result || row.isPartial !== false || rowHasFailed(row))
|
|
@@ -637,43 +675,6 @@ function renderedEditDiffStat(row: ToolExecutionRow): string | undefined {
|
|
|
637
675
|
return added + removed === 0 ? "applied" : `+${added}/-${removed}`;
|
|
638
676
|
}
|
|
639
677
|
|
|
640
|
-
function renderedEditDiffLines(
|
|
641
|
-
row: ToolExecutionRow,
|
|
642
|
-
theme: ThemeLike,
|
|
643
|
-
): string[] {
|
|
644
|
-
const diff = editDiffText(row);
|
|
645
|
-
if (diff === undefined) return [];
|
|
646
|
-
const raw = diff.split("\n");
|
|
647
|
-
if (raw[raw.length - 1] === "") raw.pop();
|
|
648
|
-
const lines: string[] = [];
|
|
649
|
-
for (const line of raw.slice(0, MAX_EDIT_DIFF_LINES)) {
|
|
650
|
-
const clean = sanitizeInline(line).trimEnd();
|
|
651
|
-
if (clean.trim() === "...") {
|
|
652
|
-
lines.push(fgCollapsed(theme, "muted", " ..."));
|
|
653
|
-
continue;
|
|
654
|
-
}
|
|
655
|
-
const match = EDIT_DIFF_LINE_RE.exec(clean);
|
|
656
|
-
if (!match) continue;
|
|
657
|
-
const color =
|
|
658
|
-
match[1] === "+"
|
|
659
|
-
? "toolDiffAdded"
|
|
660
|
-
: match[1] === "-"
|
|
661
|
-
? "toolDiffRemoved"
|
|
662
|
-
: "toolDiffContext";
|
|
663
|
-
lines.push(theme.fg(color, ` ${match[1]}${match[2]}${match[3]}`));
|
|
664
|
-
}
|
|
665
|
-
if (raw.length > MAX_EDIT_DIFF_LINES) {
|
|
666
|
-
lines.push(
|
|
667
|
-
fgCollapsed(
|
|
668
|
-
theme,
|
|
669
|
-
"muted",
|
|
670
|
-
` ... +${raw.length - MAX_EDIT_DIFF_LINES} more`,
|
|
671
|
-
),
|
|
672
|
-
);
|
|
673
|
-
}
|
|
674
|
-
return lines;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
678
|
function outcomeSummary(row: ToolExecutionRow): string | undefined {
|
|
678
679
|
// Self-rendered tools own their result framing; the built-in heuristics
|
|
679
680
|
// (line counts, diff stats) describe default-shell rows only, so their
|
|
@@ -725,22 +726,6 @@ function renderedOutcome(
|
|
|
725
726
|
return fgCollapsed(theme, "toolOutput", `→ ${summary}`);
|
|
726
727
|
}
|
|
727
728
|
|
|
728
|
-
function renderedGroupedOutcome(
|
|
729
|
-
row: ToolExecutionRow,
|
|
730
|
-
theme: ThemeLike,
|
|
731
|
-
): string | undefined {
|
|
732
|
-
const outcome = renderedOutcome(row, theme);
|
|
733
|
-
if (outcome) return outcome;
|
|
734
|
-
if (isLiveRow(row)) {
|
|
735
|
-
const elapsed = liveElapsedText(row);
|
|
736
|
-
return theme.fg("warning", elapsed ? `… · ${elapsed}` : "…");
|
|
737
|
-
}
|
|
738
|
-
// Self-rendered tools have no per-tool outcome summary; keep the group's
|
|
739
|
-
// settled tail consistent with collapsed singletons.
|
|
740
|
-
if (row.getRenderShell?.() === "self") return renderedGenericOutcome(theme);
|
|
741
|
-
return undefined;
|
|
742
|
-
}
|
|
743
|
-
|
|
744
729
|
// A budget too small for the suffix keeps literal styled text instead, so a
|
|
745
730
|
// one-column label never collapses into a bare ellipsis or loses its status.
|
|
746
731
|
function truncateStyled(text: string, width: number, suffix = "…"): string {
|
|
@@ -901,6 +886,23 @@ function collapsedCallLabel(
|
|
|
901
886
|
return styledCallLabel(label, theme, color);
|
|
902
887
|
}
|
|
903
888
|
|
|
889
|
+
// Collapsed rows anchor their call text with a glyph instead of repeating
|
|
890
|
+
// the tool name, grouped or not. Bash carries `$:` inside its own label and
|
|
891
|
+
// the subagent fallback keeps its `↪ subagent` heading, so neither takes a
|
|
892
|
+
// glyph.
|
|
893
|
+
function collapsedCallMarker(
|
|
894
|
+
row: ToolExecutionRow,
|
|
895
|
+
theme: ThemeLike,
|
|
896
|
+
color: string,
|
|
897
|
+
): string {
|
|
898
|
+
if (row.toolName === "bash" || row.toolName === "subagent") return "";
|
|
899
|
+
return fgCollapsed(
|
|
900
|
+
theme,
|
|
901
|
+
color,
|
|
902
|
+
`${TOOL_CALL_GLYPHS.get(row.toolName ?? "") ?? "*"}: `,
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
|
|
904
906
|
function collapsedOutcome(
|
|
905
907
|
row: ToolExecutionRow,
|
|
906
908
|
width: number,
|
|
@@ -931,15 +933,15 @@ function collapsedHeadline(
|
|
|
931
933
|
theme: ThemeLike,
|
|
932
934
|
): string {
|
|
933
935
|
// Failed rows render entirely in error so the row reads as the one that
|
|
934
|
-
// failed, not just its outcome tail. Only the
|
|
936
|
+
// failed, not just its outcome tail. Only the row's anchor stays bold.
|
|
935
937
|
const tone = rowHasFailed(row) ? "error" : "muted";
|
|
936
|
-
const marker =
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
)
|
|
938
|
+
const marker =
|
|
939
|
+
row.toolName === "subagent"
|
|
940
|
+
? `${fgCollapsed(theme, tone, SUBAGENT_MARKER)} `
|
|
941
|
+
: `${fgCollapsedRail(theme, GROUP_CALL_MARKER)} `;
|
|
942
|
+
const glyph = collapsedCallMarker(row, theme, tone);
|
|
941
943
|
const budget = Math.max(1, width - visibleWidth(marker));
|
|
942
|
-
const label =
|
|
944
|
+
const label = glyph + collapsedChildLabel(row, budget, theme, tone);
|
|
943
945
|
const outcome = collapsedOutcome(row, budget, theme);
|
|
944
946
|
// The truncation suffix inherits the row tone; pi-tui's truncation resets
|
|
945
947
|
// around a plain suffix, which would render it in the terminal default
|
|
@@ -1250,20 +1252,20 @@ function renderCollapsedToolRow(
|
|
|
1250
1252
|
? renderSubagentPlan(row, layout.contentWidth, theme)
|
|
1251
1253
|
: undefined;
|
|
1252
1254
|
const body = plan ?? [collapsedHeadline(row, layout.contentWidth, theme)];
|
|
1253
|
-
if (row.toolName === "edit") {
|
|
1254
|
-
body.push(...renderedEditDiffLines(row, theme));
|
|
1255
|
-
}
|
|
1256
1255
|
body.push(...imageResultLines(row, layout.contentWidth, theme));
|
|
1257
1256
|
return ["", ...insetLines(body, width)];
|
|
1258
1257
|
}
|
|
1259
1258
|
|
|
1260
|
-
|
|
1259
|
+
// Drops the call label's tool-name token: the row's glyph anchors the call
|
|
1260
|
+
// instead. The `↪` subagent fallback keeps its own heading.
|
|
1261
|
+
function collapsedChildLabel(
|
|
1261
1262
|
row: ToolExecutionRow,
|
|
1262
1263
|
width: number,
|
|
1263
1264
|
theme: ThemeLike,
|
|
1264
1265
|
color: string = "muted",
|
|
1265
1266
|
): string {
|
|
1266
1267
|
const label = collapsedCallLabel(row, width, theme, color);
|
|
1268
|
+
if (row.toolName === "subagent") return label;
|
|
1267
1269
|
const plain = stripAnsi(label);
|
|
1268
1270
|
const toolName = row.toolName ?? "tool";
|
|
1269
1271
|
let prefix = "";
|
|
@@ -1289,36 +1291,26 @@ function renderGroupedCallLines(
|
|
|
1289
1291
|
theme: ThemeLike,
|
|
1290
1292
|
): Array<{ row: ToolExecutionRow; lines: string[] }> {
|
|
1291
1293
|
const segments: Array<{ row: ToolExecutionRow; lines: string[] }> = [];
|
|
1292
|
-
let previousToolName: string | undefined;
|
|
1293
1294
|
for (const row of rows) {
|
|
1294
1295
|
const lines: string[] = [];
|
|
1295
|
-
const toolName = row.toolName ?? "tool";
|
|
1296
|
-
if (toolName !== previousToolName) {
|
|
1297
|
-
// One blank line between tool-name subgroups, mirroring the block's
|
|
1298
|
-
// leading blank so each `%` heading starts its own visual run. The
|
|
1299
|
-
// blank belongs to the new run's first row, keeping the per-member
|
|
1300
|
-
// click-routing heights aligned with the drawn lines.
|
|
1301
|
-
if (previousToolName !== undefined) lines.push("");
|
|
1302
|
-
lines.push(
|
|
1303
|
-
`${fgCollapsed(theme, "muted", GROUP_MARKER)} ${fgCollapsed(theme, "toolTitle", toolName, true)}`,
|
|
1304
|
-
);
|
|
1305
|
-
previousToolName = toolName;
|
|
1306
|
-
}
|
|
1307
1296
|
|
|
1308
1297
|
const color = rowHasFailed(row) ? "error" : "muted";
|
|
1309
|
-
const prefix =
|
|
1310
|
-
const
|
|
1311
|
-
const
|
|
1298
|
+
const prefix = `${fgCollapsedRail(theme, GROUP_CALL_MARKER)} `;
|
|
1299
|
+
const marker = collapsedCallMarker(row, theme, color);
|
|
1300
|
+
const budget = Math.max(
|
|
1301
|
+
1,
|
|
1302
|
+
width - visibleWidth(prefix) - visibleWidth(marker),
|
|
1303
|
+
);
|
|
1304
|
+
const label = collapsedChildLabel(row, budget, theme, color);
|
|
1312
1305
|
const outcome = collapsedOutcome(row, budget, theme);
|
|
1313
1306
|
const suffix = fgCollapsed(theme, color, "…");
|
|
1314
1307
|
lines.push(
|
|
1315
1308
|
prefix +
|
|
1309
|
+
marker +
|
|
1316
1310
|
(outcome
|
|
1317
1311
|
? fitSummaryTail(label, outcome, budget, suffix)
|
|
1318
1312
|
: fitSummary(label, budget, suffix)),
|
|
1319
1313
|
);
|
|
1320
|
-
if (row.toolName === "edit")
|
|
1321
|
-
lines.push(...renderedEditDiffLines(row, theme));
|
|
1322
1314
|
segments.push({ row, lines });
|
|
1323
1315
|
}
|
|
1324
1316
|
return segments;
|
|
@@ -1388,8 +1380,7 @@ function renderGroupedToolRows(
|
|
|
1388
1380
|
width,
|
|
1389
1381
|
),
|
|
1390
1382
|
];
|
|
1391
|
-
// The
|
|
1392
|
-
// both belong to the first member; every later member owns its lines.
|
|
1383
|
+
// The first member owns the leading blank; every member owns its call line.
|
|
1393
1384
|
const heights = segments.map((segment, index) => ({
|
|
1394
1385
|
component: segment.row,
|
|
1395
1386
|
height: index === 0 ? segment.lines.length + 1 : segment.lines.length,
|
|
@@ -1617,6 +1608,7 @@ function installPresentationPatch(): PresentationPatchState | undefined {
|
|
|
1617
1608
|
const state: PresentationPatchState = {
|
|
1618
1609
|
owners: 1,
|
|
1619
1610
|
collapseParallel: envEnabled(COLLAPSE_PARALLEL_ENV, true),
|
|
1611
|
+
expandedTools: envToolNames(EXPANDED_TOOLS_ENV),
|
|
1620
1612
|
groupCache: new WeakMap(),
|
|
1621
1613
|
collapsedCache: new WeakMap(),
|
|
1622
1614
|
rowVersions: new WeakMap(),
|
|
@@ -1624,7 +1616,7 @@ function installPresentationPatch(): PresentationPatchState | undefined {
|
|
|
1624
1616
|
originalRender: proto.render,
|
|
1625
1617
|
originalUpdateDisplay: proto.updateDisplay,
|
|
1626
1618
|
};
|
|
1627
|
-
const patchedUpdateDisplay = function
|
|
1619
|
+
const patchedUpdateDisplay = function updateDisplayWithToolPresentation(
|
|
1628
1620
|
this: ToolExecutionRow,
|
|
1629
1621
|
): void {
|
|
1630
1622
|
// Transcript rerenders reuse settled caches, but a real component
|
|
@@ -1634,6 +1626,17 @@ function installPresentationPatch(): PresentationPatchState | undefined {
|
|
|
1634
1626
|
state.groupCache.delete(this);
|
|
1635
1627
|
state.collapsedCache.delete(this);
|
|
1636
1628
|
state.originalUpdateDisplay.call(this);
|
|
1629
|
+
// Rows for an always-expanded tool skip the collapsed presentation.
|
|
1630
|
+
// Forcing the flag here, before grouping decides whether the row is
|
|
1631
|
+
// eligible, keeps Pi's native expanded block authoritative; it also
|
|
1632
|
+
// re-expands the row after a global collapse.
|
|
1633
|
+
if (
|
|
1634
|
+
this.expanded === false &&
|
|
1635
|
+
state.expandedTools.has(this.toolName ?? "") &&
|
|
1636
|
+
typeof this.setExpanded === "function"
|
|
1637
|
+
) {
|
|
1638
|
+
this.setExpanded(true);
|
|
1639
|
+
}
|
|
1637
1640
|
};
|
|
1638
1641
|
// Pi 0.85 wraps settled tool results in a click-to-expand MouseRegion.
|
|
1639
1642
|
// The custom collapsed row replaces those lines with a single summary, so
|
package/src/muted.ts
CHANGED
|
@@ -83,12 +83,8 @@ export function fgCollapsed(
|
|
|
83
83
|
// guaranteed lighter than the collapsed color (e.g. catppuccin-latte's `dim`
|
|
84
84
|
// resolves to the same overlay0 as syntaxComment), so apply the terminal's
|
|
85
85
|
// faint attribute: it lightens toward the background on light themes and
|
|
86
|
-
// darkens on dark ones.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
text: string,
|
|
91
|
-
): string {
|
|
92
|
-
const styled = fgCollapsed(theme, color, text);
|
|
93
|
-
return color === "error" ? styled : `\x1b[2m${styled}\x1b[22m`;
|
|
86
|
+
// darkens on dark ones. The rail keeps this muted weight even on failed
|
|
87
|
+
// rows, where only the row's text turns error-colored.
|
|
88
|
+
export function fgCollapsedRail(theme: CollapsedTheme, text: string): string {
|
|
89
|
+
return `\x1b[2m${fgCollapsed(theme, "muted", text)}\x1b[22m`;
|
|
94
90
|
}
|