@esso0428/pi-subagents 0.15.13 → 0.15.15
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 +6 -31
- package/dist/ui/agent-widget.d.ts +8 -0
- package/dist/ui/agent-widget.d.ts.map +1 -1
- package/dist/ui/agent-widget.js +40 -12
- package/dist/ui/agent-widget.js.map +1 -1
- package/dist/ui/ccstyle/diff/diff-renderer.d.ts.map +1 -1
- package/dist/ui/ccstyle/diff/diff-renderer.js +2 -4
- package/dist/ui/ccstyle/diff/diff-renderer.js.map +1 -1
- package/dist/ui/ccstyle/tool-renderer.d.ts.map +1 -1
- package/dist/ui/ccstyle/tool-renderer.js +17 -11
- package/dist/ui/ccstyle/tool-renderer.js.map +1 -1
- package/dist/ui/ccstyle/tool-result.d.ts +22 -10
- package/dist/ui/ccstyle/tool-result.d.ts.map +1 -1
- package/dist/ui/ccstyle/tool-result.js +160 -73
- package/dist/ui/ccstyle/tool-result.js.map +1 -1
- package/dist/ui/conversation-timeline.d.ts +16 -9
- package/dist/ui/conversation-timeline.d.ts.map +1 -1
- package/dist/ui/conversation-timeline.js +85 -61
- package/dist/ui/conversation-timeline.js.map +1 -1
- package/dist/ui/conversation-viewer.d.ts +4 -1
- package/dist/ui/conversation-viewer.d.ts.map +1 -1
- package/dist/ui/conversation-viewer.js +107 -110
- package/dist/ui/conversation-viewer.js.map +1 -1
- package/dist/write-execution.d.ts +0 -2
- package/dist/write-execution.d.ts.map +1 -1
- package/dist/write-execution.js +1 -5
- package/dist/write-execution.js.map +1 -1
- package/package.json +1 -1
- package/src/ui/agent-widget.ts +38 -12
- package/src/ui/ccstyle/diff/diff-renderer.ts +2 -7
- package/src/ui/ccstyle/tool-renderer.ts +23 -24
- package/src/ui/ccstyle/tool-result.ts +167 -107
- package/src/ui/conversation-timeline.ts +103 -62
- package/src/ui/conversation-viewer.ts +119 -124
- package/src/write-execution.ts +1 -7
- package/test/ui/agent-widget.test.ts +123 -0
- package/test/ui/conversation-diff.test.ts +1 -28
- package/test/ui/conversation-viewer.test.ts +181 -112
- package/test/write-execution.test.ts +0 -2
- package/.pi/tasks/tasks-01a09263-0ac6-77be-97f5-664b3ffea76b.json +0 -53
- package/.pi/workflows/index.json +0 -5
package/dist/write-execution.js
CHANGED
|
@@ -81,10 +81,7 @@ async function capturePreviousContent(absolutePath) {
|
|
|
81
81
|
}
|
|
82
82
|
function durableDetails(metadata, path, content) {
|
|
83
83
|
if (metadata.diffUnavailableReason) {
|
|
84
|
-
return {
|
|
85
|
-
fileExistedBeforeWrite: metadata.fileExistedBeforeWrite,
|
|
86
|
-
diffUnavailableReason: metadata.diffUnavailableReason,
|
|
87
|
-
};
|
|
84
|
+
return { diffUnavailableReason: metadata.diffUnavailableReason };
|
|
88
85
|
}
|
|
89
86
|
const previousContent = metadata.previousContent ?? "";
|
|
90
87
|
const diffResult = generateDiffString(previousContent, content);
|
|
@@ -94,7 +91,6 @@ function durableDetails(metadata, path, content) {
|
|
|
94
91
|
return { diffUnavailableReason: `durable diff exceeds ${MAX_DURABLE_DIFF_BYTES} bytes` };
|
|
95
92
|
}
|
|
96
93
|
return {
|
|
97
|
-
fileExistedBeforeWrite: metadata.fileExistedBeforeWrite,
|
|
98
94
|
diff: diffResult.diff,
|
|
99
95
|
patch,
|
|
100
96
|
firstChangedLine: diffResult.firstChangedLine,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-execution.js","sourceRoot":"","sources":["../src/write-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,oBAAoB,EAA8C,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACzL,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzD,yEAAyE;AACzE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AACtD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,0BAA0B,GAAG,OAAO,CAAC;AAClD,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"write-execution.js","sourceRoot":"","sources":["../src/write-execution.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@esso0428/pi-subagents",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.15",
|
|
4
4
|
"description": "A pi extension that brings smart Claude Code-style autonomous sub-agents to pi, with npm:pi-subagents-style JSON agent overrides.",
|
|
5
5
|
"author": "ESSO0428",
|
|
6
6
|
"repository": {
|
package/src/ui/agent-widget.ts
CHANGED
|
@@ -14,7 +14,19 @@ import { getLifetimeTotal, getSessionContextPercent, type LifetimeUsage, type Se
|
|
|
14
14
|
// ---- Constants ----
|
|
15
15
|
|
|
16
16
|
/** Maximum number of rendered lines before overflow collapse kicks in. */
|
|
17
|
-
const MAX_WIDGET_LINES = 12;
|
|
17
|
+
export const MAX_WIDGET_LINES = 12;
|
|
18
|
+
/** Keep a small editor/input area visible below the above-editor widget. */
|
|
19
|
+
const MIN_EDITOR_LINES = 4;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Derive the widget ceiling from the terminal height while retaining the
|
|
23
|
+
* historical MAX_WIDGET_LINES ceiling. Very short terminals may have no room
|
|
24
|
+
* for the widget; that is preferable to consuming the editor/input area.
|
|
25
|
+
*/
|
|
26
|
+
export function getWidgetLineBudget(rows: number): number {
|
|
27
|
+
if (!Number.isFinite(rows)) return MAX_WIDGET_LINES;
|
|
28
|
+
return Math.min(MAX_WIDGET_LINES, Math.max(0, Math.floor(rows) - MIN_EDITOR_LINES));
|
|
29
|
+
}
|
|
18
30
|
|
|
19
31
|
/** Braille spinner frames for animated running indicator. */
|
|
20
32
|
export const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
@@ -176,9 +188,9 @@ export function buildInvocationTags(
|
|
|
176
188
|
return { modelName: invocation.modelName, tags };
|
|
177
189
|
}
|
|
178
190
|
|
|
179
|
-
/**
|
|
191
|
+
/** Normalize and truncate text so it can never add physical widget rows. */
|
|
180
192
|
function truncateLine(text: string, len = 60): string {
|
|
181
|
-
const line = text.
|
|
193
|
+
const line = text.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
|
182
194
|
if (line.length <= len) return line;
|
|
183
195
|
return line.slice(0, len) + "…";
|
|
184
196
|
}
|
|
@@ -325,7 +337,7 @@ export class AgentWidget {
|
|
|
325
337
|
statusText = theme.fg("dim", " stopped");
|
|
326
338
|
} else if (a.status === "error") {
|
|
327
339
|
icon = theme.fg("error", "✗");
|
|
328
|
-
const errMsg = a.error ? `: ${a.error
|
|
340
|
+
const errMsg = a.error ? `: ${truncateLine(a.error)}` : "";
|
|
329
341
|
statusText = theme.fg("error", ` error${errMsg}`);
|
|
330
342
|
} else {
|
|
331
343
|
// aborted
|
|
@@ -340,7 +352,7 @@ export class AgentWidget {
|
|
|
340
352
|
parts.push(duration);
|
|
341
353
|
|
|
342
354
|
const modeTag = modeLabel ? ` ${theme.fg("dim", `(${modeLabel})`)}` : "";
|
|
343
|
-
return `${icon} ${theme.fg("dim", name)}${modeTag} ${theme.fg("dim", a.description)} ${theme.fg("dim", "·")} ${theme.fg("dim", parts.join(" · "))}${statusText}`;
|
|
355
|
+
return `${icon} ${theme.fg("dim", name)}${modeTag} ${theme.fg("dim", truncateLine(a.description))} ${theme.fg("dim", "·")} ${theme.fg("dim", parts.join(" · "))}${statusText}`;
|
|
344
356
|
}
|
|
345
357
|
|
|
346
358
|
/**
|
|
@@ -363,6 +375,8 @@ export class AgentWidget {
|
|
|
363
375
|
if (!hasActive && !hasFinished) return [];
|
|
364
376
|
|
|
365
377
|
const w = tui.terminal.columns;
|
|
378
|
+
const maxLines = getWidgetLineBudget(tui.terminal.rows);
|
|
379
|
+
if (maxLines === 0) return [];
|
|
366
380
|
const truncate = (line: string) => truncateToWidth(line, w);
|
|
367
381
|
const headingColor = hasActive ? "accent" : "dim";
|
|
368
382
|
const headingIcon = hasActive ? "●" : "○";
|
|
@@ -399,7 +413,7 @@ export class AgentWidget {
|
|
|
399
413
|
const activity = bg ? describeActivity(bg.activeTools, bg.responseText) : "thinking…";
|
|
400
414
|
|
|
401
415
|
runningLines.push([
|
|
402
|
-
truncate(theme.fg("dim", "├─") + ` ${theme.fg("accent", frame)} ${theme.bold(name)}${modeTag} ${theme.fg("muted", a.description)} ${theme.fg("dim", "·")} ${fgPreservingNestedStyles(theme, "dim", statsText)}`),
|
|
416
|
+
truncate(theme.fg("dim", "├─") + ` ${theme.fg("accent", frame)} ${theme.bold(name)}${modeTag} ${theme.fg("muted", truncateLine(a.description))} ${theme.fg("dim", "·")} ${fgPreservingNestedStyles(theme, "dim", statsText)}`),
|
|
403
417
|
truncate(theme.fg("dim", "│ ") + theme.fg("dim", ` ⎿ ${activity}`)),
|
|
404
418
|
]);
|
|
405
419
|
}
|
|
@@ -408,12 +422,18 @@ export class AgentWidget {
|
|
|
408
422
|
? truncate(theme.fg("dim", "├─") + ` ${theme.fg("muted", "◦")} ${theme.fg("dim", `${queued.length} queued`)}`)
|
|
409
423
|
: undefined;
|
|
410
424
|
|
|
411
|
-
// Assemble with
|
|
412
|
-
|
|
425
|
+
// Assemble with a responsive cap (heading + overflow indicator = 2
|
|
426
|
+
// reserved lines when content exceeds the available body budget).
|
|
427
|
+
const maxBody = maxLines - 1; // heading takes 1 line
|
|
413
428
|
const totalBody = finishedLines.length + runningLines.length * 2 + (queuedLine ? 1 : 0);
|
|
414
429
|
|
|
415
430
|
const lines: string[] = [truncate(theme.fg(headingColor, headingIcon) + " " + theme.fg(headingColor, "Agents"))];
|
|
416
431
|
|
|
432
|
+
if (maxLines === 1) {
|
|
433
|
+
// There is room only for the heading; do not consume the editor/input row.
|
|
434
|
+
return lines;
|
|
435
|
+
}
|
|
436
|
+
|
|
417
437
|
if (totalBody <= maxBody) {
|
|
418
438
|
// Everything fits — add all lines and fix up connectors for the last item.
|
|
419
439
|
lines.push(...finishedLines);
|
|
@@ -439,6 +459,7 @@ export class AgentWidget {
|
|
|
439
459
|
// Reserve 1 line for overflow indicator.
|
|
440
460
|
let budget = maxBody - 1;
|
|
441
461
|
let hiddenRunning = 0;
|
|
462
|
+
let hiddenQueued = 0;
|
|
442
463
|
let hiddenFinished = 0;
|
|
443
464
|
|
|
444
465
|
// 1. Running agents (2 lines each)
|
|
@@ -452,9 +473,13 @@ export class AgentWidget {
|
|
|
452
473
|
}
|
|
453
474
|
|
|
454
475
|
// 2. Queued line
|
|
455
|
-
if (queuedLine
|
|
456
|
-
|
|
457
|
-
|
|
476
|
+
if (queuedLine) {
|
|
477
|
+
if (budget >= 1) {
|
|
478
|
+
lines.push(queuedLine);
|
|
479
|
+
budget--;
|
|
480
|
+
} else {
|
|
481
|
+
hiddenQueued = 1;
|
|
482
|
+
}
|
|
458
483
|
}
|
|
459
484
|
|
|
460
485
|
// 3. Finished agents
|
|
@@ -470,9 +495,10 @@ export class AgentWidget {
|
|
|
470
495
|
// Overflow summary
|
|
471
496
|
const overflowParts: string[] = [];
|
|
472
497
|
if (hiddenRunning > 0) overflowParts.push(`${hiddenRunning} running`);
|
|
498
|
+
if (hiddenQueued > 0) overflowParts.push(`${hiddenQueued} queued`);
|
|
473
499
|
if (hiddenFinished > 0) overflowParts.push(`${hiddenFinished} finished`);
|
|
474
500
|
const overflowText = overflowParts.join(", ");
|
|
475
|
-
lines.push(truncate(theme.fg("dim", "└─") + ` ${theme.fg("dim", `+${hiddenRunning + hiddenFinished} more (${overflowText})`)}`)
|
|
501
|
+
lines.push(truncate(theme.fg("dim", "└─") + ` ${theme.fg("dim", `+${hiddenRunning + hiddenQueued + hiddenFinished} more (${overflowText})`)}`)
|
|
476
502
|
);
|
|
477
503
|
}
|
|
478
504
|
|
|
@@ -2951,11 +2951,6 @@ export function renderWriteDiffResult(
|
|
|
2951
2951
|
return new Text(theme.fg("warning", "↳ diff unavailable: durable diff has no displayable lines"), 0, 0);
|
|
2952
2952
|
}
|
|
2953
2953
|
}
|
|
2954
|
-
const persistedWasOverwrite = persistedParsed?.entries.some(
|
|
2955
|
-
(entry) => entry.kind === "line" && entry.lineKind === "remove",
|
|
2956
|
-
) ?? false;
|
|
2957
|
-
const wasOverwrite = options.fileExistedBeforeWrite === true || persistedWasOverwrite;
|
|
2958
|
-
|
|
2959
2954
|
if (typeof content !== "string" && !persistedParsed) {
|
|
2960
2955
|
if (!safeFallbackText.trim()) {
|
|
2961
2956
|
return new Text(theme.fg("muted", "↳ write completed"), 0, 0);
|
|
@@ -3036,7 +3031,7 @@ export function renderWriteDiffResult(
|
|
|
3036
3031
|
hovered,
|
|
3037
3032
|
clampDiffLinesToWidth(
|
|
3038
3033
|
renderWriteCollapsedHintLine(
|
|
3039
|
-
|
|
3034
|
+
options.fileExistedBeforeWrite === true,
|
|
3040
3035
|
safeWidth,
|
|
3041
3036
|
theme,
|
|
3042
3037
|
hovered,
|
|
@@ -3048,7 +3043,7 @@ export function renderWriteDiffResult(
|
|
|
3048
3043
|
}
|
|
3049
3044
|
|
|
3050
3045
|
const header = renderWriteHeader(
|
|
3051
|
-
|
|
3046
|
+
options.fileExistedBeforeWrite === true,
|
|
3052
3047
|
safeWidth,
|
|
3053
3048
|
theme,
|
|
3054
3049
|
options.headerLabel,
|
|
@@ -17,13 +17,22 @@ function titleForTool(toolName: string): string {
|
|
|
17
17
|
.replace(/\b\w/g, (character) => character.toUpperCase());
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
function summaryForCall(toolName: string, args: any): string {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
function summaryForCall(toolName: string, args: any): { main: string; detail: string } {
|
|
21
|
+
const title = titleForTool(toolName);
|
|
22
|
+
if (!args || typeof args !== "object") return { main: title, detail: "" };
|
|
23
|
+
if (toolName.toLowerCase() === "read") {
|
|
24
|
+
const path = args.path ?? args.file_path;
|
|
25
|
+
const details = [
|
|
26
|
+
args.offset !== undefined ? `offset=${args.offset}` : "",
|
|
27
|
+
args.limit !== undefined ? `limit=${args.limit}` : "",
|
|
28
|
+
].filter(Boolean);
|
|
29
|
+
return {
|
|
30
|
+
main: path === undefined ? title : `${title} ${oneLine(path)}`,
|
|
31
|
+
detail: details.length ? ` (${details.join(", ")})` : "",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const value = args.path ?? args.file_path ?? args.command ?? args.query ?? args.pattern ?? args.url ?? args.name;
|
|
35
|
+
return value === undefined ? { main: title, detail: "" } : { main: `${title} ${oneLine(value)}`, detail: "" };
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
function renderCallComponent(toolName: string, args: any, theme: any, context: any): Component {
|
|
@@ -34,7 +43,8 @@ function renderCallComponent(toolName: string, args: any, theme: any, context: a
|
|
|
34
43
|
render(width: number): string[] {
|
|
35
44
|
const safeWidth = Math.max(1, Math.floor(Number.isFinite(width) ? width : 1));
|
|
36
45
|
const prefix = ` ${theme.fg(color, icon)} `;
|
|
37
|
-
|
|
46
|
+
const summary = summaryForCall(toolName, args);
|
|
47
|
+
return [truncateToWidth(prefix + theme.fg("toolTitle", summary.main) + theme.fg("dim", summary.detail), safeWidth, "")];
|
|
38
48
|
},
|
|
39
49
|
invalidate() {},
|
|
40
50
|
};
|
|
@@ -63,22 +73,11 @@ export function createViewerCcstyleTool(toolName: string, isHovered: () => boole
|
|
|
63
73
|
},
|
|
64
74
|
renderResult(result, options, theme, context) {
|
|
65
75
|
settled = true;
|
|
66
|
-
return createViewerCcstyleResult(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{ ...
|
|
70
|
-
|
|
71
|
-
{
|
|
72
|
-
...context,
|
|
73
|
-
isHovered,
|
|
74
|
-
diffConfig: {
|
|
75
|
-
...DEFAULT_TOOL_DISPLAY_CONFIG,
|
|
76
|
-
// The viewer itself is scrollable, so an expanded card should not
|
|
77
|
-
// stop at the compact 40-line diff preview.
|
|
78
|
-
expandedPreviewMaxLines: Number.MAX_SAFE_INTEGER,
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
);
|
|
76
|
+
return createViewerCcstyleResult(name, result, { ...options, isHovered }, theme, {
|
|
77
|
+
...context,
|
|
78
|
+
isHovered,
|
|
79
|
+
diffConfig: { ...DEFAULT_TOOL_DISPLAY_CONFIG },
|
|
80
|
+
});
|
|
82
81
|
},
|
|
83
82
|
};
|
|
84
83
|
}
|
|
@@ -51,56 +51,159 @@ export function outputLineCount(result: any): number {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export function countLines(text: string): number {
|
|
54
|
-
return text.trim() ? text.trim().split("\n").length : 0;
|
|
54
|
+
return text.trim() ? text.trim().split("\n").filter((line) => line.trim()).length : 0;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/** Format arguments as stable, readable `key: value` rows for the Input rail. */
|
|
57
58
|
export function formatToolInputArgs(args: unknown, maxChars = 8_000): string {
|
|
58
59
|
if (args === undefined || args === null) return "";
|
|
59
|
-
|
|
60
|
-
typeof args === "
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
if (typeof args !== "object" || Array.isArray(args)) {
|
|
61
|
+
const rendered = typeof args === "string" ? sanitizeToolResultText(args) : safeJson(args);
|
|
62
|
+
return rendered.length > maxChars ? `${rendered.slice(0, maxChars)}…` : rendered;
|
|
63
|
+
}
|
|
64
|
+
const preferred = [
|
|
65
|
+
"path", "file_path", "command", "query", "pattern", "url", "name",
|
|
66
|
+
"message", "content", "old_string", "new_string",
|
|
67
|
+
];
|
|
68
|
+
const entries = Object.entries(args as Record<string, unknown>)
|
|
69
|
+
.filter(([, value]) => value !== undefined)
|
|
70
|
+
.sort(([left], [right]) => {
|
|
71
|
+
const li = preferred.indexOf(left);
|
|
72
|
+
const ri = preferred.indexOf(right);
|
|
73
|
+
if (li < 0 && ri < 0) return left.localeCompare(right);
|
|
74
|
+
if (li < 0) return 1;
|
|
75
|
+
if (ri < 0) return -1;
|
|
76
|
+
return li - ri;
|
|
77
|
+
});
|
|
78
|
+
const lines: string[] = [];
|
|
79
|
+
for (const [key, value] of entries) {
|
|
80
|
+
const safeKey = sanitizeToolResultText(key);
|
|
81
|
+
if (typeof value === "string") {
|
|
82
|
+
const safeValue = sanitizeToolResultText(value);
|
|
83
|
+
if (safeValue.includes("\n")) {
|
|
84
|
+
lines.push(`${safeKey}:`);
|
|
85
|
+
lines.push(...safeValue.split("\n").map((line) => ` ${line}`));
|
|
86
|
+
} else lines.push(`${safeKey}: ${safeValue}`);
|
|
87
|
+
} else {
|
|
88
|
+
const rendered = safeJson(value);
|
|
89
|
+
if (rendered.includes("\n")) {
|
|
90
|
+
lines.push(`${safeKey}:`);
|
|
91
|
+
lines.push(...rendered.split("\n").map((line) => ` ${line}`));
|
|
92
|
+
} else lines.push(`${safeKey}: ${rendered}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const rendered = lines.join("\n");
|
|
96
|
+
return rendered.length > maxChars ? `${rendered.slice(0, maxChars)}…` : rendered;
|
|
63
97
|
}
|
|
64
98
|
|
|
65
99
|
function hasExpandableDetail(text: string, args: unknown): boolean {
|
|
66
100
|
return countLines(text) > 1 || formatToolInputArgs(args).trim().length > 0;
|
|
67
101
|
}
|
|
68
102
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
private
|
|
103
|
+
export type ToolIoSection = "input" | "output";
|
|
104
|
+
|
|
105
|
+
/** Viewer-local adaptation of pi-cc's structured Input/Output tool card. */
|
|
106
|
+
export class ExpandedToolIoView implements Component {
|
|
107
|
+
private cachedWidth: number | undefined;
|
|
108
|
+
private cachedLines: string[] | undefined;
|
|
109
|
+
private lineSections: Array<ToolIoSection | null> = [];
|
|
110
|
+
private hoveredSection: ToolIoSection | null = null;
|
|
111
|
+
private showMoreRows: Partial<Record<ToolIoSection, number>> = {};
|
|
74
112
|
|
|
75
|
-
constructor(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
113
|
+
constructor(
|
|
114
|
+
private input: string,
|
|
115
|
+
private output: string,
|
|
116
|
+
private readonly isError: boolean,
|
|
117
|
+
private readonly maxOutputLines = DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines,
|
|
118
|
+
private readonly maxInputLines = DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines,
|
|
119
|
+
private readonly theme?: any,
|
|
120
|
+
) {}
|
|
121
|
+
|
|
122
|
+
getInputBody(): string { return this.input; }
|
|
123
|
+
getOutputBody(): string { return this.output.trim() ? this.output : "Done"; }
|
|
124
|
+
|
|
125
|
+
setHoveredSection(section: ToolIoSection | null): void {
|
|
126
|
+
if (this.hoveredSection === section) return;
|
|
127
|
+
this.hoveredSection = section;
|
|
128
|
+
this.invalidate();
|
|
79
129
|
}
|
|
80
130
|
|
|
131
|
+
sectionAtLine(line: number): ToolIoSection | null { return this.lineSections[line] ?? null; }
|
|
132
|
+
showMoreLine(section: ToolIoSection): number | undefined { return this.showMoreRows[section]; }
|
|
133
|
+
|
|
81
134
|
render(width: number): string[] {
|
|
82
135
|
const safeWidth = toolViewportWidth(width);
|
|
136
|
+
if (this.cachedLines && this.cachedWidth === safeWidth) return this.cachedLines;
|
|
137
|
+
const theme = this.theme;
|
|
138
|
+
const color = (name: string, value: string): string => typeof theme?.fg === "function" ? theme.fg(name, value) : value;
|
|
139
|
+
const bold = (value: string): string => typeof theme?.bold === "function" ? theme.bold(value) : value;
|
|
140
|
+
const rail = " │ ";
|
|
141
|
+
const contentWidth = Math.max(1, safeWidth - visibleWidth(rail));
|
|
142
|
+
const bodyColor = this.isError ? "error" : "toolOutput";
|
|
83
143
|
const rows: string[] = [];
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
144
|
+
this.lineSections = [];
|
|
145
|
+
this.showMoreRows = {};
|
|
146
|
+
const push = (line: string, section: ToolIoSection | null) => {
|
|
147
|
+
rows.push(truncateToWidth(line, safeWidth, ""));
|
|
148
|
+
this.lineSections.push(section);
|
|
149
|
+
};
|
|
150
|
+
const pushHeader = (corner: "├" | "└", title: string) => {
|
|
151
|
+
push(color("dim", ` ${corner} `) + color("accent", bold(title)), null);
|
|
152
|
+
};
|
|
153
|
+
const pushRail = (line: string, section: ToolIoSection, continued: boolean) => {
|
|
154
|
+
push(color("dim", continued ? rail : " ") + line, section);
|
|
155
|
+
};
|
|
156
|
+
const pushBody = (body: string, section: ToolIoSection, limit: number, continued: boolean, input: boolean) => {
|
|
157
|
+
const raw = body.replace(/\t/g, " ").replace(/\n+$/, "");
|
|
158
|
+
if (!raw.trim()) {
|
|
159
|
+
pushRail(color("dim", "(empty)"), section, continued);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const sources = raw.split("\n");
|
|
163
|
+
const wrapped: string[] = [];
|
|
164
|
+
const styleInput = (line: string): string => {
|
|
165
|
+
const match = line.match(/^([A-Za-z_][\w.-]*)(:\s*)(.*)$/);
|
|
166
|
+
return match
|
|
167
|
+
? color("dim", `${match[1]}${match[2]}`) + color("muted", match[3] ?? "")
|
|
168
|
+
: color("muted", line);
|
|
169
|
+
};
|
|
170
|
+
for (const source of sources) {
|
|
171
|
+
const styled = input ? styleInput(source) : color(bodyColor, source);
|
|
172
|
+
const lines = wrapTextWithAnsi(styled, contentWidth);
|
|
173
|
+
wrapped.push(...(lines.length ? lines : [styled]));
|
|
174
|
+
}
|
|
175
|
+
const truncated = sources.length > limit || wrapped.length > limit;
|
|
176
|
+
const visible = truncated ? wrapped.slice(0, limit) : wrapped;
|
|
177
|
+
for (const line of visible) pushRail(line, section, continued);
|
|
178
|
+
if (truncated && wrapped.length > visible.length) {
|
|
179
|
+
const hidden = wrapped.length - visible.length;
|
|
180
|
+
const hintColor = this.hoveredSection === section ? "text" : "dim";
|
|
181
|
+
pushRail(
|
|
182
|
+
color("dim", `… +${hidden} more lines`) + color("dim", " •") + color(hintColor, ` ${showMoreHintText()}`),
|
|
183
|
+
section,
|
|
184
|
+
continued,
|
|
185
|
+
);
|
|
186
|
+
this.showMoreRows[section] = rows.length - 1;
|
|
92
187
|
}
|
|
93
188
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
189
|
+
|
|
190
|
+
const hasInput = this.input.trim().length > 0;
|
|
191
|
+
if (hasInput) {
|
|
192
|
+
pushHeader("├", "Input");
|
|
193
|
+
pushBody(this.input, "input", Math.max(1, this.maxInputLines), true, true);
|
|
194
|
+
push(color("dim", " │"), null);
|
|
99
195
|
}
|
|
100
|
-
|
|
196
|
+
pushHeader("└", "Output");
|
|
197
|
+
pushBody(this.getOutputBody(), "output", Math.max(1, this.maxOutputLines), false, false);
|
|
198
|
+
this.cachedWidth = safeWidth;
|
|
199
|
+
this.cachedLines = rows;
|
|
200
|
+
return rows;
|
|
101
201
|
}
|
|
102
202
|
|
|
103
|
-
invalidate(): void {
|
|
203
|
+
invalidate(): void {
|
|
204
|
+
this.cachedWidth = undefined;
|
|
205
|
+
this.cachedLines = undefined;
|
|
206
|
+
}
|
|
104
207
|
}
|
|
105
208
|
|
|
106
209
|
function unavailableComponent(reason: string, theme: any): Component {
|
|
@@ -112,34 +215,24 @@ function unavailableComponent(reason: string, theme: any): Component {
|
|
|
112
215
|
};
|
|
113
216
|
}
|
|
114
217
|
|
|
115
|
-
function resultText(result: any): string {
|
|
116
|
-
return rawTextFromResult(result);
|
|
117
|
-
}
|
|
218
|
+
function resultText(result: any): string { return rawTextFromResult(result); }
|
|
118
219
|
|
|
119
220
|
function persistedFromDetails(details: any): PersistedDiff | undefined {
|
|
120
221
|
if (!details || typeof details !== "object") return undefined;
|
|
121
222
|
const persisted: PersistedDiff = {};
|
|
122
223
|
if (typeof details.diff === "string") persisted.diff = details.diff;
|
|
123
224
|
if (typeof details.patch === "string") persisted.patch = details.patch;
|
|
124
|
-
if (typeof details.diffUnavailableReason === "string")
|
|
125
|
-
persisted.diffUnavailableReason = details.diffUnavailableReason;
|
|
126
|
-
}
|
|
225
|
+
if (typeof details.diffUnavailableReason === "string") persisted.diffUnavailableReason = details.diffUnavailableReason;
|
|
127
226
|
return Object.keys(persisted).length ? persisted : undefined;
|
|
128
227
|
}
|
|
129
228
|
|
|
130
229
|
function viewerConfig(context: any): ViewerDiffConfig {
|
|
131
230
|
const candidate = context?.diffConfig;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
...candidate,
|
|
136
|
-
};
|
|
231
|
+
return candidate && typeof candidate === "object"
|
|
232
|
+
? { ...DEFAULT_TOOL_DISPLAY_CONFIG, ...candidate }
|
|
233
|
+
: DEFAULT_TOOL_DISPLAY_CONFIG;
|
|
137
234
|
}
|
|
138
235
|
|
|
139
|
-
/**
|
|
140
|
-
* Rich edit/write rendering for the conversation viewer. Durable details are
|
|
141
|
-
* passed through before any live/ephemeral context so history is deterministic.
|
|
142
|
-
*/
|
|
143
236
|
export function renderRichToolResult(
|
|
144
237
|
toolName: string,
|
|
145
238
|
result: any,
|
|
@@ -150,100 +243,67 @@ export function renderRichToolResult(
|
|
|
150
243
|
if (options?.isPartial || options?.isError || context?.isError) return undefined;
|
|
151
244
|
const expanded = options?.expanded === true || context?.expanded === true;
|
|
152
245
|
const args = context?.args ?? options?.args;
|
|
153
|
-
const filePath = args?.file_path ?? args?.path;
|
|
154
246
|
const details = result?.details;
|
|
155
247
|
const persistedDiff = context?.persistedDiff ?? persistedFromDetails(details);
|
|
156
248
|
const fileExistedBeforeWrite = typeof context?.fileExistedBeforeWrite === "boolean"
|
|
157
249
|
? context.fileExistedBeforeWrite
|
|
158
|
-
: typeof details?.fileExistedBeforeWrite === "boolean"
|
|
159
|
-
? details.fileExistedBeforeWrite
|
|
160
|
-
: undefined;
|
|
250
|
+
: typeof details?.fileExistedBeforeWrite === "boolean" ? details.fileExistedBeforeWrite : undefined;
|
|
161
251
|
|
|
162
252
|
if (toolName === "edit") {
|
|
163
|
-
return renderEditDiffResult(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
theme,
|
|
168
|
-
resultText(result),
|
|
169
|
-
);
|
|
253
|
+
return renderEditDiffResult(details, {
|
|
254
|
+
expanded, filePath: args?.file_path ?? args?.path, persistedDiff,
|
|
255
|
+
isHovered: options?.isHovered, invalidate: context?.invalidate,
|
|
256
|
+
}, viewerConfig(context), theme, resultText(result));
|
|
170
257
|
}
|
|
171
258
|
if (toolName !== "write") return undefined;
|
|
172
259
|
if (persistedDiff?.diffUnavailableReason && !persistedDiff.diff && !persistedDiff.patch) {
|
|
173
260
|
return unavailableComponent(persistedDiff.diffUnavailableReason, theme);
|
|
174
261
|
}
|
|
175
|
-
|
|
176
262
|
const content = typeof args?.content === "string" ? args.content : undefined;
|
|
177
|
-
if (
|
|
263
|
+
if (typeof content !== "string" && !persistedDiff?.diff && !persistedDiff?.patch) {
|
|
178
264
|
return unavailableComponent("execution metadata is unavailable", theme);
|
|
179
265
|
}
|
|
180
|
-
return renderWriteDiffResult(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
invalidate: context?.invalidate,
|
|
190
|
-
},
|
|
191
|
-
viewerConfig(context),
|
|
192
|
-
theme,
|
|
193
|
-
resultText(result),
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function renderCallSummary(toolName: string, args: any, theme: any): string {
|
|
198
|
-
const title = toolName.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ");
|
|
199
|
-
const value = args?.path ?? args?.file_path ?? args?.command ?? args?.query ?? args?.name;
|
|
200
|
-
const summary = value === undefined ? title : `${title} ${oneLine(value)}`;
|
|
201
|
-
return theme.fg("toolTitle", summary);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function settledIcon(context: any): string {
|
|
205
|
-
if (context?.isError) return "✗";
|
|
206
|
-
if (context?.isPartial || context?.executionStarted) return "●";
|
|
207
|
-
return "✓";
|
|
266
|
+
return renderWriteDiffResult(content, {
|
|
267
|
+
expanded,
|
|
268
|
+
filePath: args?.file_path ?? args?.path,
|
|
269
|
+
persistedDiff,
|
|
270
|
+
previousContent: context?.previousContent,
|
|
271
|
+
fileExistedBeforeWrite,
|
|
272
|
+
isHovered: options?.isHovered,
|
|
273
|
+
invalidate: context?.invalidate,
|
|
274
|
+
}, viewerConfig(context), theme, resultText(result));
|
|
208
275
|
}
|
|
209
276
|
|
|
210
277
|
function renderFallbackResult(result: any, options: any, theme: any, context: any): Component {
|
|
211
278
|
const error = options?.isError || context?.isError;
|
|
212
279
|
const expanded = options?.expanded === true || context?.expanded === true;
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
280
|
+
const maxChars = Number.isFinite(context?.maxChars) ? Math.max(0, Math.floor(context.maxChars)) : 16_384;
|
|
281
|
+
const text = textFromResult(result, expanded, maxChars);
|
|
282
|
+
const input = formatToolInputArgs(context?.args, maxChars);
|
|
283
|
+
if (expanded && (text.trim() || input.trim())) {
|
|
284
|
+
const maxLines = Number.isFinite(context?.diffConfig?.expandedPreviewMaxLines)
|
|
285
|
+
? Math.max(1, Math.floor(context.diffConfig.expandedPreviewMaxLines))
|
|
286
|
+
: DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines;
|
|
287
|
+
return new ExpandedToolIoView(input, text, Boolean(error), maxLines, maxLines, theme);
|
|
216
288
|
}
|
|
217
|
-
const
|
|
218
|
-
const count = lines.length;
|
|
289
|
+
const count = text ? text.split("\n").length : 0;
|
|
219
290
|
const summary = error ? oneLine(text) || "Failed" : count ? `${count} ${count === 1 ? "line" : "lines"} returned` : "Done";
|
|
220
291
|
const expandable = !expanded && hasExpandableDetail(text, context?.args);
|
|
221
292
|
return {
|
|
222
293
|
render(width: number): string[] {
|
|
223
294
|
const hovered = options?.isHovered?.() ?? context?.isHovered?.() ?? false;
|
|
224
|
-
const
|
|
225
|
-
const hint = expandable ? ` • ${clickLabel}` : "";
|
|
226
|
-
const color = error ? "error" : "muted";
|
|
295
|
+
const hint = expandable ? ` • ${showMoreHintText()}` : "";
|
|
227
296
|
const line = expandable && hovered
|
|
228
|
-
? theme.fg(
|
|
229
|
-
: theme.fg(
|
|
297
|
+
? theme.fg(error ? "error" : "muted", ` ↳ ${summary} • `) + theme.fg("text", showMoreHintText())
|
|
298
|
+
: theme.fg(error ? "error" : "muted", ` ↳ ${summary}${hint}`);
|
|
230
299
|
return [truncateToWidth(line, toolViewportWidth(width), "")];
|
|
231
300
|
},
|
|
232
301
|
invalidate() {},
|
|
233
302
|
};
|
|
234
303
|
}
|
|
235
304
|
|
|
236
|
-
export function createViewerCcstyleResult(
|
|
237
|
-
toolName
|
|
238
|
-
result: any,
|
|
239
|
-
options: any,
|
|
240
|
-
theme: any,
|
|
241
|
-
context: any,
|
|
242
|
-
): Component {
|
|
243
|
-
return (
|
|
244
|
-
renderRichToolResult(toolName, result, options, theme, context) ??
|
|
245
|
-
renderFallbackResult(result, options, theme, context)
|
|
246
|
-
);
|
|
305
|
+
export function createViewerCcstyleResult(toolName: string, result: any, options: any, theme: any, context: any): Component {
|
|
306
|
+
return renderRichToolResult(toolName, result, options, theme, context) ?? renderFallbackResult(result, options, theme, context);
|
|
247
307
|
}
|
|
248
308
|
|
|
249
|
-
export {
|
|
309
|
+
export type { DisplayConfigInput };
|