@linxiraos/pi-tui 1.2.1 → 1.3.1

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.
Files changed (280) hide show
  1. package/CHANGELOG.md +245 -224
  2. package/README.md +36 -0
  3. package/THIRD-PARTY-NOTICES.txt +55 -5
  4. package/dist/types/app-keybindings.d.ts +18 -8
  5. package/dist/types/apps/git/diff-pane.d.ts +5 -0
  6. package/dist/types/apps/git/git-tui.d.ts +16 -2
  7. package/dist/types/apps/git/state.d.ts +11 -0
  8. package/dist/types/autocomplete.d.ts +2 -0
  9. package/dist/types/charts/chart-svg.d.ts +7 -13
  10. package/dist/types/chat/advisor-message.d.ts +4 -1
  11. package/dist/types/chat/assistant-message.d.ts +9 -4
  12. package/dist/types/chat/figure-markdown.d.ts +7 -2
  13. package/dist/types/chat/messages.d.ts +3 -1
  14. package/dist/types/chat/read-tool-group.d.ts +2 -2
  15. package/dist/types/chat/table-chart.d.ts +11 -15
  16. package/dist/types/chat/tool-execution.d.ts +32 -20
  17. package/dist/types/chat/user-message.d.ts +3 -2
  18. package/dist/types/chrome/countdown-timer.d.ts +3 -2
  19. package/dist/types/chrome/diff.d.ts +2 -3
  20. package/dist/types/chrome/status-notice.d.ts +2 -0
  21. package/dist/types/chrome/transcript-container.d.ts +2 -0
  22. package/dist/types/components/image.d.ts +2 -0
  23. package/dist/types/components/markdown.d.ts +49 -3
  24. package/dist/types/components/text.d.ts +2 -0
  25. package/dist/types/debug-server.d.ts +2 -0
  26. package/dist/types/keybinding-matchers.d.ts +6 -0
  27. package/dist/types/multiplexers/tmux.d.ts +1 -0
  28. package/dist/types/multiplexers/types.d.ts +6 -0
  29. package/dist/types/native/backend.d.ts +5 -4
  30. package/dist/types/native/blobs.d.ts +24 -12
  31. package/dist/types/overlays/agent-hub-projection.d.ts +10 -5
  32. package/dist/types/overlays/annotation-overlay.d.ts +19 -0
  33. package/dist/types/overlays/approval-dialog.d.ts +79 -0
  34. package/dist/types/overlays/ask-dialog.d.ts +11 -6
  35. package/dist/types/overlays/btw-history-panel.d.ts +2 -6
  36. package/dist/types/overlays/hook-editor.d.ts +7 -2
  37. package/dist/types/overlays/hook-input.d.ts +12 -4
  38. package/dist/types/overlays/job-tree.d.ts +50 -0
  39. package/dist/types/overlays/jobs-panel.d.ts +25 -11
  40. package/dist/types/overlays/login-dialog.d.ts +8 -3
  41. package/dist/types/overlays/mcp-add-wizard.d.ts +9 -1
  42. package/dist/types/overlays/model-browser.d.ts +6 -1
  43. package/dist/types/overlays/model-picker.d.ts +2 -0
  44. package/dist/types/overlays/pause-screen.d.ts +5 -0
  45. package/dist/types/overlays/plan-review-overlay.d.ts +4 -0
  46. package/dist/types/overlays/report-panel.d.ts +5 -1
  47. package/dist/types/overlays/reset-usage-selector.d.ts +7 -5
  48. package/dist/types/overlays/session-account-selector.d.ts +4 -0
  49. package/dist/types/overlays/session-info-overlay.d.ts +7 -3
  50. package/dist/types/overlays/session-selector.d.ts +3 -1
  51. package/dist/types/overlays/usage-dashboard.d.ts +6 -6
  52. package/dist/types/prompt/composer.d.ts +23 -20
  53. package/dist/types/prompt/custom-editor.d.ts +20 -10
  54. package/dist/types/prompt/image-references.d.ts +22 -0
  55. package/dist/types/prompt/internal-url-autocomplete.d.ts +1 -0
  56. package/dist/types/prompt/macos-spelling.d.ts +2 -1
  57. package/dist/types/prompt/prose-gate.d.ts +3 -0
  58. package/dist/types/prompt/queued-messages.d.ts +1 -1
  59. package/dist/types/prompt/typing-word.d.ts +25 -0
  60. package/dist/types/prompt/welcome.d.ts +26 -6
  61. package/dist/types/render/hanging-wrap.d.ts +7 -0
  62. package/dist/types/render/hyperlink.d.ts +2 -0
  63. package/dist/types/render/render-utils.d.ts +9 -1
  64. package/dist/types/render/utils.d.ts +1 -1
  65. package/dist/types/setup/scenes/splash.d.ts +6 -5
  66. package/dist/types/status-line/context-usage.d.ts +4 -1
  67. package/dist/types/status-line/host.d.ts +6 -4
  68. package/dist/types/status-line/startup.d.ts +6 -6
  69. package/dist/types/status-line/types.d.ts +3 -0
  70. package/dist/types/stdin-buffer.d.ts +7 -0
  71. package/dist/types/terminal-capabilities.d.ts +16 -1
  72. package/dist/types/terminal-multiplexer.d.ts +7 -0
  73. package/dist/types/terminal.d.ts +8 -4
  74. package/dist/types/theme/symbols.d.ts +1 -1
  75. package/dist/types/theme/theme.d.ts +11 -0
  76. package/dist/types/thinking.d.ts +5 -0
  77. package/dist/types/tmux.d.ts +39 -4
  78. package/dist/types/tools/ast-edit.d.ts +2 -2
  79. package/dist/types/tools/ast-grep.d.ts +2 -2
  80. package/dist/types/tools/bash.d.ts +6 -1
  81. package/dist/types/tools/edit.d.ts +2 -0
  82. package/dist/types/tools/eval.d.ts +53 -4
  83. package/dist/types/tools/find.d.ts +14 -4
  84. package/dist/types/tools/glob.d.ts +3 -3
  85. package/dist/types/tools/grep.d.ts +2 -2
  86. package/dist/types/tools/grouped-file-output.d.ts +9 -4
  87. package/dist/types/tools/native-view.d.ts +1 -1
  88. package/dist/types/tools/read.d.ts +32 -10
  89. package/dist/types/tools/renderer.d.ts +2 -0
  90. package/dist/types/tools/task.d.ts +31 -0
  91. package/dist/types/tools/web-search-types.d.ts +1 -0
  92. package/dist/types/tools/write.d.ts +2 -0
  93. package/dist/types/tui.d.ts +20 -3
  94. package/package.json +10 -10
  95. package/src/app-keybindings.d.ts +18 -8
  96. package/src/app-keybindings.ts +20 -8
  97. package/src/apps/autoresearch-dashboard.ts +444 -27
  98. package/src/apps/debug/raw-sse.ts +2 -2
  99. package/src/apps/git/diff-pane.ts +39 -41
  100. package/src/apps/git/git-tui.ts +80 -14
  101. package/src/apps/git/sidebar.ts +10 -1
  102. package/src/apps/git/state.ts +12 -0
  103. package/src/autocomplete.d.ts +2 -0
  104. package/src/autocomplete.ts +21 -19
  105. package/src/bracketed-paste.ts +9 -2
  106. package/src/charts/chart-svg.d.ts +7 -13
  107. package/src/charts/chart-svg.ts +19 -22
  108. package/src/charts/table-data.ts +17 -6
  109. package/src/chat/advisor-message.d.ts +4 -1
  110. package/src/chat/advisor-message.ts +77 -24
  111. package/src/chat/assistant-message.d.ts +9 -4
  112. package/src/chat/assistant-message.ts +127 -31
  113. package/src/chat/bash-execution.ts +7 -2
  114. package/src/chat/figure-markdown.d.ts +7 -2
  115. package/src/chat/figure-markdown.ts +10 -3
  116. package/src/chat/image-loading.ts +9 -6
  117. package/src/chat/messages.d.ts +3 -1
  118. package/src/chat/messages.ts +4 -1
  119. package/src/chat/read-tool-group.d.ts +2 -2
  120. package/src/chat/read-tool-group.ts +97 -42
  121. package/src/chat/svg-figure.ts +3 -1
  122. package/src/chat/svg-source.ts +6 -3
  123. package/src/chat/table-chart.d.ts +11 -15
  124. package/src/chat/table-chart.ts +24 -57
  125. package/src/chat/tool-execution.d.ts +32 -20
  126. package/src/chat/tool-execution.ts +103 -36
  127. package/src/chat/user-message.d.ts +3 -2
  128. package/src/chat/user-message.ts +54 -34
  129. package/src/chrome/countdown-timer.ts +3 -3
  130. package/src/chrome/diff.d.ts +2 -3
  131. package/src/chrome/diff.ts +4 -9
  132. package/src/chrome/status-notice.ts +5 -0
  133. package/src/chrome/transcript-container.d.ts +2 -0
  134. package/src/chrome/transcript-container.ts +212 -28
  135. package/src/components/editor.ts +12 -12
  136. package/src/components/image.d.ts +2 -0
  137. package/src/components/image.ts +54 -20
  138. package/src/components/markdown.d.ts +49 -3
  139. package/src/components/markdown.ts +482 -12
  140. package/src/components/settings-list.ts +2 -4
  141. package/src/components/text.d.ts +2 -0
  142. package/src/components/text.ts +11 -1
  143. package/src/debug-server.d.ts +2 -0
  144. package/src/debug-server.ts +51 -69
  145. package/src/hotkeys-markdown.ts +2 -0
  146. package/src/keybinding-matchers.d.ts +6 -0
  147. package/src/keybinding-matchers.ts +19 -0
  148. package/src/multiplexers/tmux.d.ts +1 -0
  149. package/src/multiplexers/tmux.ts +3 -0
  150. package/src/multiplexers/types.d.ts +6 -0
  151. package/src/multiplexers/types.ts +6 -0
  152. package/src/native/backend.d.ts +5 -4
  153. package/src/native/backend.ts +13 -5
  154. package/src/native/blobs.d.ts +24 -12
  155. package/src/native/blobs.ts +56 -7
  156. package/src/native/reconcile.ts +43 -21
  157. package/src/overlays/advisor-config.ts +259 -8
  158. package/src/overlays/agent-hub-projection.d.ts +10 -5
  159. package/src/overlays/agent-hub-projection.ts +63 -12
  160. package/src/overlays/annotation-overlay.ts +422 -168
  161. package/src/overlays/approval-dialog.ts +389 -0
  162. package/src/overlays/ask-dialog.ts +244 -105
  163. package/src/overlays/btw-history-panel.ts +208 -147
  164. package/src/overlays/extensions/extension-list.ts +4 -6
  165. package/src/overlays/hook-editor.ts +90 -32
  166. package/src/overlays/hook-input.ts +105 -19
  167. package/src/overlays/job-tree.ts +177 -0
  168. package/src/overlays/jobs-panel.ts +222 -142
  169. package/src/overlays/login-dialog.ts +201 -91
  170. package/src/overlays/mcp-add-wizard.ts +562 -279
  171. package/src/overlays/model-browser.ts +32 -7
  172. package/src/overlays/model-hub.ts +4 -10
  173. package/src/overlays/model-picker.ts +58 -21
  174. package/src/overlays/pause-screen.ts +81 -23
  175. package/src/overlays/plan-review-overlay.ts +16 -0
  176. package/src/overlays/plugin-selector.ts +17 -1
  177. package/src/overlays/queue-mode-selector.ts +10 -0
  178. package/src/overlays/report-panel.ts +6 -2
  179. package/src/overlays/reset-usage-selector.ts +130 -21
  180. package/src/overlays/session-account-selector.ts +36 -0
  181. package/src/overlays/session-info-overlay.ts +199 -76
  182. package/src/overlays/session-selector.ts +15 -10
  183. package/src/overlays/settings-selector.ts +3 -0
  184. package/src/overlays/show-images-selector.ts +1 -0
  185. package/src/overlays/snapcompact-shape-preview.ts +13 -6
  186. package/src/overlays/theme-selector.ts +6 -1
  187. package/src/overlays/thinking-selector.ts +8 -4
  188. package/src/overlays/tree-selector.ts +117 -2
  189. package/src/overlays/usage-dashboard.ts +498 -144
  190. package/src/prompt/composer-cache.ts +4 -1
  191. package/src/prompt/composer.ts +200 -74
  192. package/src/prompt/custom-editor.ts +168 -65
  193. package/src/prompt/image-references.d.ts +22 -0
  194. package/src/prompt/image-references.ts +79 -2
  195. package/src/prompt/internal-url-autocomplete.ts +1 -0
  196. package/src/prompt/macos-spelling.ts +28 -5
  197. package/src/prompt/prose-gate.ts +3 -0
  198. package/src/prompt/queued-messages.ts +9 -2
  199. package/src/prompt/tips.txt +1 -2
  200. package/src/prompt/typing-word.ts +59 -0
  201. package/src/prompt/welcome.ts +97 -45
  202. package/src/render/code-cell.ts +18 -5
  203. package/src/render/hanging-wrap.d.ts +7 -0
  204. package/src/render/hanging-wrap.ts +58 -0
  205. package/src/render/hyperlink.d.ts +2 -0
  206. package/src/render/hyperlink.ts +5 -0
  207. package/src/render/render-utils.d.ts +9 -1
  208. package/src/render/render-utils.ts +16 -2
  209. package/src/render/utils.d.ts +1 -1
  210. package/src/render/utils.ts +1 -1
  211. package/src/render/width-aware-text.ts +6 -5
  212. package/src/setup/scenes/splash.ts +22 -8
  213. package/src/status-line/component.ts +79 -11
  214. package/src/status-line/context-usage.ts +176 -73
  215. package/src/status-line/footer.ts +18 -35
  216. package/src/status-line/host.ts +6 -1
  217. package/src/status-line/segments.ts +16 -5
  218. package/src/status-line/startup.ts +6 -6
  219. package/src/status-line/types.ts +1 -0
  220. package/src/stdin-buffer.d.ts +7 -0
  221. package/src/stdin-buffer.ts +300 -62
  222. package/src/terminal-capabilities.d.ts +16 -1
  223. package/src/terminal-capabilities.ts +66 -28
  224. package/src/terminal-multiplexer.d.ts +7 -0
  225. package/src/terminal-multiplexer.ts +14 -0
  226. package/src/terminal.d.ts +8 -4
  227. package/src/terminal.ts +190 -63
  228. package/src/theme/symbols.d.ts +1 -1
  229. package/src/theme/symbols.ts +1 -0
  230. package/src/theme/theme-class.ts +1 -0
  231. package/src/theme/theme.d.ts +11 -0
  232. package/src/theme/theme.ts +46 -14
  233. package/src/thinking.d.ts +5 -0
  234. package/src/thinking.ts +9 -1
  235. package/src/tmux.d.ts +39 -4
  236. package/src/tmux.ts +110 -16
  237. package/src/tools/ask.ts +20 -9
  238. package/src/tools/ast-edit.d.ts +2 -2
  239. package/src/tools/ast-edit.ts +30 -7
  240. package/src/tools/ast-grep.d.ts +2 -2
  241. package/src/tools/ast-grep.ts +39 -35
  242. package/src/tools/bash.d.ts +6 -1
  243. package/src/tools/bash.ts +15 -9
  244. package/src/tools/debug.ts +2 -1
  245. package/src/tools/default-renderer.ts +3 -2
  246. package/src/tools/edit.d.ts +2 -0
  247. package/src/tools/edit.ts +100 -21
  248. package/src/tools/eval.d.ts +53 -4
  249. package/src/tools/eval.ts +173 -137
  250. package/src/tools/find.d.ts +14 -4
  251. package/src/tools/find.ts +71 -18
  252. package/src/tools/glob.d.ts +3 -3
  253. package/src/tools/glob.ts +51 -17
  254. package/src/tools/grep.d.ts +2 -2
  255. package/src/tools/grep.ts +99 -22
  256. package/src/tools/grouped-file-output.d.ts +9 -4
  257. package/src/tools/grouped-file-output.ts +21 -6
  258. package/src/tools/lsp.ts +30 -18
  259. package/src/tools/mcp.ts +2 -2
  260. package/src/tools/native-view.d.ts +1 -1
  261. package/src/tools/native-view.ts +2 -2
  262. package/src/tools/read.d.ts +32 -10
  263. package/src/tools/read.ts +89 -43
  264. package/src/tools/renderer.d.ts +2 -0
  265. package/src/tools/renderer.ts +2 -0
  266. package/src/tools/task.d.ts +31 -0
  267. package/src/tools/task.ts +40 -7
  268. package/src/tools/todo.ts +3 -2
  269. package/src/tools/wait.ts +16 -30
  270. package/src/tools/web-search-types.d.ts +1 -0
  271. package/src/tools/web-search-types.ts +1 -0
  272. package/src/tools/web-search.ts +2 -1
  273. package/src/tools/write.d.ts +2 -0
  274. package/src/tools/write.ts +36 -12
  275. package/src/tools/yield.ts +2 -2
  276. package/src/tui.d.ts +20 -3
  277. package/src/tui.ts +160 -43
  278. package/src/utils.ts +5 -3
  279. package/dist/types/tools/eval-format/code-mode-declarations.d.ts +0 -5
  280. package/src/tools/eval-format/code-mode-declarations.ts +0 -61
