@pi-kaush/pi-tool-call-markers 0.1.0 → 0.1.2
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 +11 -0
- package/README.md +3 -1
- package/package.json +1 -1
- package/src/index.ts +64 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
- Keep grouping within one assistant tool batch, so a later pending batch does not reopen completed groups.
|
|
6
|
+
- Wait for every tool in a batch to settle, including tools beyond failed or expanded siblings.
|
|
7
|
+
- Preserve partial and image-bearing results instead of collapsing them.
|
|
8
|
+
- Treat self-rendered tools as owning their full shell and use only their stable header line in grouped summaries.
|
|
9
|
+
|
|
10
|
+
## 0.1.1
|
|
11
|
+
|
|
12
|
+
- Wait for every call in a contiguous parallel run to settle before grouping successful calls, which prevents completed prefixes and suffixes from repeatedly collapsing around active calls.
|
|
13
|
+
|
|
3
14
|
## 0.1.0
|
|
4
15
|
|
|
5
16
|
- Collapse adjacent successful tool calls into one compact block per tool type, each with a gear header and bulleted call summaries.
|
package/README.md
CHANGED
|
@@ -10,7 +10,9 @@ When several tool calls of the same type succeed in a row, Pi normally renders e
|
|
|
10
10
|
- **Bulleted call summaries.** Each call in a group becomes one bullet with a short summary (the tool name is stripped from the bullet since the header already names the tool).
|
|
11
11
|
- **Vertical spacing between tool types.** A blank line separates one tool group from the next.
|
|
12
12
|
- **Hanging indent for wrapped bullets.** When a summary wraps, continuation lines align under the bullet text rather than under the gear.
|
|
13
|
-
- **
|
|
13
|
+
- **Tool batches settle before grouping.** A tool batch stays ungrouped while any sibling call is active. Completed batches remain stable when a later assistant turn starts, and successful calls group around failed-call boundaries after the batch settles.
|
|
14
|
+
- **Self-rendered tools keep their shell.** Tools that own their framing keep singleton previews intact. Grouped summaries use only their stable header instead of scraping preview or diff lines.
|
|
15
|
+
- **Partial and image results stay visible.** Streaming progress and image-bearing results are not collapsed into text-only groups.
|
|
14
16
|
- **Errors expand in place.** A failed call keeps its own block and shows its full detail.
|
|
15
17
|
- **Ctrl+O restores full blocks.** Expanding tools (`setToolsExpanded(true)`) brings back Pi's individual full blocks, results and all.
|
|
16
18
|
- **Adjacent thinking blocks combine.** Only directly adjacent `thinking` blocks merge into one; a non-thinking block between them keeps them separate. Malformed thinking content safely falls back to Pi's renderer exactly once, so the display never breaks.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-kaush/pi-tool-call-markers",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Collapse adjacent successful tool calls into one compact, gear-headed block per tool type in Pi's transcript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kaushik Gopal",
|
package/src/index.ts
CHANGED
|
@@ -47,7 +47,10 @@ type ToolExecutionRow = {
|
|
|
47
47
|
args?: unknown;
|
|
48
48
|
expanded?: boolean;
|
|
49
49
|
isPartial?: boolean;
|
|
50
|
-
result?: {
|
|
50
|
+
result?: {
|
|
51
|
+
isError?: boolean;
|
|
52
|
+
content?: Array<{ type?: unknown }>;
|
|
53
|
+
};
|
|
51
54
|
contentBox?: ComponentContainer;
|
|
52
55
|
contentText?: TextComponent;
|
|
53
56
|
selfRenderContainer?: ComponentContainer;
|
|
@@ -204,14 +207,18 @@ function hideResultImages(row: ToolExecutionRow): void {
|
|
|
204
207
|
}
|
|
205
208
|
|
|
206
209
|
function collapseSuccessfulResult(row: ToolExecutionRow): void {
|
|
207
|
-
if (
|
|
210
|
+
if (
|
|
211
|
+
row.expanded !== false ||
|
|
212
|
+
row.isPartial !== false ||
|
|
213
|
+
!row.result ||
|
|
214
|
+
row.result.isError ||
|
|
215
|
+
hasImageResult(row) ||
|
|
216
|
+
row.getRenderShell?.() === "self"
|
|
217
|
+
)
|
|
218
|
+
return;
|
|
208
219
|
|
|
209
220
|
const collapsed = row.hasRendererDefinition?.()
|
|
210
|
-
? removeResultComponent(
|
|
211
|
-
row.getRenderShell?.() === "self"
|
|
212
|
-
? row.selfRenderContainer
|
|
213
|
-
: row.contentBox,
|
|
214
|
-
)
|
|
221
|
+
? removeResultComponent(row.contentBox)
|
|
215
222
|
: collapseGenericResult(row);
|
|
216
223
|
if (collapsed) hideResultImages(row);
|
|
217
224
|
}
|
|
@@ -222,15 +229,55 @@ function isToolExecutionRow(
|
|
|
222
229
|
return component instanceof ToolExecutionComponent;
|
|
223
230
|
}
|
|
224
231
|
|
|
232
|
+
function isAssistantMessageRow(component: unknown): boolean {
|
|
233
|
+
return component instanceof AssistantMessageComponent;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function hasImageResult(row: ToolExecutionRow): boolean {
|
|
237
|
+
return (
|
|
238
|
+
row.result?.content?.some((content) => content.type === "image") === true ||
|
|
239
|
+
(row.imageComponents?.length ?? 0) > 0 ||
|
|
240
|
+
(row.imageSpacers?.length ?? 0) > 0
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
225
244
|
function isCollapsibleSuccess(row: ToolExecutionRow): boolean {
|
|
226
245
|
return (
|
|
227
246
|
row.expanded === false &&
|
|
228
247
|
row.isPartial === false &&
|
|
229
248
|
!!row.result &&
|
|
230
|
-
!row.result.isError
|
|
249
|
+
!row.result.isError &&
|
|
250
|
+
!hasImageResult(row)
|
|
231
251
|
);
|
|
232
252
|
}
|
|
233
253
|
|
|
254
|
+
function isSettledToolRow(row: ToolExecutionRow): boolean {
|
|
255
|
+
return row.isPartial === false && !!row.result;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function hasUnsettledToolInBatch(
|
|
259
|
+
children: unknown[],
|
|
260
|
+
index: number,
|
|
261
|
+
renderAt: (index: number) => string[],
|
|
262
|
+
): boolean {
|
|
263
|
+
for (const direction of [-1, 1] as const) {
|
|
264
|
+
for (
|
|
265
|
+
let candidateIndex = index + direction;
|
|
266
|
+
candidateIndex >= 0 && candidateIndex < children.length;
|
|
267
|
+
candidateIndex += direction
|
|
268
|
+
) {
|
|
269
|
+
const candidate = children[candidateIndex];
|
|
270
|
+
if (isAssistantMessageRow(candidate)) break;
|
|
271
|
+
if (isToolExecutionRow(candidate)) {
|
|
272
|
+
if (!isSettledToolRow(candidate)) return true;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (renderAt(candidateIndex).some(hasVisibleContent)) break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
|
|
234
281
|
function renderComponent(component: unknown, width: number): string[] {
|
|
235
282
|
if (!component || typeof (component as ComponentLike).render !== "function")
|
|
236
283
|
return [];
|
|
@@ -313,11 +360,12 @@ function renderedCallSummary(
|
|
|
313
360
|
component = row.contentBox.children[0] as ComponentLike | undefined;
|
|
314
361
|
}
|
|
315
362
|
|
|
363
|
+
const selfRendered = row.getRenderShell?.() === "self";
|
|
316
364
|
if (component && typeof component.render === "function") {
|
|
317
365
|
const visibleLines = component
|
|
318
366
|
.render(Math.max(1, width))
|
|
319
367
|
.filter(hasVisibleContent);
|
|
320
|
-
const rendered = visibleLines.slice(0, 3);
|
|
368
|
+
const rendered = visibleLines.slice(0, selfRendered ? 1 : 3);
|
|
321
369
|
const line = rendered[0];
|
|
322
370
|
if (line) {
|
|
323
371
|
const first = trimRenderedLine(line);
|
|
@@ -353,6 +401,8 @@ function renderedCallSummary(
|
|
|
353
401
|
}
|
|
354
402
|
}
|
|
355
403
|
|
|
404
|
+
if (selfRendered) return theme.fg("muted", "(details omitted)");
|
|
405
|
+
|
|
356
406
|
const fallback = compactArgs(row.args);
|
|
357
407
|
return fallback
|
|
358
408
|
? theme.fg("accent", fallback)
|
|
@@ -550,6 +600,10 @@ function renderContainerWithToolGroups(
|
|
|
550
600
|
lines.push(...renderAt(index));
|
|
551
601
|
continue;
|
|
552
602
|
}
|
|
603
|
+
if (hasUnsettledToolInBatch(children, index, renderAt)) {
|
|
604
|
+
lines.push(...renderAt(index));
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
553
607
|
|
|
554
608
|
const group: ToolExecutionRow[] = [child];
|
|
555
609
|
let lastMemberIndex = index;
|
|
@@ -559,6 +613,7 @@ function renderContainerWithToolGroups(
|
|
|
559
613
|
candidateIndex++
|
|
560
614
|
) {
|
|
561
615
|
const candidate = children[candidateIndex];
|
|
616
|
+
if (isAssistantMessageRow(candidate)) break;
|
|
562
617
|
if (isToolExecutionRow(candidate)) {
|
|
563
618
|
if (!isCollapsibleSuccess(candidate)) break;
|
|
564
619
|
group.push(candidate);
|