@esso0428/pi-subagents 0.17.6 → 0.17.7
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 +9 -0
- package/CONTRIBUTING.md +4 -0
- package/dist/abortable.d.ts +13 -0
- package/dist/abortable.d.ts.map +1 -0
- package/dist/abortable.js +43 -0
- package/dist/abortable.js.map +1 -0
- package/dist/agent-color.d.ts +36 -0
- package/dist/agent-color.d.ts.map +1 -0
- package/dist/agent-color.js +124 -0
- package/dist/agent-color.js.map +1 -0
- package/dist/agent-file-toggle.d.ts +126 -0
- package/dist/agent-file-toggle.d.ts.map +1 -0
- package/dist/agent-file-toggle.js +259 -0
- package/dist/agent-file-toggle.js.map +1 -0
- package/dist/agent-history.d.ts +4 -0
- package/dist/agent-history.d.ts.map +1 -1
- package/dist/agent-history.js +47 -1
- package/dist/agent-history.js.map +1 -1
- package/dist/agent-manager.d.ts +370 -56
- package/dist/agent-manager.d.ts.map +1 -1
- package/dist/agent-manager.js +1123 -409
- package/dist/agent-manager.js.map +1 -1
- package/dist/agent-runner.d.ts +100 -10
- package/dist/agent-runner.d.ts.map +1 -1
- package/dist/agent-runner.js +166 -21
- package/dist/agent-runner.js.map +1 -1
- package/dist/agent-types.d.ts +57 -5
- package/dist/agent-types.d.ts.map +1 -1
- package/dist/agent-types.js +164 -32
- package/dist/agent-types.js.map +1 -1
- package/dist/child-context.d.ts +3 -0
- package/dist/child-context.d.ts.map +1 -0
- package/dist/child-context.js +13 -0
- package/dist/child-context.js.map +1 -0
- package/dist/cross-extension-rpc.d.ts +23 -3
- package/dist/cross-extension-rpc.d.ts.map +1 -1
- package/dist/cross-extension-rpc.js +79 -17
- package/dist/cross-extension-rpc.js.map +1 -1
- package/dist/custom-agents.d.ts +38 -1
- package/dist/custom-agents.d.ts.map +1 -1
- package/dist/custom-agents.js +164 -12
- package/dist/custom-agents.js.map +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1908 -495
- package/dist/index.js.map +1 -1
- package/dist/invocation-config.d.ts +87 -2
- package/dist/invocation-config.d.ts.map +1 -1
- package/dist/invocation-config.js +71 -3
- package/dist/invocation-config.js.map +1 -1
- package/dist/mention-clone.d.ts +88 -0
- package/dist/mention-clone.d.ts.map +1 -0
- package/dist/mention-clone.js +154 -0
- package/dist/mention-clone.js.map +1 -0
- package/dist/mention.d.ts +82 -0
- package/dist/mention.d.ts.map +1 -0
- package/dist/mention.js +132 -0
- package/dist/mention.js.map +1 -0
- package/dist/model-resolver.d.ts +17 -0
- package/dist/model-resolver.d.ts.map +1 -1
- package/dist/model-resolver.js +15 -0
- package/dist/model-resolver.js.map +1 -1
- package/dist/model-scope.d.ts +50 -0
- package/dist/model-scope.d.ts.map +1 -0
- package/dist/model-scope.js +49 -0
- package/dist/model-scope.js.map +1 -0
- package/dist/nested-tools.d.ts +57 -0
- package/dist/nested-tools.d.ts.map +1 -0
- package/dist/nested-tools.js +301 -0
- package/dist/nested-tools.js.map +1 -0
- package/dist/output-file.d.ts +22 -3
- package/dist/output-file.d.ts.map +1 -1
- package/dist/output-file.js +58 -7
- package/dist/output-file.js.map +1 -1
- package/dist/prompts.d.ts +23 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +20 -2
- package/dist/prompts.js.map +1 -1
- package/dist/schedule.d.ts.map +1 -1
- package/dist/schedule.js +36 -15
- package/dist/schedule.js.map +1 -1
- package/dist/settings.d.ts +228 -2
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +94 -0
- package/dist/settings.js.map +1 -1
- package/dist/status-note.d.ts +49 -1
- package/dist/status-note.d.ts.map +1 -1
- package/dist/status-note.js +62 -1
- package/dist/status-note.js.map +1 -1
- package/dist/structured-output.d.ts +62 -0
- package/dist/structured-output.d.ts.map +1 -0
- package/dist/structured-output.js +113 -0
- package/dist/structured-output.js.map +1 -0
- package/dist/types.d.ts +176 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/agent-mention.d.ts +83 -0
- package/dist/ui/agent-mention.d.ts.map +1 -0
- package/dist/ui/agent-mention.js +188 -0
- package/dist/ui/agent-mention.js.map +1 -0
- package/dist/ui/agent-widget.d.ts +96 -75
- package/dist/ui/agent-widget.d.ts.map +1 -1
- package/dist/ui/agent-widget.js +397 -420
- package/dist/ui/agent-widget.js.map +1 -1
- package/dist/ui/conversation-blocks.d.ts.map +1 -1
- package/dist/ui/conversation-blocks.js +6 -0
- package/dist/ui/conversation-blocks.js.map +1 -1
- package/dist/ui/conversation-timeline.d.ts +10 -2
- package/dist/ui/conversation-timeline.d.ts.map +1 -1
- package/dist/ui/conversation-timeline.js +130 -23
- package/dist/ui/conversation-timeline.js.map +1 -1
- package/dist/ui/conversation-viewer.d.ts +15 -5
- package/dist/ui/conversation-viewer.d.ts.map +1 -1
- package/dist/ui/conversation-viewer.js +202 -50
- package/dist/ui/conversation-viewer.js.map +1 -1
- package/dist/ui/fleet-list.d.ts +198 -0
- package/dist/ui/fleet-list.d.ts.map +1 -0
- package/dist/ui/fleet-list.js +487 -0
- package/dist/ui/fleet-list.js.map +1 -0
- package/dist/ui/schedule-menu.d.ts.map +1 -1
- package/dist/ui/schedule-menu.js +6 -7
- package/dist/ui/schedule-menu.js.map +1 -1
- package/dist/ui/select-item.d.ts +28 -0
- package/dist/ui/select-item.d.ts.map +1 -0
- package/dist/ui/select-item.js +35 -0
- package/dist/ui/select-item.js.map +1 -0
- package/dist/ui/workflow-card.d.ts +176 -0
- package/dist/ui/workflow-card.d.ts.map +1 -0
- package/dist/ui/workflow-card.js +333 -0
- package/dist/ui/workflow-card.js.map +1 -0
- package/dist/ui/workflow-dialog.d.ts +306 -0
- package/dist/ui/workflow-dialog.d.ts.map +1 -0
- package/dist/ui/workflow-dialog.js +844 -0
- package/dist/ui/workflow-dialog.js.map +1 -0
- package/dist/ui/workflow-menu.d.ts +61 -0
- package/dist/ui/workflow-menu.d.ts.map +1 -0
- package/dist/ui/workflow-menu.js +148 -0
- package/dist/ui/workflow-menu.js.map +1 -0
- package/dist/usage.d.ts +86 -1
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +72 -1
- package/dist/usage.js.map +1 -1
- package/dist/workflow/collisions.d.ts +96 -0
- package/dist/workflow/collisions.d.ts.map +1 -0
- package/dist/workflow/collisions.js +89 -0
- package/dist/workflow/collisions.js.map +1 -0
- package/dist/workflow/entry.d.ts +33 -0
- package/dist/workflow/entry.d.ts.map +1 -0
- package/dist/workflow/entry.js +30 -0
- package/dist/workflow/entry.js.map +1 -0
- package/dist/workflow/host.d.ts +63 -0
- package/dist/workflow/host.d.ts.map +1 -0
- package/dist/workflow/host.js +363 -0
- package/dist/workflow/host.js.map +1 -0
- package/dist/workflow/journal.d.ts +98 -0
- package/dist/workflow/journal.d.ts.map +1 -0
- package/dist/workflow/journal.js +121 -0
- package/dist/workflow/journal.js.map +1 -0
- package/dist/workflow/json-schema.d.ts +52 -0
- package/dist/workflow/json-schema.d.ts.map +1 -0
- package/dist/workflow/json-schema.js +112 -0
- package/dist/workflow/json-schema.js.map +1 -0
- package/dist/workflow/meta.d.ts +68 -0
- package/dist/workflow/meta.d.ts.map +1 -0
- package/dist/workflow/meta.js +318 -0
- package/dist/workflow/meta.js.map +1 -0
- package/dist/workflow/progress.d.ts +225 -0
- package/dist/workflow/progress.d.ts.map +1 -0
- package/dist/workflow/progress.js +362 -0
- package/dist/workflow/progress.js.map +1 -0
- package/dist/workflow/runtime.d.ts +335 -0
- package/dist/workflow/runtime.d.ts.map +1 -0
- package/dist/workflow/runtime.js +831 -0
- package/dist/workflow/runtime.js.map +1 -0
- package/dist/workflow/saved.d.ts +91 -0
- package/dist/workflow/saved.d.ts.map +1 -0
- package/dist/workflow/saved.js +204 -0
- package/dist/workflow/saved.js.map +1 -0
- package/dist/workflow/task.d.ts +137 -0
- package/dist/workflow/task.d.ts.map +1 -0
- package/dist/workflow/task.js +208 -0
- package/dist/workflow/task.js.map +1 -0
- package/dist/workflow/tool-description.d.ts +39 -0
- package/dist/workflow/tool-description.d.ts.map +1 -0
- package/dist/workflow/tool-description.js +200 -0
- package/dist/workflow/tool-description.js.map +1 -0
- package/dist/workflow/worker-source.d.ts +48 -0
- package/dist/workflow/worker-source.d.ts.map +1 -0
- package/dist/workflow/worker-source.js +779 -0
- package/dist/workflow/worker-source.js.map +1 -0
- package/dist/worktree.d.ts +10 -3
- package/dist/worktree.d.ts.map +1 -1
- package/dist/worktree.js +58 -54
- package/dist/worktree.js.map +1 -1
- package/dist/xml.d.ts +11 -0
- package/dist/xml.d.ts.map +1 -0
- package/dist/xml.js +13 -0
- package/dist/xml.js.map +1 -0
- package/docs/rpc.md +183 -0
- package/docs/superpowers/plans/2026-09-30-upstream-event-workflow-partial-history.md +195 -0
- package/docs/superpowers/specs/2026-09-30-upstream-event-workflow-partial-history-design.md +49 -0
- package/docs/workflows.md +437 -0
- package/examples/agent-tool-description.md +7 -7
- package/examples/workflows/compose.js +51 -0
- package/examples/workflows/fan-out-audit.js +47 -0
- package/examples/workflows/gated-fix.js +60 -0
- package/examples/workflows/lib/count-child.js +27 -0
- package/examples/workflows/review-panel.js +63 -0
- package/examples/workflows/structured-findings.js +78 -0
- package/package.json +1 -1
- package/src/abortable.ts +43 -0
- package/src/agent-color.ts +161 -0
- package/src/agent-file-toggle.ts +269 -0
- package/src/agent-history.ts +54 -2
- package/src/agent-manager.ts +1263 -402
- package/src/agent-runner.ts +251 -27
- package/src/agent-types.ts +188 -32
- package/src/child-context.ts +15 -0
- package/src/cross-extension-rpc.ts +96 -20
- package/src/custom-agents.ts +170 -13
- package/src/index.ts +2024 -537
- package/src/invocation-config.ts +118 -3
- package/src/mention-clone.ts +196 -0
- package/src/mention.ts +141 -0
- package/src/model-resolver.ts +18 -0
- package/src/model-scope.ts +70 -0
- package/src/nested-tools.ts +424 -0
- package/src/output-file.ts +61 -6
- package/src/prompts.ts +45 -2
- package/src/schedule.ts +35 -14
- package/src/settings.ts +312 -2
- package/src/status-note.ts +66 -1
- package/src/structured-output.ts +130 -0
- package/src/types.ts +177 -10
- package/src/ui/agent-mention.ts +216 -0
- package/src/ui/agent-widget.ts +389 -441
- package/src/ui/conversation-blocks.ts +6 -0
- package/src/ui/conversation-timeline.ts +139 -25
- package/src/ui/conversation-viewer.ts +212 -48
- package/src/ui/fleet-list.ts +558 -0
- package/src/ui/schedule-menu.ts +9 -8
- package/src/ui/select-item.ts +45 -0
- package/src/ui/workflow-card.ts +470 -0
- package/src/ui/workflow-dialog.ts +1115 -0
- package/src/ui/workflow-menu.ts +193 -0
- package/src/usage.ts +109 -2
- package/src/workflow/collisions.ts +123 -0
- package/src/workflow/entry.ts +47 -0
- package/src/workflow/host.ts +403 -0
- package/src/workflow/journal.ts +164 -0
- package/src/workflow/json-schema.ts +128 -0
- package/src/workflow/meta.ts +325 -0
- package/src/workflow/progress.ts +550 -0
- package/src/workflow/runtime.ts +1219 -0
- package/src/workflow/saved.ts +217 -0
- package/src/workflow/task.ts +302 -0
- package/src/workflow/tool-description.ts +200 -0
- package/src/workflow/worker-source.ts +781 -0
- package/src/worktree.ts +69 -55
- package/src/xml.ts +13 -0
- package/vitest.config.ts +0 -18
|
@@ -251,6 +251,10 @@ function bashBlock(
|
|
|
251
251
|
const body = command ? `$ ${command}${output ? `\n${output}` : ""}` : output;
|
|
252
252
|
const toolLine = `· bash → ${command || "(no command)"}`;
|
|
253
253
|
const fullText = bound(body, maxChars);
|
|
254
|
+
const result: ConversationToolResultSnapshot = {
|
|
255
|
+
toolName: "bash",
|
|
256
|
+
content: [{ type: "text", text: body }],
|
|
257
|
+
};
|
|
254
258
|
return {
|
|
255
259
|
id,
|
|
256
260
|
kind: "tool",
|
|
@@ -261,6 +265,8 @@ function bashBlock(
|
|
|
261
265
|
fullText,
|
|
262
266
|
toolLine,
|
|
263
267
|
toolName: "bash",
|
|
268
|
+
toolResult: result,
|
|
269
|
+
result,
|
|
264
270
|
};
|
|
265
271
|
}
|
|
266
272
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as CodingAgent from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { getMarkdownTheme } from "@earendil-works/pi-coding-agent";
|
|
3
|
+
import type { MarkdownOptions, MarkdownTheme } from "@earendil-works/pi-tui";
|
|
3
4
|
import {
|
|
4
5
|
type Component,
|
|
5
6
|
Markdown,
|
|
6
|
-
Text,
|
|
7
7
|
type TUI,
|
|
8
8
|
type TuiMouseEvent,
|
|
9
9
|
truncateToWidth,
|
|
10
|
+
wrapTextWithAnsi,
|
|
10
11
|
} from "@earendil-works/pi-tui";
|
|
11
|
-
import type { AgentRecord } from "../types.js";
|
|
12
|
+
import type { AgentRecord, ViewerMarkdownMode } from "../types.js";
|
|
12
13
|
import type { Theme } from "./agent-widget.js";
|
|
13
14
|
import { showMoreHintText } from "./ccstyle/diff/render-utils.js";
|
|
14
15
|
import {
|
|
@@ -73,6 +74,7 @@ export interface ConversationTimelineChange {
|
|
|
73
74
|
export interface ConversationTimelineOptions {
|
|
74
75
|
cwd?: string;
|
|
75
76
|
record?: AgentRecord;
|
|
77
|
+
markdownMode?: () => ViewerMarkdownMode;
|
|
76
78
|
onChange?: (change: ConversationTimelineChange) => void;
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -80,12 +82,60 @@ function safeWidth(width: number): number {
|
|
|
80
82
|
return Math.max(1, Math.floor(Number.isFinite(width) ? width : 1));
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
const MARKDOWN_OPTIONS: MarkdownOptions = {
|
|
86
|
+
preserveOrderedListMarkers: true,
|
|
87
|
+
preserveBackslashEscapes: true,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
function fallbackMarkdownTheme(theme: Theme): MarkdownTheme {
|
|
91
|
+
const sgr = (on: number, off: number) => (text: string) => `\x1b[${on}m${text}\x1b[${off}m`;
|
|
92
|
+
return {
|
|
93
|
+
heading: text => theme.bold(theme.fg("accent", text)),
|
|
94
|
+
link: text => theme.fg("accent", text),
|
|
95
|
+
linkUrl: text => theme.fg("muted", text),
|
|
96
|
+
code: text => theme.fg("muted", text),
|
|
97
|
+
codeBlock: text => theme.fg("muted", text),
|
|
98
|
+
codeBlockBorder: text => theme.fg("dim", text),
|
|
99
|
+
quote: text => theme.fg("muted", text),
|
|
100
|
+
quoteBorder: text => theme.fg("dim", text),
|
|
101
|
+
hr: text => theme.fg("dim", text),
|
|
102
|
+
listBullet: text => theme.fg("accent", text),
|
|
103
|
+
bold: text => theme.bold(text),
|
|
104
|
+
italic: sgr(3, 23),
|
|
105
|
+
underline: sgr(4, 24),
|
|
106
|
+
strikethrough: sgr(9, 29),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function resolveMarkdownTheme(theme: Theme): MarkdownTheme {
|
|
111
|
+
try {
|
|
112
|
+
const markdownTheme = getMarkdownTheme();
|
|
113
|
+
markdownTheme.heading("probe");
|
|
114
|
+
return markdownTheme;
|
|
115
|
+
} catch {
|
|
116
|
+
return fallbackMarkdownTheme(theme);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
83
120
|
function resultContent(result: ConversationToolResultSnapshot): Array<Record<string, unknown>> {
|
|
84
121
|
if (Array.isArray(result.content)) return result.content as Array<Record<string, unknown>>;
|
|
85
122
|
if (typeof result.content === "string") return [{ type: "text", text: result.content }];
|
|
86
123
|
return [];
|
|
87
124
|
}
|
|
88
125
|
|
|
126
|
+
const RESULT_MAX_CHARS = 16_000;
|
|
127
|
+
|
|
128
|
+
function humanCount(n: number): string {
|
|
129
|
+
if (n < 1_000) return `${n}`;
|
|
130
|
+
const thousands = n < 999_950;
|
|
131
|
+
const value = thousands ? n / 1_000 : n / 1_000_000;
|
|
132
|
+
return `${value.toFixed(1).replace(/\.0$/, "")}${thousands ? "k" : "M"}`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function truncationNote(elided: number): string {
|
|
136
|
+
return `... (truncated, ${humanCount(elided)} more character${elided === 1 ? "" : "s"})`;
|
|
137
|
+
}
|
|
138
|
+
|
|
89
139
|
function fallbackToolLines(block: ConversationBlock, width: number, expanded = false, hovered = false, theme?: Theme): string[] {
|
|
90
140
|
const summary = block.toolLine || block.fullText || block.toolName || "tool";
|
|
91
141
|
const output = block.toolResult
|
|
@@ -173,6 +223,8 @@ export class ConversationTimeline implements Component {
|
|
|
173
223
|
private lastClickedToolCallId: string | undefined;
|
|
174
224
|
private lastClickedPoint: { x: number; y: number } | undefined;
|
|
175
225
|
private toolComponents = new Map<string, Component & { handleMouse?: (event: TuiMouseEvent) => unknown }>();
|
|
226
|
+
private markdownCache = new WeakMap<object, { markdown: Markdown; text: string; failed?: boolean }>();
|
|
227
|
+
private lastWidth = 0;
|
|
176
228
|
private snapshot: ConversationTimelineSnapshot = {
|
|
177
229
|
lines: [],
|
|
178
230
|
messageStarts: [],
|
|
@@ -181,7 +233,6 @@ export class ConversationTimeline implements Component {
|
|
|
181
233
|
blockSpans: [],
|
|
182
234
|
toolSpans: [],
|
|
183
235
|
};
|
|
184
|
-
private lastWidth = 0;
|
|
185
236
|
|
|
186
237
|
constructor(
|
|
187
238
|
private readonly tui: TUI,
|
|
@@ -223,6 +274,11 @@ export class ConversationTimeline implements Component {
|
|
|
223
274
|
return this.showTools;
|
|
224
275
|
}
|
|
225
276
|
|
|
277
|
+
setMarkdownMode(mode: () => ViewerMarkdownMode): void {
|
|
278
|
+
this.options.markdownMode = mode;
|
|
279
|
+
this.invalidate();
|
|
280
|
+
}
|
|
281
|
+
|
|
226
282
|
setFocusedToolCallId(id: string | undefined): void {
|
|
227
283
|
// Focus changes are view state. The rendered rows do not change, so keep
|
|
228
284
|
// the snapshot and its Markdown/tool output cache intact.
|
|
@@ -267,8 +323,6 @@ export class ConversationTimeline implements Component {
|
|
|
267
323
|
|
|
268
324
|
render(width: number): string[] {
|
|
269
325
|
const requestedWidth = safeWidth(width);
|
|
270
|
-
if (this.lastWidth === requestedWidth) return this.snapshot.lines.map((line) => line.text);
|
|
271
|
-
|
|
272
326
|
const lines: TimelineRenderLine[] = [];
|
|
273
327
|
const messageStarts: number[] = [];
|
|
274
328
|
const messageBlocks: ConversationBlock[] = [];
|
|
@@ -323,26 +377,12 @@ export class ConversationTimeline implements Component {
|
|
|
323
377
|
continue;
|
|
324
378
|
}
|
|
325
379
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
});
|
|
333
|
-
for (const line of markdown.render(requestedWidth)) {
|
|
334
|
-
lines.push({ text: truncateToWidth(line, requestedWidth), plain: stripAnsi(line), blockIndex, railable: true });
|
|
335
|
-
}
|
|
336
|
-
} catch {
|
|
337
|
-
try {
|
|
338
|
-
for (const line of new Text(block.markdown || "∅").render(requestedWidth)) {
|
|
339
|
-
lines.push({ text: truncateToWidth(line, requestedWidth), plain: stripAnsi(line), blockIndex, railable: true });
|
|
340
|
-
}
|
|
341
|
-
} catch {
|
|
342
|
-
for (const line of (block.markdown || "∅").split("\n")) {
|
|
343
|
-
lines.push({ text: truncateToWidth(line, requestedWidth), plain: line, blockIndex, railable: true });
|
|
344
|
-
}
|
|
345
|
-
}
|
|
380
|
+
const mode = this.options.markdownMode?.() ?? "assistant";
|
|
381
|
+
const rendered = mode === "off"
|
|
382
|
+
? this.renderLiteralText(block.markdown || "∅", requestedWidth)
|
|
383
|
+
: this.renderMarkdown(block, block.markdown || "∅", requestedWidth, false);
|
|
384
|
+
for (const line of rendered) {
|
|
385
|
+
lines.push({ text: truncateToWidth(line, requestedWidth), plain: stripAnsi(line), blockIndex, railable: true });
|
|
346
386
|
}
|
|
347
387
|
blockSpans.push({ blockIndex: snapshotBlockIndex, startLine: blockStartLine, height: lines.length - blockStartLine });
|
|
348
388
|
}
|
|
@@ -353,6 +393,13 @@ export class ConversationTimeline implements Component {
|
|
|
353
393
|
}
|
|
354
394
|
|
|
355
395
|
private renderToolLines(block: ConversationBlock, width: number): { rendered: string[]; hintLine: number } {
|
|
396
|
+
const mode = this.options.markdownMode?.() ?? "assistant";
|
|
397
|
+
if (block.toolResult && (mode === "all" || block.toolArguments === undefined)) {
|
|
398
|
+
return {
|
|
399
|
+
rendered: mode === "all" ? this.renderToolMarkdownLines(block, width) : this.renderToolRawLines(block, width),
|
|
400
|
+
hintLine: -1,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
356
403
|
const id = block.toolCallId;
|
|
357
404
|
let component: (Component & { handleMouse?: (event: TuiMouseEvent) => unknown }) | undefined;
|
|
358
405
|
if (id) {
|
|
@@ -399,6 +446,73 @@ export class ConversationTimeline implements Component {
|
|
|
399
446
|
return { rendered, hintLine };
|
|
400
447
|
}
|
|
401
448
|
|
|
449
|
+
private toolOutputText(block: ConversationBlock): string {
|
|
450
|
+
const output = block.toolResult ? resultContent(block.toolResult)
|
|
451
|
+
.filter(item => item.type === "text" && typeof item.text === "string")
|
|
452
|
+
.map(item => item.text as string)
|
|
453
|
+
.join("\n") : "";
|
|
454
|
+
return output || block.fullText || block.toolLine || "(no output)";
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
private renderToolRawLines(block: ConversationBlock, width: number): string[] {
|
|
458
|
+
const source = this.toolOutputText(block);
|
|
459
|
+
const capped = source.length > RESULT_MAX_CHARS
|
|
460
|
+
? `${source.slice(0, RESULT_MAX_CHARS)}\n${truncationNote(source.length - RESULT_MAX_CHARS)}`
|
|
461
|
+
: source;
|
|
462
|
+
try {
|
|
463
|
+
return wrapTextWithAnsi(capped, width).map(line => this.theme.fg("dim", truncateToWidth(line, width)));
|
|
464
|
+
} catch {
|
|
465
|
+
return capped.split("\n").map(line => this.theme.fg("dim", truncateToWidth(line, width)));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
private renderToolMarkdownLines(block: ConversationBlock, width: number): string[] {
|
|
470
|
+
const source = this.toolOutputText(block);
|
|
471
|
+
if (source.length <= RESULT_MAX_CHARS) return this.renderMarkdown(block, source, width, true);
|
|
472
|
+
const prefix = source.slice(0, RESULT_MAX_CHARS);
|
|
473
|
+
return [
|
|
474
|
+
...this.renderMarkdown(block, prefix, width, true),
|
|
475
|
+
this.theme.fg("dim", truncationNote(source.length - RESULT_MAX_CHARS)),
|
|
476
|
+
];
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
private renderMarkdown(block: ConversationBlock, text: string, width: number, dim: boolean): string[] {
|
|
480
|
+
let entry = this.markdownCache.get(block);
|
|
481
|
+
if (!entry) {
|
|
482
|
+
const defaultStyle = {
|
|
483
|
+
color: (value: string) => this.theme.fg(
|
|
484
|
+
dim ? "dim" : block.role === "user" ? "userMessageText" : block.role === "meta" ? "muted" : "text",
|
|
485
|
+
value,
|
|
486
|
+
),
|
|
487
|
+
};
|
|
488
|
+
entry = {
|
|
489
|
+
markdown: new Markdown(text, 0, 0, resolveMarkdownTheme(this.theme), defaultStyle, MARKDOWN_OPTIONS),
|
|
490
|
+
text,
|
|
491
|
+
};
|
|
492
|
+
this.markdownCache.set(block, entry);
|
|
493
|
+
} else if (entry.text !== text) {
|
|
494
|
+
const shouldRetry = !text.startsWith(entry.text);
|
|
495
|
+
entry.markdown.setText(text);
|
|
496
|
+
entry.text = text;
|
|
497
|
+
if (shouldRetry) entry.failed = false;
|
|
498
|
+
}
|
|
499
|
+
if (entry.failed) return dim ? this.renderToolRawLines(block, width) : this.renderLiteralText(text, width);
|
|
500
|
+
try {
|
|
501
|
+
return entry.markdown.render(width).map(line => truncateToWidth(line, width));
|
|
502
|
+
} catch {
|
|
503
|
+
entry.failed = true;
|
|
504
|
+
return dim ? this.renderToolRawLines(block, width) : this.renderLiteralText(text, width);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
private renderLiteralText(text: string, width: number): string[] {
|
|
509
|
+
try {
|
|
510
|
+
return wrapTextWithAnsi(text || "∅", width).map(line => truncateToWidth(line, width));
|
|
511
|
+
} catch {
|
|
512
|
+
return text.split("\n").map(line => truncateToWidth(line, width));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
402
516
|
/**
|
|
403
517
|
* Hover only changes styling in a tool card. Re-render those rows in place
|
|
404
518
|
* and leave the Markdown rows and their spans untouched.
|