@@ -173,7 +173,9 @@ export declare function isUserInvokedSkillPrompt(message: CustomMessage): boolea
173
173
  * reminders, and auto-continues are not turn starts.
174
174
  */
175
175
  export declare function isUserTurnInitiator(message: CustomMessage): boolean;
176
- export type AdvisorSeverity = "nit" | "concern" | "blocker";
176
+ /** Advisor note severities, weakest first; ranks severity thresholds such as `advisor.continueSeverity`. */
177
+ export declare const ADVISOR_SEVERITIES: readonly ["nit", "concern", "blocker"];
178
+ export type AdvisorSeverity = (typeof ADVISOR_SEVERITIES)[number];
177
179
  /** One queued advice note. */
178
180
  export interface AdvisorNote {
179
181
  note: string;
@@ -294,7 +294,10 @@ export function isUserTurnInitiator(message: CustomMessage): boolean {
294
294
  );
295
295
  }
296
296
 
297
- export type AdvisorSeverity = "nit" | "concern" | "blocker";
297
+ /** Advisor note severities, weakest first; ranks severity thresholds such as `advisor.continueSeverity`. */
298
+ export const ADVISOR_SEVERITIES = ["nit", "concern", "blocker"] as const;
299
+
300
+ export type AdvisorSeverity = (typeof ADVISOR_SEVERITIES)[number];
298
301
 
