@pi-kaush/pi-tool-call-markers 0.2.10 → 0.2.11
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 +4 -3
- package/README.md +10 -8
- package/package.json +1 -1
- package/src/index.ts +8 -0
- package/src/thinking-block-merger.ts +41 -25
package/CHANGELOG.md
CHANGED
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
- Adopt Pi's native content-color split in collapsed rows: tool names ride
|
|
14
14
|
`toolTitle` and call content/outcomes ride `toolOutput` (structural
|
|
15
15
|
chrome stays muted; failed rows stay uniformly error).
|
|
16
|
-
-
|
|
17
|
-
|
|
16
|
+
- Quiet the settled "+ Thought" label to the muted tone collapsed tool
|
|
17
|
+
calls use; only the live "⠋ Thinking…" spinner keeps the session's active
|
|
18
|
+
thinking-level tint (thinkingOff…thinkingMax), re-tinting on
|
|
18
19
|
thinking_level_select; the expanded thinking block is untouched. The
|
|
19
|
-
PI_TOOL_CALL_MARKERS_THOUGHT_COLOR values are
|
|
20
|
+
PI_TOOL_CALL_MARKERS_THOUGHT_COLOR values are `level` (default),
|
|
20
21
|
`mdheading`, and `inherit`; the midpoint `gray` variant and its RGB
|
|
21
22
|
color math are gone.
|
|
22
23
|
- Paint user-run `!` bash block surfaces with the theme's
|
package/README.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Give Pi's collapsed tool calls a quiet, width-safe transcript shell while preserving native details under `Ctrl+O`. The package also includes a display-only thinking-block adapter.
|
|
4
4
|
|
|
5
|
+
### Install
|
|
6
|
+
|
|
7
|
+
```fish
|
|
8
|
+
pi install npm:@pi-kaush/pi-tool-call-markers
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Restart Pi or run `/reload`.
|
|
12
|
+
|
|
5
13
|
## What it changes
|
|
6
14
|
|
|
7
15
|
Collapsed tool rows use semantic theme colors with no gear, background fill, box padding, or filled blank rows:
|
|
@@ -73,15 +81,9 @@ When Pi exposes its per-row hidden-thinking and streaming fields, hidden reasoni
|
|
|
73
81
|
|
|
74
82
|
The live label samples Pi's native braille spinner sequence from the content updates Pi already renders; it does not add a timer. The adapter stores the first local streaming timestamp per assistant row in a `WeakMap`. A restored message or an older runtime with no streaming argument uses `+ Thought`. Visible-thinking mode remains native. There is no interval, timeout, render request, model call, or network work.
|
|
75
83
|
|
|
76
|
-
##
|
|
84
|
+
## Local development
|
|
77
85
|
|
|
78
|
-
```
|
|
79
|
-
pi install npm:@pi-kaush/pi-tool-call-markers
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
For local development:
|
|
83
|
-
|
|
84
|
-
```bash
|
|
86
|
+
```fish
|
|
85
87
|
pi \
|
|
86
88
|
-e ./extensions/pi-tool-call-markers/src/index.ts \
|
|
87
89
|
-e ./extensions/pi-tool-call-markers/src/thinking-block-merger.ts
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1660,6 +1660,14 @@ function uninstallPresentationPatch(
|
|
|
1660
1660
|
delete proto[PRESENTATION_PATCHED];
|
|
1661
1661
|
}
|
|
1662
1662
|
|
|
1663
|
+
// TODO(compaction cards): native/failed compaction cards in the transcript
|
|
1664
|
+
// are currently rendered by the pi-verbatim-compaction extension. Its
|
|
1665
|
+
// src/chat-log.ts is deliberately self-contained (public Pi imports only), so
|
|
1666
|
+
// porting here is: drop in that file, registerEntryRenderer(COMPACTION_LOG_TYPE),
|
|
1667
|
+
// and wire pi.on("session_compact") / pi.on("session_compact_failed") filtered
|
|
1668
|
+
// to fromExtension === false. Do this only if pi-verbatim-compaction is
|
|
1669
|
+
// removed or native cards should exist without it; while both are installed,
|
|
1670
|
+
// rendering here too would double-render every native compaction.
|
|
1663
1671
|
export default function (pi: ExtensionAPI) {
|
|
1664
1672
|
const patch = installPresentationPatch();
|
|
1665
1673
|
const grouping = patch ? installGroupingPatch(patch) : undefined;
|
|
@@ -6,13 +6,16 @@ const THINKING_GROUPING_PATCHED = Symbol.for("kg.pi.thinkingGrouping.v2");
|
|
|
6
6
|
const PI_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
7
7
|
const SPINNER_INTERVAL_MS = 80;
|
|
8
8
|
|
|
9
|
-
// Visual
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
9
|
+
// Visual treatment for the collapsed thinking label. The live "Thinking…"
|
|
10
|
+
// spinner tints with the session's active thinking-level color
|
|
11
|
+
// (thinkingOff…thinkingMax), so progress reads as activity; the settled
|
|
12
|
+
// "+ Thought" row drops to the muted token collapsed tool calls use, so
|
|
13
|
+
// finished reasoning stops advertising the level. "inherit" keeps Pi's
|
|
14
|
+
// native styling (italic + thinkingText) for both states, and "mdheading"
|
|
15
|
+
// rides the theme's mdHeading token for both. The env var overrides the
|
|
16
|
+
// default so variants can be compared without republishing. Only the
|
|
17
|
+
// collapsed label is restyled — the expanded thinking block keeps Pi's
|
|
18
|
+
// thinkingText.
|
|
16
19
|
const THOUGHT_LABEL_COLOR_ENV = "PI_TOOL_CALL_MARKERS_THOUGHT_COLOR";
|
|
17
20
|
type ThoughtLabelColor = "inherit" | "level" | "mdheading";
|
|
18
21
|
const DEFAULT_THOUGHT_LABEL_COLOR: ThoughtLabelColor = "level";
|
|
@@ -44,35 +47,48 @@ type ThemeDetail = {
|
|
|
44
47
|
let activeTheme: ThemeDetail | undefined;
|
|
45
48
|
let activeLevel: (() => string) | undefined;
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
let
|
|
50
|
+
type LabelStyle = { prefix: string; suffix: string };
|
|
51
|
+
let liveLabelStyle: LabelStyle | undefined;
|
|
52
|
+
let settledLabelStyle: LabelStyle | undefined;
|
|
53
|
+
|
|
54
|
+
function styledWith(token: string): LabelStyle | undefined {
|
|
55
|
+
const ansi = activeTheme?.getFgAnsi?.(token);
|
|
56
|
+
if (!ansi) return undefined;
|
|
57
|
+
// The styled label replaces Pi's italicized Text node wholesale (see
|
|
58
|
+
// restyleHiddenThinkingLabel). The leading italic-off still matters: the
|
|
59
|
+
// TUI's diff renderer can skip bytes shared with the previously drawn
|
|
60
|
+
// italic line, leaving the terminal in italic state otherwise.
|
|
61
|
+
return { prefix: `\x1b[23m${ansi}`, suffix: "\x1b[39m" };
|
|
62
|
+
}
|
|
49
63
|
|
|
50
64
|
function updateThoughtLabelStyle(): void {
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
liveLabelStyle = undefined;
|
|
66
|
+
settledLabelStyle = undefined;
|
|
53
67
|
const choice = thoughtLabelColorChoice();
|
|
54
68
|
if (choice === "inherit" || !activeTheme) return;
|
|
55
69
|
|
|
56
|
-
let ansi: string | undefined;
|
|
57
70
|
const token =
|
|
58
71
|
choice === "mdheading"
|
|
59
72
|
? "mdHeading"
|
|
60
73
|
: (LEVEL_TOKEN[activeLevel?.() ?? "off"] ?? "thinkingOff");
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
liveLabelStyle = styledWith(token);
|
|
75
|
+
settledLabelStyle =
|
|
76
|
+
choice === "mdheading" ? liveLabelStyle : styledWith("muted");
|
|
77
|
+
}
|
|
63
78
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
thoughtLabelPrefix = `\x1b[23m${ansi}`;
|
|
69
|
-
thoughtLabelSuffix = "\x1b[39m";
|
|
79
|
+
// The settled label is the finalized "+ Thought" row; every other label is
|
|
80
|
+
// the live spinner.
|
|
81
|
+
function isSettledThoughtLabel(label: string): boolean {
|
|
82
|
+
return label.startsWith("+ Thought");
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
export function visibleThoughtLabel(label: string): string {
|
|
73
|
-
|
|
86
|
+
const style = isSettledThoughtLabel(label)
|
|
87
|
+
? settledLabelStyle
|
|
88
|
+
: liveLabelStyle;
|
|
89
|
+
if (!style) return label;
|
|
74
90
|
const raw = label.replace(/\x1b\[[0-9;]*m/g, "");
|
|
75
|
-
return `${
|
|
91
|
+
return `${style.prefix}${raw}${style.suffix}`;
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
type AssistantMessageLike = {
|
|
@@ -98,7 +114,6 @@ type TextLikeChild = {
|
|
|
98
114
|
// terminal. Swap the node's text for a self-contained styled version after
|
|
99
115
|
// each native render pass instead.
|
|
100
116
|
function restyleHiddenThinkingLabel(row: AssistantMessageRow): void {
|
|
101
|
-
if (!thoughtLabelPrefix) return;
|
|
102
117
|
if (
|
|
103
118
|
row.hideThinkingBlock !== true ||
|
|
104
119
|
typeof row.hiddenThinkingLabel !== "string"
|
|
@@ -108,6 +123,7 @@ function restyleHiddenThinkingLabel(row: AssistantMessageRow): void {
|
|
|
108
123
|
const label = row.hiddenThinkingLabel;
|
|
109
124
|
const children = row.contentContainer?.children;
|
|
110
125
|
if (!Array.isArray(children)) return;
|
|
126
|
+
if (!liveLabelStyle && !settledLabelStyle) return;
|
|
111
127
|
const styled = visibleThoughtLabel(label);
|
|
112
128
|
for (const child of children) {
|
|
113
129
|
const textChild = child as TextLikeChild | undefined;
|
|
@@ -419,7 +435,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
419
435
|
if (patch && !uninstallThinkingGroupingPatch(patch)) return;
|
|
420
436
|
activeTheme = undefined;
|
|
421
437
|
activeLevel = undefined;
|
|
422
|
-
|
|
423
|
-
|
|
438
|
+
liveLabelStyle = undefined;
|
|
439
|
+
settledLabelStyle = undefined;
|
|
424
440
|
});
|
|
425
441
|
}
|