299
302
  /** One queued advice note. */
300
303
  export interface AdvisorNote {
@@ -74,8 +74,8 @@ export declare class ReadToolGroupComponent extends Container implements ToolExe
74
74
  * The read run as one inline `tool` on terminals that list the kind, else
75
75
  * the fallback: a bare `card` (role `zeta.tool.read`) with `Read <path>` or
76
76
  * `Read (N)` in the head, a `list` of path items (status tone, link,
77
- * correction and conflict detail, nested usage) and, with content previews
78
- * on, a `code` block per read clamped by the card's preview while collapsed.
77
+ * correction and conflict detail, nested usage) and a clamped preview per
78
+ * read when content previews are on.
79
79
  */
80
80
  describe(cx?: DescribeContext): NativeNode;
81
81
  }
@@ -10,19 +10,22 @@ import {
10
10
  type ReadRenderArgs,
11
11
  type ReadToolDetails,
12
12
  readContentCode,
13
+ readResultIsMarkdown,
13
14
  readSourceFsPath,
14
15
  splitPathAndSel,
15
16
  } from "../tools/read";
16
17
  import { PREVIEW_LIMITS, shortenPath } from "../render/render-utils";
17
- import { fileHyperlink, renderCodeCell } from "../render";
18
+ import { fileHyperlink, renderCodeCell, renderMarkdownCell } from "../render";
19
+ import { wrapTreeLine } from "../render/hanging-wrap";
20
+ import { wrapTextWithAnsi } from "../utils";
18
21
  import { canonicalizeMessage } from "./thinking-display";
19
22
  import { internalUrlSchemeSpec, splitUrlScheme } from "../tools/url-scheme-host";
20
23
  import type { ToolExecutionHandle } from "./tool-execution";
21
24
  import { formatUsageRow } from "../overlays/usage-row";
22
- import { formatCount } from "@linxiraos/pi-utils";
25
+ import { formatCount, sanitizeText, sanitizeTextDeep } from "@linxiraos/pi-utils";
23
26
  import type { TspCardStatus, TspSpan, TspText } from "@linxiraos/pi-wire";
24
27
  import type { NativeToolHead } from "../tools/renderer";
25
- import { card, code, keyed, node, span, text, withHidden } from "../native/describe";
28
+ import { card, code, keyed, md, node, span, text, withHidden } from "../native/describe";
26
29
  import {
27
30
  type DescribeContext,
28
31
  type NativeChild,
@@ -121,11 +124,23 @@ type ReadEntry = {
121
124
  status: "pending" | "success" | "warning" | "error";
122
125
  correctedFrom?: string;
123
126
  contentText?: string;
127
+ /** The result's `details.contentType`; see {@link previewsMarkdown}. */
128
+ contentType?: string;
129
+ /** The call's `raw` arg, which keeps Markdown previews as source. */
130
+ raw?: boolean;
124
131
  conflictCount?: number;
125
132
  codeStartLine?: number;
126
133
  codeLineNumbers?: Array<number | null>;
127
134
  };
128
135
 
136
+ /**
137
+ * Whether an entry previews as rendered Markdown instead of numbered source.
138
+ * Derived on each render so `raw`/path args that land after the result still apply.
139
+ */
140
+ function previewsMarkdown(entry: ReadEntry): boolean {
141
+ return readResultIsMarkdown({ contentType: entry.contentType }, { path: entry.path, raw: entry.raw });
142
+ }
143
+
129
144
  type ReadUsageRow = {
130
145
  toolCallIds: readonly string[];
131
146
  usage: Usage;
@@ -135,13 +150,12 @@ type ReadUsageRow = {
135
150
  turnElapsedMs?: number;
136
151
  };
137
152
 
138
- /** Number of code lines to show in collapsed preview mode */
153
+ /** Number of preview rows to show per read while collapsed. */
139
154
  const COLLAPSED_PREVIEW_LINES = PREVIEW_LIMITS.OUTPUT_COLLAPSED;
140
155
 
141
156
  /**
142
- * Collapsed clamp for a data-first group whose previews are already trimmed
143
- * to {@link COLLAPSED_PREVIEW_LINES}: large enough never to cut the trimmed
144
- * body, so collapsed shows every file and the head of each preview.
157
+ * The outer data-first group must not cut off later files: code is trimmed by
158
+ * source line and Markdown is clamped by each file's native card after rendering.
145
159
  */
146
160
  const TRIMMED_BODY_PREVIEW = { lines: 1000 } as const;
147
161
 
@@ -174,9 +188,12 @@ const READ_STATUS_RANK: Record<ReadEntry["status"], number> = {
174
188
  error: 3,
175
189
  };
176
190
 
177
- function getDisplayReadTargets(details: ReadToolDetails | undefined): ReadDisplayPathSpec[] | undefined {
191
+ function getDisplayReadTargets(
192
+ details: ReadToolDetails | undefined,
193
+ rawDetails: ReadToolDetails | undefined,
194
+ ): ReadDisplayPathSpec[] | undefined {
178
195
  if (!Array.isArray(details?.displayReadTargets)) return undefined;
179
- const links = Array.isArray(details.displayReadTargetLinks) ? details.displayReadTargetLinks : undefined;
196
+ const links = Array.isArray(rawDetails?.displayReadTargetLinks) ? rawDetails.displayReadTargetLinks : undefined;
180
197
  const targets: ReadDisplayPathSpec[] = [];
181
198
  details.displayReadTargets.forEach((raw, index) => {
182
199
  if (typeof raw !== "string") return;
@@ -423,12 +440,15 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
423
440
  if (!toolCallId) return;
424
441
  const rawPath =
425
442
  typeof args.file_path === "string" ? args.file_path : typeof args.path === "string" ? args.path : "";
443
+ const displayPath = sanitizeText(rawPath);
426
444
  const entry: ReadEntry = this.#entries.get(toolCallId) ?? {
427
445
  toolCallId,
428
- path: rawPath,
446
+ path: displayPath,
429
447
  status: "pending",
430
448
  };
431
- entry.path = rawPath;
449
+ entry.path = displayPath;
450
+ entry.linkPath = path.isAbsolute(rawPath) ? rawPath : undefined;
451
+ entry.raw = args.raw === true;
432
452
  this.#entries.set(toolCallId, entry);
433
453
  this.#updateDisplay();
434
454
  }
@@ -469,12 +489,15 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
469
489
  if (!entry) return;
470
490
  if (isPartial) return;
471
491
  this.#blockVersion++;
472
- const details = result.details as ReadToolDetails | undefined;
492
+ // `details` can contain raw file text and filesystem paths. Keep the
493
+ // latter for links while only the sanitized copy supplies display labels.
494
+ const rawDetails = result.details as ReadToolDetails | undefined;
495
+ const details = sanitizeTextDeep(rawDetails) as ReadToolDetails | undefined;
473
496
  const suffixResolution = getSuffixResolution(details);
474
- const displayPaths = getDisplayReadTargets(details);
475
- entry.linkPath = readResultLinkPath(details);
497
+ const displayPaths = getDisplayReadTargets(details, rawDetails);
498
+ entry.linkPath = readResultLinkPath(rawDetails) ?? entry.linkPath;
476
499
  if (suffixResolution) {
477
- entry.path = displayPathWithSuffixResolution(entry.path, suffixResolution);
500
+ entry.path = sanitizeText(displayPathWithSuffixResolution(entry.path, suffixResolution));
478
501
  entry.correctedFrom = suffixResolution.from;
479
502
  entry.displayPaths = undefined;
480
503
  } else {
@@ -485,6 +508,7 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
485
508
  typeof details?.conflictCount === "number" && details.conflictCount > 0 ? details.conflictCount : undefined;
486
509
  entry.conflictCount = conflictCount;
487
510
  entry.status = result.isError ? "error" : suffixResolution ? "warning" : "success";
511
+ entry.contentType = details?.contentType;
488
512
  // Store clean display content for preview/expanded display when the read
489
513
  // tool provides it; fall back to model-facing text for legacy results.
490
514
  const displayContent = details?.displayContent;
@@ -578,8 +602,8 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
578
602
  * The read run as one inline `tool` on terminals that list the kind, else
579
603
  * the fallback: a bare `card` (role `zeta.tool.read`) with `Read <path>` or
580
604
  * `Read (N)` in the head, a `list` of path items (status tone, link,
581
- * correction and conflict detail, nested usage) and, with content previews
582
- * on, a `code` block per read clamped by the card's preview while collapsed.
605
+ * correction and conflict detail, nested usage) and a clamped preview per
606
+ * read when content previews are on.
583
607
  */
584
608
  override describe(cx?: DescribeContext): NativeNode {
585
609
  const dataFirst = cx?.supports("tool") === true;
@@ -593,8 +617,8 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
593
617
  * The data-first read (§7.3 read, read group, read error): one inline
594
618
  * `tool` (role `zeta.tool.read`). One file: `Read path:13-36`, a failure's
595
619
  * message in the head. Several: `Read 3 files` over one 22px row per file
596
- * (glyph, dim dir, strong name, range). Content previews are numbered
597
- * `code` (a section per file in a group), trimmed while collapsed.
620
+ * (glyph, dim dir, strong name, range). Each content preview is numbered
621
+ * code or rendered Markdown, clamped per file while collapsed.
598
622
  */
599
623
  #describeTool(): NativeNode {
600
624
  const entries = [...this.#entries.values()];
@@ -715,8 +739,21 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
715
739
  );
716
740
  }
717
741
 
718
- /** One read's content as numbered `code`, trimmed to its first lines (plus a count) while collapsed. */
742
+ /** One read's content, clamped per file while the group is collapsed. */
719
743
  #nativePreview(entry: ReadEntry): NativeChild[] {
744
+ if (previewsMarkdown(entry)) {
745
+ return [
746
+ card(
747
+ {
748
+ variant: "bare",
749
+ collapsible: true,
750
+ collapsed: !this.#expanded,
751
+ preview: { lines: COLLAPSED_PREVIEW_LINES },
752
+ },
753
+ [md(entry.contentText ?? "")],
754
+ ),
755
+ ];
756
+ }
720
757
  const split = splitPathAndSel(entry.path);
721
758
  const lines = (entry.contentText ?? "").split("\n");
722
759
  const shown = this.#expanded ? lines.length : Math.min(lines.length, COLLAPSED_PREVIEW_LINES);
@@ -724,7 +761,7 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
724
761
  lines.slice(0, shown).join("\n"),
725
762
  entry.codeStartLine ?? firstSelectorLine(split.sel) ?? 1,
726
763
  entry.codeLineNumbers?.slice(0, shown),
727
- getLanguageFromPath(split.path),
764
+ split.path,
728
765
  );
729
766
  const hidden = lines.length - shown;
730
767
  if (hidden > 0) {
@@ -796,11 +833,14 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
796
833
  preview: { lines: COLLAPSED_PREVIEW_LINES },
797
834
  },
798
835
  [
799
- code(entry.contentText ?? "", {
800
- lang: getLanguageFromPath(split.path),
801
- start: entry.codeStartLine,
802
- numbers: true,
803
- }),
836
+ previewsMarkdown(entry)
837
+ ? md(entry.contentText ?? "")
838
+ : code(entry.contentText ?? "", {
839
+ path: split.path,
840
+ start: entry.codeStartLine,
841
+ numbers: true,
842
+ wrap: true,
843
+ }),
804
844
  ],
805
845
  `p${entry.toolCallId}`,
806
846
  ),
@@ -862,7 +902,9 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
862
902
 
863
903
  // Clear previous children and rebuild the summary and preview blocks.
864
904
  this.clear();
865
- this.#text = new Text("", 0, 0);
905
+ this.#text = new Text("", 0, 0).setWrapLine(
906
+ (line, width) => wrapTreeLine(line, width, theme) ?? wrapTextWithAnsi(line, width),
907
+ );
866
908
 
867
909
  if (displayRows.length === 0) {
868
910
  this.#text.setText(` ${theme.format.bullet} ${theme.fg("toolTitle", theme.bold("Read"))}`);
@@ -1124,7 +1166,7 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
1124
1166
  }
1125
1167
 
1126
1168
  /**
1127
- * Add a code-cell content preview below the entry summary.
1169
+ * Add a code-cell (or Markdown-cell) content preview below the entry summary.
1128
1170
  * When collapsed: shows first COLLAPSED_PREVIEW_LINES lines with a "… N more lines ⟨<key>: Expand⟩" hint.
1129
1171
  * When expanded: shows full content.
1130
1172
  */
@@ -1151,20 +1193,33 @@ export class ReadToolGroupComponent extends Container implements ToolExecutionHa
1151
1193
  const component: Component = {
1152
1194
  render: (width: number) => {
1153
1195
  if (cachedLines && cachedWidth === width) return cachedLines;
1154
- cachedLines = renderCodeCell(
1155
- {
1156
- code: entry.contentText ?? "",
1157
- language: lang,
1158
- title,
1159
- status: entry.status === "success" ? "complete" : entry.status,
1160
- expanded,
1161
- codeMaxLines: expanded ? undefined : COLLAPSED_PREVIEW_LINES,
1162
- codeStartLine: entry.codeStartLine,
1163
- codeLineNumbers: entry.codeLineNumbers,
1164
- width,
1165
- },
1166
- theme,
1167
- );
1196
+ const status = entry.status === "success" ? "complete" : entry.status;
1197
+ cachedLines = previewsMarkdown(entry)
1198
+ ? renderMarkdownCell(
1199
+ {
1200
+ content: entry.contentText ?? "",
1201
+ title,
1202
+ status,
1203
+ expanded,
1204
+ contentMaxLines: COLLAPSED_PREVIEW_LINES,
1205
+ width,
1206
+ },
1207
+ theme,
1208
+ )
1209
+ : renderCodeCell(
1210
+ {
1211
+ code: entry.contentText ?? "",
1212
+ language: lang,
1213
+ title,
1214
+ status,
1215
+ expanded,
1216
+ codeMaxLines: expanded ? undefined : COLLAPSED_PREVIEW_LINES,
1217
+ codeStartLine: entry.codeStartLine,
1218
+ codeLineNumbers: entry.codeLineNumbers,
1219
+ width,
1220
+ },
1221
+ theme,
1222
+ );
1168
1223
  cachedWidth = width;
1169
1224
  return cachedLines;
1170
1225
  },
@@ -17,7 +17,7 @@ import { hexToOklch, hueDistance, logger, oklchCusp, oklchToHex } from "@linxira
17
17
  import { Image, type ImageBudget, imageMaxColumns } from "../components/image";
18
18
  import { fencedCode, type Markdown } from "../components/markdown";
19
19
  import { type CellDimensions, getCellDimensions, getImageDimensions } from "../terminal-capabilities";
20
- import { getThemeEpoch, type ThemeColor, theme } from "../theme";
20
+ import { ensureThemeSync, getThemeEpoch, type ThemeColor, theme } from "../theme";
21
21
  import type { Component } from "../tui";
22
22
  import { closePartialSvg, prepareSvg } from "./svg-source";
23
23
 
@@ -59,6 +59,7 @@ const SERIES_CHROMA = 0.19;
59
59
 
60
60
  /** The active theme's color per figure token, for resolving a figure with `prepareSvg`. */
61
61
  export function svgFigurePalette(): Record<string, string> {
62
+ ensureThemeSync();
62
63
  const palette: Record<string, string> = { surface: theme.getBgHex("selectedBg") };
63
64
  for (const token in PALETTE) palette[token] = theme.getColorHex(PALETTE[token]!);
64
65
  seriesColors(palette.accent!, theme.isLight).forEach((color, at) => {
@@ -181,6 +182,7 @@ export class SvgFigure implements Component {
181
182
  #placeholder: readonly string[] | undefined;
182
183
 
183
184
  constructor(options: SvgFigureOptions) {
185
+ ensureThemeSync();
184
186
  this.#options = options;
185
187
  }
186
188
 
@@ -35,9 +35,12 @@ export function splitSvgFences(markdown: string): FigureSegment[] {
35
35
  let proseStart = 0;
36
36
  let lineStart = 0;
37
37
  while (lineStart <= markdown.length) {
38
- const newline = markdown.indexOf("\n", lineStart);
39
- const lineEnd = newline < 0 ? markdown.length : newline;
40
- const next = newline < 0 ? markdown.length + 1 : newline + 1;
38
+ let lineEnd = lineStart;
39
+ while (lineEnd < markdown.length && markdown[lineEnd] !== "\n" && markdown[lineEnd] !== "\r") lineEnd++;
40
+ const next =
41
+ lineEnd === markdown.length
42
+ ? markdown.length + 1
43
+ : lineEnd + (markdown[lineEnd] === "\r" && markdown[lineEnd + 1] === "\n" ? 2 : 1);
41
44
  const line = markdown.slice(lineStart, lineEnd);
42
45
  if (fence) {
43
46
  if (closesFence(line, fence.marker)) {
@@ -2,7 +2,6 @@ import type { Tokens } from "@linxiraos/pi-utils/marked";
2
2
  import { type ChartPlan } from "../charts/chart-plan";
3
3
  import { type TableAnalysis } from "../charts/table-data";
4
4
  import type { ImageBudget } from "../components/image";
5
- import type { NativeNode } from "../native/node";
6
5
  import type { Component } from "../tui";
7
6
  /**
8
7
  * `smart`: a model refines the local guess where meaning decides (kind,
@@ -24,17 +23,11 @@ export interface TableChartRequest {
24
23
  * for no chart. A rejection falls back to the local guess.
25
24
  */
26
25
  export type TableChartPlanner = (request: TableChartRequest) => Promise<ChartPlan | null>;
27
- /** A drawn chart, ready to resolve against the theme. */
28
- export interface TableChart {
29
- /** SVG colored with figure tokens (`var(--accent)`, …). */
30
- readonly svg: string;
31
- readonly alt: string;
32
- /** Size in SVG user units. */
33
- readonly width: number;
34
- readonly height: number;
35
- }
36
- /** The chart under a table: drawn, none, or a smart pick on its way (the promise settles once the cache holds it). */
37
- export type ChartLookup = TableChart | null | Promise<void>;
26
+ /**
27
+ * The chart under a table: its SVG, colored with figure tokens (`var(--accent)`, …)
28
+ * still to resolve; none; or a smart pick on its way (the promise settles once the cache holds it).
29
+ */
30
+ export type ChartLookup = string | null | Promise<void>;
38
31
  /** One run of a Markdown block: prose (ending at a charted table), or the chart drawn after that table. */
39
32
  export type ChartSegment = {
40
33
  readonly kind: "markdown";
@@ -60,10 +53,13 @@ export declare function splitTableCharts(markdown: string, streaming: boolean):
60
53
  */
61
54
  export declare function lookupTableChart(table: Tokens.Table): ChartLookup;
62
55
  /**
63
- * A native `image` node drawing `chart` from its SVG — no raster — resolved
64
- * against the active theme; rebuilt when the theme changes.
56
+ * Chart `svg` as a Markdown ```svg fence, for a TSP terminal's `md` node. Its
57
+ * figure tokens stay unresolved: the terminal draws the fence as a figure in
58
+ * the palette it shows the prose in, so the chart cannot fall out of step with
59
+ * the page when omp's own idea of the appearance does, and a theme switch
60
+ * recolors it without a resend.
65
61
  */
66
- export declare function describeTableChart(chart: TableChart, key: string): NativeNode;
62
+ export declare function chartFence(svg: string): string;
67
63
  export interface TableChartFigureOptions {
68
64
  /** Shared inline-image budget. */
69
65
  budget?: ImageBudget;
@@ -5,24 +5,19 @@
5
5
  * and draws that chart — locally under `always`, through the host's
6
6
  * model-backed {@link TableChartPlanner} under `smart` for the tables
7
7
  * {@link shouldJudge} picks — and caches it per table source. {@link TableChartFigure} shows it
8
- * as a rasterized terminal image; {@link describeTableChart} hands a TSP
9
- * terminal the SVG itself. Both resolve the figure tokens against the live
10
- * theme, so a chart follows theme switches like the prose around it.
8
+ * as a terminal image rasterized in omp's theme; {@link chartFence} hands a
9
+ * TSP terminal the SVG as an ```svg fence, which it draws in the palette it
10
+ * shows. Either way a chart follows theme switches like the prose around it.
11
11
  */
12
12
  import { logger } from "@linxiraos/pi-utils";
13
13
  import type { Token, Tokens } from "@linxiraos/pi-utils/marked";
14
14
  import { type ChartPlan, buildChart, planChart, shouldJudge, worthCharting } from "../charts/chart-plan";
15
- import { chartAlt, renderChartSvg } from "../charts/chart-svg";
15
+ import { renderChartSvg } from "../charts/chart-svg";
16
16
  import { analyzeTable, type TableAnalysis } from "../charts/table-data";
17
17
  import type { ImageBudget } from "../components/image";
18
18
  import { lexDocument } from "../components/markdown";
19
- import { keyed } from "../native/describe";
20
- import { nativeImageNode } from "../native/blobs";
21
- import type { NativeNode } from "../native/node";
22
- import { getThemeEpoch } from "../theme";
23
19
  import type { Component } from "../tui";
24
- import { SvgFigure, svgFigurePalette } from "./svg-figure";
25
- import { prepareSvg } from "./svg-source";
20
+ import { SvgFigure } from "./svg-figure";
26
21
 
27
22
  /**
28
23
  * `smart`: a model refines the local guess where meaning decides (kind,
@@ -47,18 +42,11 @@ export interface TableChartRequest {
47
42
  */
48
43
  export type TableChartPlanner = (request: TableChartRequest) => Promise<ChartPlan | null>;
49
44
 
50
- /** A drawn chart, ready to resolve against the theme. */
51
- export interface TableChart {
52
- /** SVG colored with figure tokens (`var(--accent)`, …). */
53
- readonly svg: string;
54
- readonly alt: string;
55
- /** Size in SVG user units. */
56
- readonly width: number;
57
- readonly height: number;
58
- }
59
-
60
- /** The chart under a table: drawn, none, or a smart pick on its way (the promise settles once the cache holds it). */
61
- export type ChartLookup = TableChart | null | Promise<void>;
45
+ /**
46
+ * The chart under a table: its SVG, colored with figure tokens (`var(--accent)`, …)
47
+ * still to resolve; none; or a smart pick on its way (the promise settles once the cache holds it).
48
+ */
49
+ export type ChartLookup = string | null | Promise<void>;
62
50
 
63
51
  /** One run of a Markdown block: prose (ending at a charted table), or the chart drawn after that table. */
64
52
  export type ChartSegment =
@@ -67,8 +55,6 @@ export type ChartSegment =
67
55
 
68
56
  /** Tables cached per source; a long session keeps its recent charts without growing without bound. */
69
57
  const CACHE_LIMIT = 256;
70
- /** SVG user units per terminal column (16 per row on 1:2 cells), sizing native images. */
71
- const UNITS_PER_COLUMN = 8;
72
58
  /** A GFM delimiter row (`|---|:--:|`), the cheap test before lexing a block. */
73
59
  const DELIMITER_ROW = /^ {0,3}\|?[ \t]*:?-+:?[ \t]*\|/m;
74
60
 
@@ -78,20 +64,14 @@ interface ChartEntry {
78
64
  readonly guess: ChartPlan | undefined;
79
65
  /** The host's planner picks this table's chart. */
80
66
  readonly smart: boolean;
81
- /** `undefined` until drawn (or judged chartless). */
82
- chart?: TableChart | null;
67
+ /** The chart's SVG; `undefined` until drawn (or judged chartless). */
68
+ chart?: string | null;
83
69
  pending?: Promise<void>;
84
70
  }
85
71
 
86
72
  let chartMode: TableChartMode = "off";
87
73
  let chartPlanner: TableChartPlanner | undefined;
88
74
  const charts = new Map<string, ChartEntry>();
89
- /** The theme-resolved image node owning a chart's native bytes. */
90
- const kNativeImage = Symbol("tableChart.nativeImage");
91
-
92
- interface NativeTagged extends TableChart {
93
- [kNativeImage]?: { epoch: number; image: NativeNode };
94
- }
95
75
 
96
76
  /** Set how tables become charts (the host's `tui.autoGraph`) and its `smart` planner; the host rebuilds the transcript after. */
97
77
  export function setTableCharts(mode: TableChartMode, planner?: TableChartPlanner): void {
@@ -188,34 +168,21 @@ function chartEntry(table: Tokens.Table): ChartEntry {
188
168
  * Draw `plan`. A guess must also pass {@link worthCharting}; a model's pick
189
169
  * already judged the chart worth drawing.
190
170
  */
191
- function drawChart(analysis: TableAnalysis, plan: ChartPlan, guessed = false): TableChart | null {
171
+ function drawChart(analysis: TableAnalysis, plan: ChartPlan, guessed = false): string | null {
192
172
  const spec = buildChart(analysis, plan);
193
173
  if (!spec || (guessed && !worthCharting(spec))) return null;
194
- return { ...renderChartSvg(spec), alt: chartAlt(spec) };
174
+ return renderChartSvg(spec);
195
175
  }
196
176
 
197
177
  /**
198
- * A native `image` node drawing `chart` from its SVG — no raster — resolved
199
- * against the active theme; rebuilt when the theme changes.
178
+ * Chart `svg` as a Markdown ```svg fence, for a TSP terminal's `md` node. Its
179
+ * figure tokens stay unresolved: the terminal draws the fence as a figure in
180
+ * the palette it shows the prose in, so the chart cannot fall out of step with
181
+ * the page when omp's own idea of the appearance does, and a theme switch
182
+ * recolors it without a resend.
200
183
  */
201
- export function describeTableChart(chart: TableChart, key: string): NativeNode {
202
- const epoch = getThemeEpoch();
203
- const tagged: NativeTagged = chart;
204
- let entry = tagged[kNativeImage];
205
- if (entry?.epoch !== epoch) {
206
- const svg = prepareSvg(chart.svg, svgFigurePalette());
207
- entry = {
208
- epoch,
209
- image: nativeImageNode(new TextEncoder().encode(svg), "image/svg+xml", {
210
- alt: chart.alt,
211
- w: chart.width,
212
- h: chart.height,
213
- max: { w: `${Math.round(chart.width / UNITS_PER_COLUMN)}ch` },
214
- }),
215
- };
216
- tagged[kNativeImage] = entry;
217
- }
218
- return keyed(entry.image, key);
184
+ export function chartFence(svg: string): string {
185
+ return `\`\`\`svg\n${svg}\n\`\`\``;
219
186
  }
220
187
 
221
188
  export interface TableChartFigureOptions {
@@ -235,8 +202,8 @@ export class TableChartFigure implements Component {
235
202
  readonly #options: TableChartFigureOptions;
236
203
  readonly #figure: SvgFigure;
237
204
  #table: Tokens.Table | undefined;
238
- /** `undefined` while not looked up or waiting for a pick. */
239
- #chart: TableChart | null | undefined;
205
+ /** The chart's SVG; `undefined` while not looked up or waiting for a pick. */
206
+ #chart: string | null | undefined;
240
207
  #waiting = false;
241
208
  #disposed = false;
242
209
 
@@ -289,6 +256,6 @@ export class TableChartFigure implements Component {
289
256
  return;
290
257
  }
291
258
  this.#chart = found;
292
- if (found) this.#figure.update(found.svg, true);
259
+ if (found) this.#figure.update(found, true);
293
260
  }
294
261
  }
@@ -17,19 +17,21 @@ export interface ToolExecutionOptions {
17
17
  /** Allow the name-keyed renderer registry only when the active tool is the built-in implementation. */
18
18
  useBuiltInRenderer?: boolean;
19
19
  }
20
+ /** A tool result or progress frame as a card shows it. */
21
+ export interface ToolResultFrame {
22
+ content: Array<{
23
+ type: string;
24
+ text?: string;
25
+ data?: string;
26
+ mimeType?: string;
27
+ }>;
28
+ details?: unknown;
29
+ isError?: boolean;
30
+ }
20
31
  export interface ToolExecutionHandle extends Component {
21
32
  updateArgs(args: unknown, toolCallId?: string): void;
22
33
  updateStreamPreview?(update: unknown): void;
23
- updateResult(result: {
24
- content: Array<{
25
- type: string;
26
- text?: string;
27
- data?: string;
28
- mimeType?: string;
29
- }>;
30
- details?: unknown;
31
- isError?: boolean;
32
- }, isPartial?: boolean, toolCallId?: string): void;
34
+ updateResult(result: ToolResultFrame, isPartial?: boolean, toolCallId?: string): void;
33
35
  setArgsComplete(toolCallId?: string): void;
34
36
  setExecutionStarted(toolCallId?: string): void;
35
37
  setExpanded(expanded: boolean): void;
@@ -39,6 +41,25 @@ export interface ToolExecutionHandle extends Component {
39
41
  /** Seal the block as final history and stop its animations. */
40
42
  seal(): void;
41
43
  }
44
+ /**
45
+ * Whether a call that returned with `details.async.state === "running"` stays
46
+ * parked ({@link ToolExecutionHandle.parkAsBackground}) so its job's later
47
+ * frames keep filling the card until a `completed`/`failed` frame settles it.
48
+ * Detached `task` spawns always do; backgrounded `bash`/`eval` jobs only under
49
+ * native rendering, where the terminal transcript keeps them frozen instead.
50
+ * Shared by the live event controller and the transcript rebuild.
51
+ */
52
+ export declare function parksAsBackground(toolName: string, details: unknown): boolean;
53
+ /** The background job state a tool result reports (`details.async.state`: running, completed, failed, cancelled). */
54
+ export declare function asyncJobState(details: unknown): string | undefined;
55
+ /** Whether a frame is a background job's last one: it completed, failed or was cancelled. */
56
+ export declare function isSettledJobFrame(details: unknown): boolean;
57
+ /**
58
+ * Settle a parked card ({@link parksAsBackground}) with its job's last frame
59
+ * ({@link isSettledJobFrame}): a completed or failed job is the call's result;
60
+ * a cancelled one keeps the output it got to and seals the card as cancelled.
61
+ */
62
+ export declare function settleWithJobFrame(component: ToolExecutionHandle, frame: ToolResultFrame, toolCallId: string): void;
42
63
  /** Phase-locked spinner glyph index shared by every live tool block so parallel
43
64
  * spinners advance in lockstep instead of each tracking its own start time. */
44
65
  export declare function sharedSpinnerFrame(frameCount: number, now?: number): number;
@@ -74,16 +95,7 @@ export declare class ToolExecutionComponent extends Container {
74
95
  */
75
96
  whenPreviewSettled(timeoutMs?: number): Promise<void>;
76
97
  updateStreamPreview(update: unknown): void;
77
- updateResult(result: {
78
- content: Array<{
79
- type: string;
80
- text?: string;
81
- data?: string;
82
- mimeType?: string;
83
- }>;
84
- details?: unknown;
85
- isError?: boolean;
86
- }, isPartial?: boolean, _toolCallId?: string): void;
98
+ updateResult(result: ToolResultFrame, isPartial?: boolean, _toolCallId?: string): void;
87
99
  /**
88
100
  * Advance to the shared spinner glyph and repaint just this block. Driven by
89
101
  * the single shared spinner ticker (see `registerSpinnerBlock`); the tick is