@simon_he/vue-tui 1.0.1 → 1.1.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 (107) hide show
  1. package/README.md +99 -46
  2. package/dist/TMermaidText-CXm_L969.js +885 -0
  3. package/dist/{TSelect-HzILuti9.js → TSelect-CiyMvwl-.js} +60 -81
  4. package/dist/{TTree-ChOot2Bh.js → TTree-DKGiuIcM.js} +140 -103
  5. package/dist/agent/mermaid.cjs +2 -0
  6. package/dist/agent/mermaid.d.cts +2 -0
  7. package/dist/agent/mermaid.d.ts +2 -0
  8. package/dist/agent/mermaid.js +1 -0
  9. package/dist/agent.cjs +31184 -24907
  10. package/dist/agent.d.cts +11 -1
  11. package/dist/agent.d.ts +11 -1
  12. package/dist/agent.js +1700 -13
  13. package/dist/block-source-5CQp4tF8.js +3230 -0
  14. package/dist/cli/stdin-buffer.d.ts +1 -1
  15. package/dist/cli.cjs +5363 -6178
  16. package/dist/cli.d.cts +5 -1
  17. package/dist/cli.d.ts +5 -1
  18. package/dist/cli.js +3569 -302
  19. package/dist/core/buffer/buffer.d.ts +2 -2
  20. package/dist/core/buffer/eaw-ranges-unicode-17.d.ts +14 -0
  21. package/dist/core/perf/instrumentation-noop.d.ts +48 -0
  22. package/dist/core/perf/instrumentation.d.ts +136 -0
  23. package/dist/core/terminal/create-terminal.d.ts +1 -0
  24. package/dist/core/types.d.ts +0 -4
  25. package/dist/core.cjs +851 -1462
  26. package/dist/core.js +6 -6
  27. package/dist/{create-terminal-C2oiWFJU.js → create-terminal-DXuZ2fci.js} +54 -19
  28. package/dist/debug-logger-ChY_PXVk.js +74 -0
  29. package/dist/{dom-renderer-BqGijQID.js → dom-renderer-DNzmg2As.js} +2 -2
  30. package/dist/experimental.cjs +4115 -5928
  31. package/dist/experimental.d.cts +2 -0
  32. package/dist/experimental.d.ts +2 -0
  33. package/dist/experimental.js +1490 -9
  34. package/dist/frame-perf-BBhE-iuS.js +111 -0
  35. package/dist/{sgr-BmzxEjAO.js → hyperlink-B35-O-cW.js} +100 -1
  36. package/dist/index.cjs +5025 -10332
  37. package/dist/index.js +16 -14
  38. package/dist/{linkify-D_gzn9Xq.js → linkify-CuuquMQT.js} +32 -3
  39. package/dist/markdown.cjs +21295 -12691
  40. package/dist/markdown.d.cts +1 -1
  41. package/dist/markdown.d.ts +1 -1
  42. package/dist/markdown.js +211 -51
  43. package/dist/mermaid-CWto52Wk.js +123 -0
  44. package/dist/mermaid.cjs +1707 -0
  45. package/dist/mermaid.d.cts +3 -0
  46. package/dist/mermaid.d.ts +3 -0
  47. package/dist/mermaid.js +6 -0
  48. package/dist/observability/frame-perf-store.d.ts +2 -1
  49. package/dist/observability/frame-perf.d.ts +33 -0
  50. package/dist/observability.cjs +106 -107
  51. package/dist/observability.d.cts +2 -2
  52. package/dist/observability.d.ts +2 -2
  53. package/dist/observability.js +3 -3
  54. package/dist/{path-suggest-BNqcuE3-.js → path-suggest-fPzRsgPv.js} +1 -1
  55. package/dist/{wheel-scroll-vBRaQ7p-.js → rect-Ng-3eKzF.js} +253 -117
  56. package/dist/renderer/cli/index.d.ts +1 -1
  57. package/dist/renderer/cli/stdout-metrics.d.ts +10 -0
  58. package/dist/renderer/cli/stdout-renderer.d.ts +53 -7
  59. package/dist/renderer/terminal-graphic-render-queue.d.ts +50 -0
  60. package/dist/renderer/terminal-graphics-trace.d.ts +53 -0
  61. package/dist/renderer/terminal-graphics.d.ts +146 -0
  62. package/dist/renderer-dom.cjs +364 -903
  63. package/dist/renderer-dom.js +4 -4
  64. package/dist/runtime/index.d.ts +2 -0
  65. package/dist/{runtime-rfcZCyJq.js → runtime-D77C03RM.js} +28 -15
  66. package/dist/runtime.cjs +427 -889
  67. package/dist/runtime.js +2 -2
  68. package/dist/{terminal-selection-DBinO6p5.js → terminal-selection-CQYr--26.js} +4 -1
  69. package/dist/{tlog-theme-CvLFNMwk.js → tlog-theme-CopRt9SC.js} +37 -6
  70. package/dist/{trace-CjzYeIxN.js → trace-CYHDKM1m.js} +5 -0
  71. package/dist/vue/agent/create-png-terminal-graphic-renderer.d.ts +19 -0
  72. package/dist/vue/components/TAgentTerminalGraphic.d.ts +481 -0
  73. package/dist/vue/components/TCharts.d.ts +1121 -0
  74. package/dist/vue/components/TFeedback.d.ts +1 -1
  75. package/dist/vue/components/TFlex.d.ts +389 -0
  76. package/dist/vue/components/TForm.d.ts +4 -4
  77. package/dist/vue/components/TLogSearchBar.d.ts +3 -3
  78. package/dist/vue/components/TLogSearchPager.d.ts +2 -2
  79. package/dist/vue/components/TMarkdownText.d.ts +162 -4
  80. package/dist/vue/components/TMermaidText.d.ts +900 -0
  81. package/dist/vue/components/TVirtualList.d.ts +9 -0
  82. package/dist/vue/components/TVirtualMarkdown.d.ts +170 -9
  83. package/dist/vue/components/TVirtualRows.d.ts +9 -0
  84. package/dist/vue/components/TerminalProvider.d.ts +2 -0
  85. package/dist/vue/context.d.ts +24 -0
  86. package/dist/vue/index.d.ts +5 -0
  87. package/dist/vue/layout/flex.d.ts +67 -0
  88. package/dist/vue/markdown/ast.d.ts +5 -2
  89. package/dist/vue/markdown/document.d.ts +5 -0
  90. package/dist/vue/markdown/image-actions.d.ts +14 -0
  91. package/dist/vue/markdown/image.d.ts +11 -0
  92. package/dist/vue/markdown/link-actions.d.ts +14 -0
  93. package/dist/vue/markdown/math-actions.d.ts +14 -0
  94. package/dist/vue/markdown/math.d.ts +6 -0
  95. package/dist/vue/markdown/render.d.ts +28 -0
  96. package/dist/vue/markdown/types.d.ts +78 -0
  97. package/dist/vue/mermaid/beautiful-mermaid.d.ts +1436 -0
  98. package/dist/vue/render/render-manager.d.ts +7 -0
  99. package/dist/vue.cjs +7215 -12430
  100. package/dist/vue.js +706 -39
  101. package/dist/wheel-scroll-CQ22Hcyj.js +106 -0
  102. package/dist/{hyperlink-Bn02UXJb.js → width-GqllnV8C.js} +166 -111
  103. package/package.json +107 -18
  104. package/dist/block-source-CKUOnkgT.js +0 -1663
  105. package/dist/frame-perf-C6Xfg85O.js +0 -24
  106. /package/dist/{env-Cl8qmNFN.js → env-DNCzvX8b.js} +0 -0
  107. /package/dist/{path-mnSgEpCm.js → path-BI9W15Zt.js} +0 -0
package/dist/agent.js CHANGED
@@ -1,16 +1,1202 @@
1
- import "./create-terminal-C2oiWFJU.js";
2
- import "./hyperlink-Bn02UXJb.js";
3
- import "./sgr-BmzxEjAO.js";
4
- import { forEachTextCellSegment, sanitizeInlineText, sanitizeTextBlock, sliceByCells, spaces, textCellWidth$1 as textCellWidth, useTerminal, withTextWidthProvider } from "./wheel-scroll-vBRaQ7p-.js";
5
- import { TView } from "./linkify-D_gzn9Xq.js";
6
- import "./terminal-selection-DBinO6p5.js";
7
- import { TBox, TCommandPalette, TDialog, TInput, TRenderPlane, TSelect, TText, computeCommandPaletteMatchRanges } from "./TSelect-HzILuti9.js";
8
- import "./frame-perf-C6Xfg85O.js";
9
- import "./path-mnSgEpCm.js";
10
- import { TVirtualMarkdown, createMarkdownBlockSource } from "./block-source-CKUOnkgT.js";
11
- import { TLogLinksPanel, TLogMinimap, TLogScrollbar, TLogSearchBar, TLogSearchPager, TLogSearchResults, TLogView, TLogVirtualLinksPanel, TLogVirtualSearchResults, TTranscriptView, TVirtualList, createAppendOnlyLogStore, createTLogDensityBucketsFromMarkers, createTLogLevelPlugin, createTLogLineMatcherPlugin, createTLogLinkActionPlugin, createTLogOsc8LinkPlugin, createTLogUrlPlugin, detectTLogUrls, dispatchTLogPluginLinkAction, getTLogPluginMetadata, parseTLogAnnotatedText, resolveTLogLinksPanelTheme, resolveTLogMinimapTheme, resolveTLogScrollbarTheme, resolveTLogSearchBarTheme, resolveTLogSearchPagerTheme, resolveTLogSearchResultsTheme, resolveTLogViewTheme, stripTLogAnsiText, tlogDarkPreset, tlogDarkTheme, tlogDefaultPreset, tlogDefaultTheme, tlogHighContrastPreset, tlogHighContrastTheme, toTLogExternalLinkFromVisibleLink, useTLogLinkController, useTLogRetainedIndex, useTLogSearchController, useTLogSearchResultsPage, useTLogVirtualSearchResults } from "./tlog-theme-CvLFNMwk.js";
12
- import { computed, defineComponent, h } from "vue";
1
+ import "./create-terminal-DXuZ2fci.js";
2
+ import "./width-GqllnV8C.js";
3
+ import "./hyperlink-B35-O-cW.js";
4
+ import { TerminalGraphicsActivityKey, forEachTextCellSegment, intersectRect, nowTerminalGraphicTraceTime, padEndByCells$1 as padEndByCells, recordTerminalGraphicTrace, sanitizeInlineText, sanitizeTextBlock, sliceByCells, sliceByCellsRange, spaces, textCellWidth$1 as textCellWidth, translateRect, useLayout, useRenderNode, useTerminal, useVisibility, withTextWidthProvider } from "./rect-Ng-3eKzF.js";
5
+ import { TView } from "./linkify-CuuquMQT.js";
6
+ import "./frame-perf-BBhE-iuS.js";
7
+ import "./env-DNCzvX8b.js";
8
+ import "./terminal-selection-CQYr--26.js";
9
+ import "./debug-logger-ChY_PXVk.js";
10
+ import { TBox, TCommandPalette, TDialog, TInput, TRenderPlane, TSelect, TText, computeCommandPaletteMatchRanges } from "./TSelect-CiyMvwl-.js";
11
+ import "./path-BI9W15Zt.js";
12
+ import "./wheel-scroll-CQ22Hcyj.js";
13
+ import { TMermaid$1 as TMermaid, TMermaidText$1 as TMermaidText, isSimpleMermaidFlowchartSource, markMermaidRenderErrorFatal } from "./TMermaidText-CXm_L969.js";
14
+ import { TVirtualMarkdown, canDrawTerminalGraphicRect, createIterm2InlineImageSequence, createKittyDeleteGraphicsSequence, createKittyGraphicsSequence, createKittyPlacementSequence, createMarkdownBlockSource, detectTerminalGraphicsCapabilities, getTerminalGraphicsOutput, getTerminalGraphicsOutputVersion, hashTerminalGraphicsString, isSafeTerminalGraphicsSequence, isTerminalGraphicsProtocol, normalizeTerminalGraphicSize, sanitizeTerminalFallbackText, stableTerminalGraphicNumericId, subscribeTerminalGraphicsOutput } from "./block-source-5CQp4tF8.js";
15
+ import { TLogLinksPanel, TLogMinimap, TLogScrollbar, TLogSearchBar, TLogSearchPager, TLogSearchResults, TLogView, TLogVirtualLinksPanel, TLogVirtualSearchResults, TTranscriptView, TVirtualList, createAppendOnlyLogStore, createTLogDensityBucketsFromMarkers, createTLogLevelPlugin, createTLogLineMatcherPlugin, createTLogLinkActionPlugin, createTLogOsc8LinkPlugin, createTLogUrlPlugin, detectTLogUrls, dispatchTLogPluginLinkAction, getTLogPluginMetadata, parseTLogAnnotatedText, resolveTLogLinksPanelTheme, resolveTLogMinimapTheme, resolveTLogScrollbarTheme, resolveTLogSearchBarTheme, resolveTLogSearchPagerTheme, resolveTLogSearchResultsTheme, resolveTLogViewTheme, stripTLogAnsiText, tlogDarkPreset, tlogDarkTheme, tlogDefaultPreset, tlogDefaultTheme, tlogHighContrastPreset, tlogHighContrastTheme, toTLogExternalLinkFromVisibleLink, useTLogLinkController, useTLogRetainedIndex, useTLogSearchController, useTLogSearchResultsPage, useTLogVirtualSearchResults } from "./tlog-theme-CopRt9SC.js";
16
+ import { computed, defineComponent, getCurrentInstance, h, inject, markRaw, onBeforeUnmount, shallowRef, watch } from "vue";
13
17
 
18
+ //#region src/vue/components/TAgentTerminalGraphic.ts
19
+ const NO_GRAPHICS_CAPABILITIES = Object.freeze({
20
+ supported: false,
21
+ kitty: false,
22
+ iterm2: false,
23
+ sixel: false,
24
+ preferredProtocol: null,
25
+ protocol: "unicode",
26
+ candidates: [],
27
+ stdoutIsTTY: false,
28
+ insideTmux: false,
29
+ insideScreen: false,
30
+ insideZellij: false,
31
+ multiplexer: null,
32
+ passthrough: false,
33
+ forced: false,
34
+ reason: "no-terminal-graphics-output"
35
+ });
36
+ function splitTextOutput(value) {
37
+ const normalized = sanitizeTextBlock(sanitizeTerminalFallbackText(value).replace(/\r\n?/g, "\n"));
38
+ const lines = normalized.split("\n");
39
+ return lines.length ? lines : [""];
40
+ }
41
+ function hasVisibleOutput(value) {
42
+ return value.some((line) => line.trim().length > 0);
43
+ }
44
+ function errorMessage(error) {
45
+ return error instanceof Error ? error.message : String(error);
46
+ }
47
+ function positiveInt$1(value) {
48
+ const n = Math.floor(Number(value));
49
+ return Number.isFinite(n) && n > 0 ? n : void 0;
50
+ }
51
+ function finiteInt(value) {
52
+ const n = Math.floor(Number(value));
53
+ return Number.isFinite(n) ? n : void 0;
54
+ }
55
+ function clampNumber(value, min, max) {
56
+ return Math.max(min, Math.min(max, value));
57
+ }
58
+ function rectArea(rect) {
59
+ return Math.max(0, rect.w) * Math.max(0, rect.h);
60
+ }
61
+ function sameRect(a, b) {
62
+ return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
63
+ }
64
+ function subtractRect(rect, cover) {
65
+ const hit = intersectRect(rect, cover);
66
+ if (!hit) return [rect];
67
+ const out = [];
68
+ const rectRight = rect.x + rect.w;
69
+ const rectBottom = rect.y + rect.h;
70
+ const hitRight = hit.x + hit.w;
71
+ const hitBottom = hit.y + hit.h;
72
+ if (hit.y > rect.y) out.push({
73
+ x: rect.x,
74
+ y: rect.y,
75
+ w: rect.w,
76
+ h: hit.y - rect.y
77
+ });
78
+ if (hitBottom < rectBottom) out.push({
79
+ x: rect.x,
80
+ y: hitBottom,
81
+ w: rect.w,
82
+ h: rectBottom - hitBottom
83
+ });
84
+ if (hit.x > rect.x) out.push({
85
+ x: rect.x,
86
+ y: hit.y,
87
+ w: hit.x - rect.x,
88
+ h: hit.h
89
+ });
90
+ if (hitRight < rectRight) out.push({
91
+ x: hitRight,
92
+ y: hit.y,
93
+ w: rectRight - hitRight,
94
+ h: hit.h
95
+ });
96
+ return out.filter((part) => part.w > 0 && part.h > 0);
97
+ }
98
+ function largestUncoveredRect(rect, covers) {
99
+ let parts = [rect];
100
+ for (const cover of covers) {
101
+ parts = parts.flatMap((part) => subtractRect(part, cover));
102
+ if (!parts.length) return null;
103
+ }
104
+ parts.sort((a, b) => rectArea(b) - rectArea(a) || a.y - b.y || a.x - b.x);
105
+ return parts[0] ?? null;
106
+ }
107
+ function parseKittyClearControls(sequence) {
108
+ const prefix = "\x1B_G";
109
+ const terminator = "\x1B\\";
110
+ if (!sequence.startsWith(prefix) || !sequence.endsWith(terminator)) return null;
111
+ const body = sequence.slice(prefix.length, -terminator.length);
112
+ if (body.includes(terminator) || body.includes("\x1B") || body.includes("\x07")) return null;
113
+ const semicolon = body.indexOf(";");
114
+ const rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body;
115
+ const controls = new Map();
116
+ for (const part of rawControls.split(",")) {
117
+ const eq = part.indexOf("=");
118
+ if (eq <= 0) return null;
119
+ controls.set(part.slice(0, eq), part.slice(eq + 1));
120
+ }
121
+ return controls;
122
+ }
123
+ function kittyClearTargetsComponent(sequence, imageId, placementId) {
124
+ const controls = parseKittyClearControls(sequence);
125
+ if (!controls) return false;
126
+ const mode = controls.get("d");
127
+ if (mode !== "i" && mode !== "I") return false;
128
+ return controls.get("i") === String(imageId) && controls.get("p") === String(placementId);
129
+ }
130
+ function isSafeComponentClearSequence(sequence, protocol, imageId, placementId) {
131
+ if (!isSafeTerminalGraphicsSequence(sequence, protocol, "clear")) return false;
132
+ return protocol !== "kitty" || kittyClearTargetsComponent(sequence, imageId, placementId);
133
+ }
134
+ let textEncoder = null;
135
+ function stringByteLength(value) {
136
+ if (typeof TextEncoder !== "undefined") {
137
+ textEncoder ?? (textEncoder = new TextEncoder());
138
+ return textEncoder.encode(value).length;
139
+ }
140
+ let bytes = 0;
141
+ for (let index = 0; index < value.length; index++) {
142
+ const code = value.charCodeAt(index);
143
+ if (code <= 127) bytes += 1;
144
+ else if (code <= 2047) bytes += 2;
145
+ else if (code >= 55296 && code <= 56319 && index + 1 < value.length) {
146
+ bytes += 4;
147
+ index++;
148
+ } else bytes += 3;
149
+ }
150
+ return bytes;
151
+ }
152
+ function smallHash(input) {
153
+ let hash = 2166136261;
154
+ for (let i = 0; i < input.length; i++) {
155
+ hash ^= input.charCodeAt(i);
156
+ hash = Math.imul(hash, 16777619);
157
+ }
158
+ return (hash >>> 0).toString(36);
159
+ }
160
+ const tAgentTerminalGraphicProps = {
161
+ x: {
162
+ type: Number,
163
+ required: true
164
+ },
165
+ y: {
166
+ type: Number,
167
+ required: true
168
+ },
169
+ w: {
170
+ type: Number,
171
+ required: true
172
+ },
173
+ h: {
174
+ type: Number,
175
+ default: void 0
176
+ },
177
+ zIndex: {
178
+ type: Number,
179
+ default: 0
180
+ },
181
+ content: {
182
+ type: String,
183
+ required: true
184
+ },
185
+ kind: {
186
+ type: String,
187
+ default: "image"
188
+ },
189
+ fallback: {
190
+ type: String,
191
+ default: void 0
192
+ },
193
+ style: {
194
+ type: Object,
195
+ default: void 0
196
+ },
197
+ loadingStyle: {
198
+ type: Object,
199
+ default: void 0
200
+ },
201
+ errorStyle: {
202
+ type: Object,
203
+ default: void 0
204
+ },
205
+ clear: {
206
+ type: Boolean,
207
+ default: true
208
+ },
209
+ final: {
210
+ type: Boolean,
211
+ default: true
212
+ },
213
+ streaming: {
214
+ type: Boolean,
215
+ default: false
216
+ },
217
+ renderer: {
218
+ type: Function,
219
+ default: void 0
220
+ },
221
+ loadingText: {
222
+ type: String,
223
+ default: "Rendering terminal graphic..."
224
+ },
225
+ deferRenderUntilVisible: {
226
+ type: Boolean,
227
+ default: true
228
+ },
229
+ suspendRawWhileScrolling: {
230
+ type: Boolean,
231
+ default: true
232
+ },
233
+ suspendRenderWhileScrolling: {
234
+ type: Boolean,
235
+ default: true
236
+ },
237
+ scrolling: {
238
+ type: Boolean,
239
+ default: false
240
+ },
241
+ scrollVersion: {
242
+ type: Number,
243
+ default: 0
244
+ },
245
+ placementMoveWithoutClear: {
246
+ type: Boolean,
247
+ default: false
248
+ },
249
+ suspended: {
250
+ type: Boolean,
251
+ default: false
252
+ },
253
+ retainRawWhileCovered: {
254
+ type: Boolean,
255
+ default: false
256
+ },
257
+ ignoreRawCoverage: {
258
+ type: Boolean,
259
+ default: false
260
+ },
261
+ ignoreSamePlaneRawCoverage: {
262
+ type: Boolean,
263
+ default: false
264
+ },
265
+ cacheKey: {
266
+ type: String,
267
+ default: void 0
268
+ },
269
+ placementKey: {
270
+ type: String,
271
+ default: void 0
272
+ },
273
+ trace: {
274
+ type: Function,
275
+ default: void 0
276
+ }
277
+ };
278
+ function terminalDrawKey(current, rect, clearSequence, resizeSequence) {
279
+ return [
280
+ current.protocol,
281
+ rect.x,
282
+ rect.y,
283
+ rect.w,
284
+ rect.h,
285
+ current.sequenceHash,
286
+ clearSequence === current.clearSequence ? current.clearSequenceHash ?? "" : smallHash(clearSequence ?? ""),
287
+ resizeSequence === current.resizeSequence ? current.resizeSequenceHash ?? "" : smallHash(resizeSequence ?? "")
288
+ ].join(":");
289
+ }
290
+ const TAgentTerminalGraphic = defineComponent({
291
+ name: "TAgentTerminalGraphic",
292
+ props: tAgentTerminalGraphicProps,
293
+ setup(props) {
294
+ const instance = getCurrentInstance();
295
+ const { terminal, defaultStyle, scheduler, widthProvider, render } = useTerminal();
296
+ const layout = useLayout();
297
+ const { visible, rootProps } = useVisibility();
298
+ const graphicsActivity = inject(TerminalGraphicsActivityKey, null);
299
+ const status = shallowRef("idle");
300
+ const error = shallowRef("");
301
+ const graphic = shallowRef(null);
302
+ const documentVersion = shallowRef(0);
303
+ let builtOnce = false;
304
+ let renderVersion = 0;
305
+ let renderAbort = null;
306
+ let alive = true;
307
+ let lastRenderedContent = "";
308
+ let lastRenderRawVisible = false;
309
+ let lastRenderProtocol = null;
310
+ let lastRenderGraphicsOutputVersion = 0;
311
+ const rawIdSeed = props.placementKey ? `placement:${props.placementKey}` : props.cacheKey ? `cache:${props.cacheKey}` : `instance:${instance?.uid ?? "unknown"}`;
312
+ const rawId = `TAgentTerminalGraphic:${smallHash(rawIdSeed)}`;
313
+ const frameTaskId = `${rawId}:render`;
314
+ const lastDrawnGraphic = shallowRef(null);
315
+ const rawClearPendingRepaint = shallowRef(null);
316
+ const rawDrawRejectedKey = shallowRef(null);
317
+ const reservedTerminalGraphicSize = shallowRef(null);
318
+ const terminalSizeVersion = shallowRef(0);
319
+ const renderNodeId = shallowRef(null);
320
+ let lastRawSkipScrollKey = "";
321
+ let lastDeferTraceKey = "";
322
+ const isParentScrolling = computed(() => props.scrolling || Boolean(graphicsActivity?.scrolling.value));
323
+ const graphicsActivityVersion = computed(() => (graphicsActivity?.version.value ?? 0) + Math.floor(Number(props.scrollVersion ?? 0)));
324
+ const graphicsOutput = () => getTerminalGraphicsOutput(terminal);
325
+ const graphicsOutputVersion = shallowRef(getTerminalGraphicsOutputVersion(terminal));
326
+ const unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
327
+ graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
328
+ });
329
+ const unsubscribeTerminalResize = terminal.on("resize", () => {
330
+ terminalSizeVersion.value++;
331
+ });
332
+ const fallbackText = () => props.fallback ?? (props.kind === "math" ? props.content : "");
333
+ const contentIdentity = computed(() => `${props.content.length}:${smallHash(props.content)}`);
334
+ const stableGraphicKey = computed(() => [
335
+ rawIdSeed,
336
+ props.cacheKey ?? "",
337
+ props.kind,
338
+ contentIdentity.value,
339
+ props.w,
340
+ props.h ?? "",
341
+ props.final ? "final" : "draft"
342
+ ].join(""));
343
+ const imageId = computed(() => stableTerminalGraphicNumericId(`image:${stableGraphicKey.value}`));
344
+ const placementId = computed(() => stableTerminalGraphicNumericId(`placement:${stableGraphicKey.value}`));
345
+ function rememberTerminalGraphicSize(current) {
346
+ if (current.type !== "terminal") return;
347
+ const rows = positiveInt$1(current.rows);
348
+ if (!rows) return;
349
+ reservedTerminalGraphicSize.value = {
350
+ key: stableGraphicKey.value,
351
+ rows
352
+ };
353
+ }
354
+ function bump() {
355
+ documentVersion.value++;
356
+ }
357
+ function currentCapabilities() {
358
+ return graphicsOutput()?.capabilities ?? NO_GRAPHICS_CAPABILITIES;
359
+ }
360
+ function trace(type, extra = {}) {
361
+ const capabilities = currentCapabilities();
362
+ try {
363
+ props.trace?.({
364
+ type,
365
+ id: rawId,
366
+ kind: props.kind,
367
+ protocol: capabilities.protocol,
368
+ contentHash: smallHash(props.content),
369
+ ...extra
370
+ });
371
+ } catch {}
372
+ const protocol = isTerminalGraphicsProtocol(capabilities.protocol) ? capabilities.protocol : void 0;
373
+ const key = props.cacheKey ?? smallHash(props.content);
374
+ if (type === "render-start") recordTerminalGraphicTrace({
375
+ type: "renderer-start",
376
+ id: rawId,
377
+ key,
378
+ protocol
379
+ });
380
+ else if (type === "render-end") recordTerminalGraphicTrace({
381
+ type: extra.reason ? "renderer-error" : "renderer-end",
382
+ id: rawId,
383
+ key,
384
+ protocol,
385
+ durationMs: extra.durationMs,
386
+ bytes: extra.sequenceBytes,
387
+ error: extra.reason
388
+ });
389
+ else if (type === "defer") recordTerminalGraphicTrace({
390
+ type: extra.reason === "scrolling" ? "skip-scrolling" : "skip-hidden",
391
+ id: rawId,
392
+ key,
393
+ protocol,
394
+ reason: extra.reason
395
+ });
396
+ else if (type === "raw-draw") {} else if (type === "render-abort") recordTerminalGraphicTrace({
397
+ type: "renderer-abort",
398
+ id: rawId,
399
+ key,
400
+ protocol,
401
+ reason: extra.reason
402
+ });
403
+ else if (type === "raw-clear") recordTerminalGraphicTrace({
404
+ type: "clear",
405
+ id: rawId,
406
+ key,
407
+ protocol
408
+ });
409
+ else if (type === "raw-skip-scroll") recordTerminalGraphicTrace({
410
+ type: "skip-scrolling",
411
+ id: rawId,
412
+ key,
413
+ protocol,
414
+ reason: extra.reason
415
+ });
416
+ }
417
+ function traceDeferOnce(reason) {
418
+ const key = [
419
+ reason,
420
+ graphicsActivityVersion.value,
421
+ stableGraphicKey.value
422
+ ].join(":");
423
+ if (lastDeferTraceKey === key) return;
424
+ lastDeferTraceKey = key;
425
+ trace("defer", { reason });
426
+ }
427
+ function abortCurrentRender(reason) {
428
+ if (!renderAbort) return;
429
+ renderAbort.abort();
430
+ renderAbort = null;
431
+ trace("render-abort", { reason });
432
+ }
433
+ function normalizeResult(result) {
434
+ if (result == null) return {
435
+ type: "text",
436
+ text: fallbackText()
437
+ };
438
+ if (typeof result === "string") return {
439
+ type: "text",
440
+ text: result
441
+ };
442
+ if (typeof result !== "object") return {
443
+ type: "text",
444
+ text: fallbackText()
445
+ };
446
+ if ("type" in result && result.type === "text") return {
447
+ type: "text",
448
+ text: result.text
449
+ };
450
+ const maybeRaw = result;
451
+ const isRawCandidate = maybeRaw.type === "sequence" || "sequence" in result || "protocol" in result;
452
+ if (!isRawCandidate && "text" in result) return {
453
+ type: "text",
454
+ text: result.text
455
+ };
456
+ const sequence = typeof maybeRaw.sequence === "string" ? maybeRaw.sequence : "";
457
+ const protocol = isTerminalGraphicsProtocol(maybeRaw.protocol) ? maybeRaw.protocol : null;
458
+ const fallback = typeof maybeRaw.fallback === "string" ? sanitizeTerminalFallbackText(maybeRaw.fallback) : fallbackText();
459
+ const fallbackFromProps = typeof maybeRaw.fallback !== "string";
460
+ if (!sequence || !protocol || !isSafeTerminalGraphicsSequence(sequence, protocol, "draw")) return {
461
+ type: "text",
462
+ text: fallback
463
+ };
464
+ const rawClear = typeof maybeRaw.clearSequence === "string" ? maybeRaw.clearSequence : void 0;
465
+ const clearSequence = rawClear && isSafeComponentClearSequence(rawClear, protocol, imageId.value, placementId.value) ? rawClear : void 0;
466
+ const rawResize = typeof maybeRaw.resizeSequence === "string" ? maybeRaw.resizeSequence : void 0;
467
+ const resizeSequence = rawResize && isSafeTerminalGraphicsSequence(rawResize, protocol, "draw") ? rawResize : void 0;
468
+ const declaredRows = positiveInt$1(maybeRaw.rows);
469
+ const declaredCols = positiveInt$1(maybeRaw.cols);
470
+ const sourceWidth = positiveInt$1(maybeRaw.sourceWidth);
471
+ const sourceHeight = positiveInt$1(maybeRaw.sourceHeight);
472
+ const zIndex = finiteInt(maybeRaw.zIndex);
473
+ const declaredSize = declaredRows == null ? null : normalizeTerminalGraphicSize(declaredCols ?? props.w, declaredRows);
474
+ return {
475
+ type: "terminal",
476
+ protocol,
477
+ sequence,
478
+ sequenceHash: smallHash(sequence),
479
+ sequenceBytes: stringByteLength(sequence),
480
+ fallback,
481
+ fallbackFromProps,
482
+ clearSequence,
483
+ clearSequenceHash: clearSequence ? smallHash(clearSequence) : void 0,
484
+ resizeSequence,
485
+ resizeSequenceHash: resizeSequence ? smallHash(resizeSequence) : void 0,
486
+ cols: declaredRows == null ? declaredCols : declaredSize?.width,
487
+ rows: declaredSize?.height,
488
+ sourceWidth,
489
+ sourceHeight,
490
+ zIndex
491
+ };
492
+ }
493
+ function defaultClearSequence(protocol) {
494
+ return protocol === "kitty" ? createKittyDeleteGraphicsSequence({
495
+ imageId: imageId.value,
496
+ placementId: placementId.value
497
+ }) : "";
498
+ }
499
+ function resolveClearSequence(current) {
500
+ if (current.clearSequence) return current.clearSequence;
501
+ const candidate = defaultClearSequence(current.protocol);
502
+ if (!candidate) return void 0;
503
+ return isSafeComponentClearSequence(candidate, current.protocol, imageId.value, placementId.value) ? candidate : void 0;
504
+ }
505
+ function resolveResizeSequence(current, rect, full) {
506
+ if (current.protocol !== "kitty") return current.resizeSequence;
507
+ const sourceWidth = positiveInt$1(current.sourceWidth);
508
+ const sourceHeight = positiveInt$1(current.sourceHeight);
509
+ if (!sourceWidth || !sourceHeight || full.w <= 0 || full.h <= 0) return current.resizeSequence;
510
+ const offsetX = Math.max(0, rect.x - full.x);
511
+ const offsetY = Math.max(0, rect.y - full.y);
512
+ const visibleW = Math.max(0, Math.min(rect.w, full.w - offsetX));
513
+ const visibleH = Math.max(0, Math.min(rect.h, full.h - offsetY));
514
+ const x0 = clampNumber(Math.floor(offsetX * sourceWidth / full.w), 0, sourceWidth - 1);
515
+ const y0 = clampNumber(Math.floor(offsetY * sourceHeight / full.h), 0, sourceHeight - 1);
516
+ const x1 = Math.max(x0 + 1, clampNumber(Math.ceil((offsetX + visibleW) * sourceWidth / full.w), 1, sourceWidth));
517
+ const y1 = Math.max(y0 + 1, clampNumber(Math.ceil((offsetY + visibleH) * sourceHeight / full.h), 1, sourceHeight));
518
+ return createKittyPlacementSequence({
519
+ imageId: imageId.value,
520
+ placementId: placementId.value,
521
+ columns: rect.w,
522
+ rows: rect.h,
523
+ sourceX: x0,
524
+ sourceY: y0,
525
+ sourceWidth: x1 - x0,
526
+ sourceHeight: y1 - y0,
527
+ zIndex: current.zIndex
528
+ });
529
+ }
530
+ function queueClearLastGraphic(options = {}) {
531
+ const previous = lastDrawnGraphic.value;
532
+ if (!previous) return false;
533
+ const output = graphicsOutput();
534
+ let accepted = false;
535
+ if (output?.clear && !previous.retainOnClear) try {
536
+ accepted = Boolean(output.clear(previous.id));
537
+ } catch {
538
+ accepted = false;
539
+ }
540
+ if (!accepted && output && previous.clearSequence) try {
541
+ accepted = output.queue({
542
+ id: previous.id,
543
+ x: previous.x,
544
+ y: previous.y,
545
+ w: previous.w,
546
+ h: previous.h,
547
+ protocol: previous.protocol,
548
+ sequence: previous.clearSequence,
549
+ deferFlush: true,
550
+ retainOnClear: previous.retainOnClear,
551
+ op: "clear"
552
+ });
553
+ } catch {
554
+ accepted = false;
555
+ }
556
+ if (accepted) {
557
+ if (options.markPendingRepaint ?? true) rawClearPendingRepaint.value = previous;
558
+ lastDrawnGraphic.value = null;
559
+ trace("raw-clear", {
560
+ x: previous.x,
561
+ y: previous.y,
562
+ w: previous.w,
563
+ h: previous.h
564
+ });
565
+ }
566
+ return accepted;
567
+ }
568
+ function queueDrawGraphic(output, current, rect, full = rect, options = {}) {
569
+ const clearSequence = resolveClearSequence(current);
570
+ const resizeSequence = resolveResizeSequence(current, rect, full);
571
+ const drawKey = terminalDrawKey(current, rect, clearSequence, resizeSequence);
572
+ const activePrevious = lastDrawnGraphic.value;
573
+ const retainedPrevious = rawClearPendingRepaint.value;
574
+ const previous = activePrevious ?? retainedPrevious;
575
+ const previousIsRetained = activePrevious == null && retainedPrevious != null;
576
+ const previousStillActive = previous ? typeof output.isActive === "function" ? output.isActive(previous.id) : true : false;
577
+ if (!previousIsRetained && !options.force && previous?.drawKey === drawKey && previousStillActive) return false;
578
+ const canReusePlacementSequence = previousStillActive && previous?.protocol === current.protocol && previous.sequenceHash === current.sequenceHash && current.protocol === "kitty" && Boolean(resizeSequence);
579
+ const scrollVersion = Math.floor(Number(props.scrollVersion ?? 0));
580
+ const canMoveWithoutClear = canReusePlacementSequence && Boolean(options.placementMoveWithoutClear);
581
+ if (!previousIsRetained && previousStillActive && !resizeSequence && previous?.protocol === current.protocol && previous.sequenceHash === current.sequenceHash && previous.x === rect.x && previous.y === rect.y && rect.w <= previous.w && rect.h <= previous.h && (options.force || !sameRect(rect, full))) {
582
+ lastDrawnGraphic.value = {
583
+ ...previous,
584
+ w: rect.w,
585
+ h: rect.h,
586
+ clearSequence,
587
+ resizeSequence,
588
+ drawKey,
589
+ activityVersion: graphicsActivityVersion.value,
590
+ scrollVersion
591
+ };
592
+ lastRawSkipScrollKey = "";
593
+ return false;
594
+ }
595
+ if (previousStillActive && !previousIsRetained && !canReusePlacementSequence) {
596
+ if (!queueClearLastGraphic({ markPendingRepaint: false })) return false;
597
+ } else if (previous) {
598
+ if (!previousStillActive) {
599
+ lastDrawnGraphic.value = null;
600
+ rawClearPendingRepaint.value = null;
601
+ }
602
+ }
603
+ let accepted = false;
604
+ try {
605
+ accepted = output.queue({
606
+ id: rawId,
607
+ x: rect.x,
608
+ y: rect.y,
609
+ w: rect.w,
610
+ h: rect.h,
611
+ protocol: current.protocol,
612
+ sequence: canReusePlacementSequence && resizeSequence ? resizeSequence : current.sequence,
613
+ resizeSequence,
614
+ clearSequence,
615
+ resizeRedraw: canReusePlacementSequence,
616
+ placementMoveWithoutClear: canMoveWithoutClear,
617
+ allowTextOverlay: options.allowTextOverlay,
618
+ forceDraw: options.force,
619
+ deferFlush: options.deferFlush ?? true,
620
+ fallbackText: current.fallback
621
+ });
622
+ } catch {
623
+ accepted = false;
624
+ }
625
+ if (!accepted) {
626
+ lastDrawnGraphic.value = null;
627
+ if (rawDrawRejectedKey.value !== drawKey) {
628
+ rawDrawRejectedKey.value = drawKey;
629
+ scheduler.invalidate({
630
+ priority: "low",
631
+ reason: "data"
632
+ });
633
+ }
634
+ return false;
635
+ }
636
+ rawDrawRejectedKey.value = null;
637
+ rawClearPendingRepaint.value = null;
638
+ lastDrawnGraphic.value = {
639
+ id: rawId,
640
+ x: rect.x,
641
+ y: rect.y,
642
+ w: rect.w,
643
+ h: rect.h,
644
+ protocol: current.protocol,
645
+ sequenceHash: current.sequenceHash,
646
+ clearSequence,
647
+ resizeSequence,
648
+ retainOnClear: Boolean(props.cacheKey && resizeSequence),
649
+ drawKey,
650
+ activityVersion: graphicsActivityVersion.value,
651
+ scrollVersion
652
+ };
653
+ lastRawSkipScrollKey = "";
654
+ return true;
655
+ }
656
+ function hasRetainedActiveRawGraphic() {
657
+ const output = graphicsOutput();
658
+ return Boolean(status.value === "loading" && !graphic.value && output && typeof output.isActive === "function" && output.isActive(rawId));
659
+ }
660
+ const showingInitialLoadingText = computed(() => status.value === "loading" && !graphic.value && !hasRetainedActiveRawGraphic());
661
+ const fullRect = computed(() => {
662
+ const current = graphic.value;
663
+ const reserved = reservedTerminalGraphicSize.value;
664
+ const reservedRows = current?.type === "terminal" ? void 0 : status.value === "idle" && reserved?.key === stableGraphicKey.value ? reserved.rows : void 0;
665
+ const textLines = current?.type === "text" ? splitTextOutput(current.text) : splitTextOutput(fallbackText());
666
+ const height = props.h ?? (current?.type === "terminal" ? current.rows : void 0) ?? reservedRows ?? Math.max(1, textLines.length);
667
+ return translateRect({
668
+ x: props.x,
669
+ y: props.y,
670
+ w: props.w,
671
+ h: height
672
+ }, layout.originX, layout.originY);
673
+ });
674
+ const absRect = computed(() => {
675
+ terminalSizeVersion.value;
676
+ const translated = fullRect.value;
677
+ const size = terminal.size();
678
+ const terminalClip = {
679
+ x: 0,
680
+ y: 0,
681
+ w: Math.max(0, Math.floor(size.cols)),
682
+ h: Math.max(0, Math.floor(size.rows))
683
+ };
684
+ const clip = layout.clipRect ? intersectRect(layout.clipRect, terminalClip) : terminalClip;
685
+ if (!clip) return {
686
+ x: 0,
687
+ y: 0,
688
+ w: 0,
689
+ h: 0
690
+ };
691
+ return intersectRect(translated, clip) ?? {
692
+ x: 0,
693
+ y: 0,
694
+ w: 0,
695
+ h: 0
696
+ };
697
+ });
698
+ const renderRect = computed(() => absRect.value);
699
+ function rawRectFitsTerminalViewport(rect) {
700
+ return canDrawTerminalGraphicRect(rect, terminal.size());
701
+ }
702
+ function rawCoveredByHigherRenderNode(rect = fullRect.value) {
703
+ if (props.retainRawWhileCovered) return false;
704
+ const id = renderNodeId.value;
705
+ return !props.ignoreRawCoverage && id != null && render.isRectCoveredByHigherNode(id, rect, { ignoreSamePlane: props.ignoreSamePlaneRawCoverage });
706
+ }
707
+ function retainedRawCoveredByHigherRenderNode(rect) {
708
+ if (!props.retainRawWhileCovered) return false;
709
+ const id = renderNodeId.value;
710
+ return Boolean(id != null && render.isRectCoveredByHigherNode(id, rect, { ignoreSamePlane: props.ignoreSamePlaneRawCoverage }));
711
+ }
712
+ function rawUncoveredRenderRect(rect) {
713
+ if (props.retainRawWhileCovered) return rect;
714
+ const id = renderNodeId.value;
715
+ if (id == null) return rect;
716
+ const covers = render.higherNodeCoverageRects(id, rect, { ignoreSamePlane: props.ignoreSamePlaneRawCoverage });
717
+ if (!covers.length) return rect;
718
+ if (!props.ignoreRawCoverage) return null;
719
+ return largestUncoveredRect(rect, covers);
720
+ }
721
+ const rawCanRender = computed(() => {
722
+ graphicsOutputVersion.value;
723
+ terminalSizeVersion.value;
724
+ const current = graphic.value;
725
+ const output = graphicsOutput();
726
+ const rect = absRect.value;
727
+ return current?.type === "terminal" && rawRectFitsTerminalViewport(rect) && Boolean(output?.capabilities.supported) && output?.capabilities.preferredProtocol === current.protocol;
728
+ });
729
+ const rawOutputCanRenderValue = computed(() => {
730
+ graphicsOutputVersion.value;
731
+ terminalSizeVersion.value;
732
+ return rawOutputCanRender();
733
+ });
734
+ const rawSuppressedByScroll = computed(() => props.suspended || props.suspendRawWhileScrolling && isParentScrolling.value);
735
+ const rawCanQueue = computed(() => rawCanRender.value && !rawSuppressedByScroll.value);
736
+ function traceRawSkipScrollOnce(reason) {
737
+ const r = absRect.value;
738
+ const key = [
739
+ reason,
740
+ graphicsActivityVersion.value,
741
+ stableGraphicKey.value,
742
+ r.x,
743
+ r.y,
744
+ r.w,
745
+ r.h
746
+ ].join(":");
747
+ if (lastRawSkipScrollKey === key) return;
748
+ lastRawSkipScrollKey = key;
749
+ trace("raw-skip-scroll", { reason });
750
+ }
751
+ function hasPaintableRect() {
752
+ const r = absRect.value;
753
+ return visible.value && r.w > 0 && r.h > 0;
754
+ }
755
+ function rawOutputCanRender() {
756
+ const output = graphicsOutput();
757
+ const rect = absRect.value;
758
+ return rawRectFitsTerminalViewport(rect) && Boolean(output?.capabilities.supported);
759
+ }
760
+ function renderDeferReason() {
761
+ if (props.suspended) return "suspended";
762
+ if (props.deferRenderUntilVisible && !hasPaintableRect()) return "not-visible";
763
+ if (props.suspendRenderWhileScrolling && isParentScrolling.value) return "scrolling";
764
+ return null;
765
+ }
766
+ function shouldDeferRender() {
767
+ return renderDeferReason() != null;
768
+ }
769
+ function shouldRerenderForGraphicsOutputChange() {
770
+ if (!props.renderer) return false;
771
+ if (!props.content.trim()) return false;
772
+ if (shouldDeferRender()) return false;
773
+ if (rawSuppressedByScroll.value) return false;
774
+ const protocol = currentCapabilities().protocol;
775
+ return lastRenderProtocol != null && (lastRenderProtocol !== protocol || lastRenderGraphicsOutputVersion !== graphicsOutputVersion.value);
776
+ }
777
+ function shouldRetryTemporaryRawFallback(rawCovered = rawCoveredByHigherRenderNode()) {
778
+ return Boolean(props.renderer) && props.content.trim().length > 0 && graphic.value?.type === "text" && status.value !== "loading" && !lastRenderRawVisible && rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCovered;
779
+ }
780
+ function setDeferredFallback(content) {
781
+ graphic.value = {
782
+ type: "text",
783
+ text: content.trim() ? fallbackText() : ""
784
+ };
785
+ lastRenderedContent = content;
786
+ status.value = "idle";
787
+ error.value = "";
788
+ bump();
789
+ }
790
+ function resolveRendererContext(signal) {
791
+ const capabilities = currentCapabilities();
792
+ const visibleNow = hasPaintableRect();
793
+ const rawVisible = rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCoveredByHigherRenderNode();
794
+ return {
795
+ kind: props.kind,
796
+ width: props.w,
797
+ height: props.h,
798
+ final: props.final,
799
+ streaming: props.streaming,
800
+ protocol: capabilities.protocol,
801
+ capabilities,
802
+ signal,
803
+ imageId: imageId.value,
804
+ placementId: placementId.value,
805
+ visible: visibleNow,
806
+ rawVisible,
807
+ scrolling: isParentScrolling.value,
808
+ cacheKey: props.cacheKey,
809
+ viewport: {
810
+ visible: visibleNow,
811
+ rawVisible,
812
+ scrolling: isParentScrolling.value,
813
+ rect: absRect.value,
814
+ fullRect: fullRect.value
815
+ }
816
+ };
817
+ }
818
+ async function renderNow(version) {
819
+ const protocol = currentCapabilities().protocol;
820
+ recordTerminalGraphicTrace({
821
+ type: "request",
822
+ id: rawId,
823
+ key: props.cacheKey ?? smallHash(props.content),
824
+ protocol: isTerminalGraphicsProtocol(protocol) ? protocol : void 0
825
+ });
826
+ const content = props.content;
827
+ if (!content.trim()) {
828
+ abortCurrentRender("superseded");
829
+ if (!alive || version !== renderVersion) return;
830
+ graphic.value = {
831
+ type: "text",
832
+ text: ""
833
+ };
834
+ lastRenderedContent = content;
835
+ status.value = "ready";
836
+ error.value = "";
837
+ bump();
838
+ return;
839
+ }
840
+ const renderer = props.renderer;
841
+ if (!renderer) {
842
+ abortCurrentRender("superseded");
843
+ if (!alive || version !== renderVersion) return;
844
+ graphic.value = {
845
+ type: "text",
846
+ text: fallbackText()
847
+ };
848
+ lastRenderedContent = content;
849
+ status.value = "ready";
850
+ error.value = "";
851
+ bump();
852
+ return;
853
+ }
854
+ const deferred = renderDeferReason();
855
+ if (deferred) {
856
+ abortCurrentRender(deferred);
857
+ if (!alive || version !== renderVersion) return;
858
+ setDeferredFallback(content);
859
+ traceDeferOnce(deferred);
860
+ return;
861
+ }
862
+ abortCurrentRender("superseded");
863
+ lastDeferTraceKey = "";
864
+ const abort = new AbortController();
865
+ renderAbort = abort;
866
+ const startedAt = nowTerminalGraphicTraceTime();
867
+ status.value = "loading";
868
+ error.value = "";
869
+ trace("render-start");
870
+ bump();
871
+ try {
872
+ const contextGraphicsOutputVersion = graphicsOutputVersion.value;
873
+ const context = resolveRendererContext(abort.signal);
874
+ lastRenderRawVisible = context.rawVisible;
875
+ lastRenderProtocol = context.protocol;
876
+ lastRenderGraphicsOutputVersion = contextGraphicsOutputVersion;
877
+ const result = await renderer(content, context);
878
+ if (abort.signal.aborted) return;
879
+ if (!alive || version !== renderVersion) return;
880
+ const normalized = normalizeResult(result);
881
+ rememberTerminalGraphicSize(normalized);
882
+ graphic.value = normalized;
883
+ lastRenderedContent = content;
884
+ status.value = "ready";
885
+ error.value = "";
886
+ trace("render-end", {
887
+ durationMs: nowTerminalGraphicTraceTime() - startedAt,
888
+ sequenceChars: normalized.type === "terminal" ? normalized.sequence.length : 0,
889
+ sequenceBytes: normalized.type === "terminal" ? normalized.sequenceBytes : 0
890
+ });
891
+ bump();
892
+ if (normalized.type === "terminal") scheduler.invalidate({
893
+ priority: "low",
894
+ reason: "data"
895
+ });
896
+ } catch (err) {
897
+ if (abort.signal.aborted) return;
898
+ if (!alive || version !== renderVersion) return;
899
+ graphic.value = {
900
+ type: "text",
901
+ text: fallbackText()
902
+ };
903
+ lastRenderedContent = content;
904
+ status.value = "ready";
905
+ error.value = errorMessage(err);
906
+ trace("render-end", {
907
+ durationMs: nowTerminalGraphicTraceTime() - startedAt,
908
+ reason: error.value
909
+ });
910
+ bump();
911
+ } finally {
912
+ if (renderAbort === abort) renderAbort = null;
913
+ }
914
+ }
915
+ function scheduleRender(options = {}) {
916
+ const version = ++renderVersion;
917
+ if (options.clearLastGraphic ?? true) queueClearLastGraphic();
918
+ if (!builtOnce || !props.streaming) {
919
+ builtOnce = true;
920
+ renderNow(version);
921
+ return;
922
+ }
923
+ const accepted = scheduler.queueFrameTask({
924
+ id: frameTaskId,
925
+ reason: "stream",
926
+ priority: "low",
927
+ sync: false,
928
+ run: () => {
929
+ if (!alive) return;
930
+ if (version !== renderVersion) return;
931
+ renderNow(version);
932
+ }
933
+ });
934
+ if (accepted === false) renderNow(version);
935
+ }
936
+ watch([
937
+ () => props.content,
938
+ () => props.kind,
939
+ () => props.renderer,
940
+ () => props.w,
941
+ () => props.h,
942
+ () => props.streaming,
943
+ () => props.final,
944
+ () => props.deferRenderUntilVisible,
945
+ () => props.suspendRawWhileScrolling,
946
+ () => props.suspendRenderWhileScrolling,
947
+ () => props.scrolling,
948
+ () => props.suspended,
949
+ () => props.retainRawWhileCovered,
950
+ () => props.ignoreRawCoverage,
951
+ () => props.ignoreSamePlaneRawCoverage,
952
+ () => props.cacheKey,
953
+ () => props.placementKey
954
+ ], () => {
955
+ scheduleRender();
956
+ }, { immediate: true });
957
+ watch(() => props.fallback, () => {
958
+ const current = graphic.value;
959
+ if (current?.type === "terminal") {
960
+ if (current.fallbackFromProps) {
961
+ graphic.value = {
962
+ ...current,
963
+ fallback: fallbackText()
964
+ };
965
+ bump();
966
+ scheduler.invalidate({
967
+ priority: "low",
968
+ reason: "data"
969
+ });
970
+ return;
971
+ }
972
+ scheduleRender({ clearLastGraphic: false });
973
+ return;
974
+ }
975
+ scheduleRender();
976
+ });
977
+ watch(() => [graphicsOutputVersion.value, rawOutputCanRenderValue.value], () => {
978
+ if (!props.renderer || !props.content.trim()) return;
979
+ if (graphic.value?.type === "terminal") return;
980
+ if (!rawOutputCanRenderValue.value || shouldDeferRender()) return;
981
+ scheduleRender({ clearLastGraphic: false });
982
+ });
983
+ watch(() => [
984
+ props.x,
985
+ props.y,
986
+ props.w,
987
+ props.h,
988
+ props.scrollVersion
989
+ ], () => {
990
+ if (graphic.value?.type === "terminal") {
991
+ scheduler.invalidate({
992
+ priority: "low",
993
+ reason: "data"
994
+ });
995
+ return;
996
+ }
997
+ if (props.kind !== "image" || status.value !== "loading" || !props.renderer) return;
998
+ scheduleRender({ clearLastGraphic: false });
999
+ }, { flush: "sync" });
1000
+ onBeforeUnmount(() => {
1001
+ alive = false;
1002
+ renderVersion++;
1003
+ unsubscribeTerminalResize();
1004
+ unsubscribeGraphicsOutput();
1005
+ abortCurrentRender("unmount");
1006
+ scheduler.cancelFrameTask?.(frameTaskId);
1007
+ queueClearLastGraphic();
1008
+ });
1009
+ function resolveDisplayLines(rawPlaceholderAllowed) {
1010
+ if (showingInitialLoadingText.value) return splitTextOutput(props.loadingText);
1011
+ const current = graphic.value;
1012
+ if (!current) return splitTextOutput(fallbackText());
1013
+ if (current.type === "terminal" && rawPlaceholderAllowed) {
1014
+ const clearSequence = resolveClearSequence(current);
1015
+ const drawKey = terminalDrawKey(current, absRect.value, clearSequence, resolveResizeSequence(current, absRect.value, fullRect.value));
1016
+ if (rawDrawRejectedKey.value !== drawKey) return markRaw([""]);
1017
+ }
1018
+ const text = current.type === "terminal" ? current.fallback : current.text;
1019
+ const lines = splitTextOutput(text);
1020
+ return text.trim().length > 0 && !hasVisibleOutput(lines) ? splitTextOutput(fallbackText()) : lines;
1021
+ }
1022
+ const displayLines = computed(() => {
1023
+ return resolveDisplayLines(rawCanQueue.value);
1024
+ });
1025
+ const currentStyle = computed(() => {
1026
+ if (error.value) return props.errorStyle ?? props.style ?? defaultStyle.value;
1027
+ if (showingInitialLoadingText.value) return props.loadingStyle ?? props.style ?? defaultStyle.value;
1028
+ return props.style ?? defaultStyle.value;
1029
+ });
1030
+ const renderNode = useRenderNode(() => ({
1031
+ zIndex: props.zIndex,
1032
+ rect: visible.value ? renderRect.value : {
1033
+ x: 0,
1034
+ y: 0,
1035
+ w: 0,
1036
+ h: 0
1037
+ },
1038
+ deps: [
1039
+ visible.value,
1040
+ renderRect.value,
1041
+ fullRect.value,
1042
+ displayLines.value,
1043
+ currentStyle.value,
1044
+ props.clear,
1045
+ status.value,
1046
+ error.value,
1047
+ documentVersion.value,
1048
+ rawOutputCanRenderValue.value,
1049
+ rawCanRender.value,
1050
+ rawCanQueue.value,
1051
+ rawClearPendingRepaint.value,
1052
+ rawDrawRejectedKey.value,
1053
+ rawSuppressedByScroll.value,
1054
+ props.placementMoveWithoutClear,
1055
+ props.retainRawWhileCovered,
1056
+ isParentScrolling.value,
1057
+ graphicsActivityVersion.value,
1058
+ graphicsOutputVersion.value
1059
+ ],
1060
+ paint: (dirtyRows) => {
1061
+ withTextWidthProvider(widthProvider, () => {
1062
+ if (!visible.value) {
1063
+ queueClearLastGraphic();
1064
+ return;
1065
+ }
1066
+ const r = absRect.value;
1067
+ const full = fullRect.value;
1068
+ if (r.w <= 0 || r.h <= 0) {
1069
+ queueClearLastGraphic();
1070
+ return;
1071
+ }
1072
+ const style = currentStyle.value;
1073
+ const dx = Math.max(0, Math.floor(r.x - full.x));
1074
+ const fullY = Math.floor(full.y);
1075
+ const current = graphic.value;
1076
+ const output = graphicsOutput();
1077
+ const retainedActiveRawGraphic = hasRetainedActiveRawGraphic();
1078
+ const rawRectForPaint = rawUncoveredRenderRect(r);
1079
+ const rawCoverageClipped = rawRectForPaint != null && props.ignoreRawCoverage && !sameRect(rawRectForPaint, r);
1080
+ const rawCoveredForPaint = rawRectForPaint == null && rawCoveredByHigherRenderNode(r);
1081
+ const rawCanQueueForPaint = current?.type === "terminal" && rawCanQueue.value && rawRectForPaint != null;
1082
+ let preserveActiveRawGraphic = false;
1083
+ let forceActiveRawRedraw = false;
1084
+ let allowTextOverlay = false;
1085
+ if (rawCanQueueForPaint && output) {
1086
+ const previous = lastDrawnGraphic.value;
1087
+ const previousStillActive = previous ? typeof output.isActive === "function" ? output.isActive(previous.id) : true : false;
1088
+ if (previousStillActive && previous) {
1089
+ const clearSequence = resolveClearSequence(current);
1090
+ const resizeSequence = resolveResizeSequence(current, rawRectForPaint, full);
1091
+ preserveActiveRawGraphic = rawClearPendingRepaint.value == null && previous.drawKey === terminalDrawKey(current, rawRectForPaint, clearSequence, resizeSequence);
1092
+ allowTextOverlay = retainedRawCoveredByHigherRenderNode(r);
1093
+ forceActiveRawRedraw = preserveActiveRawGraphic && (previous.activityVersion !== graphicsActivityVersion.value || allowTextOverlay);
1094
+ }
1095
+ }
1096
+ const preserveActiveRawGraphicForPaint = preserveActiveRawGraphic;
1097
+ let out = rawCanQueueForPaint ? displayLines.value : resolveDisplayLines(false);
1098
+ const clearingRawGraphic = rawClearPendingRepaint.value != null || lastDrawnGraphic.value != null && !preserveActiveRawGraphicForPaint;
1099
+ const clearOwnedRegion = preserveActiveRawGraphicForPaint || retainedActiveRawGraphic ? false : props.clear || clearingRawGraphic || Boolean(rawCanQueueForPaint);
1100
+ const blank = clearOwnedRegion ? spaces(r.w) : "";
1101
+ const paintRow = (y) => {
1102
+ if (y < r.y || y >= r.y + r.h) return;
1103
+ const rowIndex = y - fullY;
1104
+ if (rowIndex < 0 || rowIndex >= out.length) {
1105
+ if (clearOwnedRegion) terminal.write(blank, {
1106
+ x: r.x,
1107
+ y,
1108
+ style
1109
+ });
1110
+ return;
1111
+ }
1112
+ const src = out[rowIndex] ?? "";
1113
+ const clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w);
1114
+ const value = clearOwnedRegion ? padEndByCells(clipped, r.w) : clipped;
1115
+ if (value || clearOwnedRegion) terminal.write(value, {
1116
+ x: r.x,
1117
+ y,
1118
+ style
1119
+ });
1120
+ };
1121
+ const paintRows = () => {
1122
+ if (dirtyRows?.length) for (const y of dirtyRows) paintRow(y);
1123
+ else for (let y = r.y; y < r.y + r.h; y++) paintRow(y);
1124
+ };
1125
+ paintRows();
1126
+ if (current?.type === "terminal" && output?.capabilities.supported && output.capabilities.preferredProtocol === current.protocol && rawCanQueueForPaint) {
1127
+ const drawKey = terminalDrawKey(current, rawRectForPaint, resolveClearSequence(current), resolveResizeSequence(current, rawRectForPaint, full));
1128
+ const queued = queueDrawGraphic(output, current, rawRectForPaint, full, {
1129
+ force: forceActiveRawRedraw,
1130
+ deferFlush: preserveActiveRawGraphicForPaint,
1131
+ placementMoveWithoutClear: props.placementMoveWithoutClear || rawCoverageClipped,
1132
+ allowTextOverlay
1133
+ });
1134
+ if (queued) trace("raw-draw", {
1135
+ sequenceChars: current.sequence.length,
1136
+ sequenceBytes: current.sequenceBytes,
1137
+ x: rawRectForPaint.x,
1138
+ y: rawRectForPaint.y,
1139
+ w: rawRectForPaint.w,
1140
+ h: rawRectForPaint.h
1141
+ });
1142
+ else if (rawDrawRejectedKey.value === drawKey) {
1143
+ out = resolveDisplayLines(false);
1144
+ paintRows();
1145
+ }
1146
+ } else {
1147
+ if (current?.type === "terminal" && rawSuppressedByScroll.value) traceRawSkipScrollOnce(isParentScrolling.value ? "scrolling" : "suspended");
1148
+ queueClearLastGraphic({ markPendingRepaint: false });
1149
+ if (!shouldDeferRender() && shouldRetryTemporaryRawFallback(rawCoveredForPaint)) scheduleRender({ clearLastGraphic: false });
1150
+ }
1151
+ if (clearingRawGraphic) rawClearPendingRepaint.value = null;
1152
+ });
1153
+ }
1154
+ }));
1155
+ watch(renderNode.id, (id) => {
1156
+ renderNodeId.value = id;
1157
+ }, { immediate: true });
1158
+ watch([
1159
+ visible,
1160
+ rawOutputCanRenderValue,
1161
+ rawCanRender,
1162
+ rawCanQueue,
1163
+ rawSuppressedByScroll,
1164
+ isParentScrolling,
1165
+ graphicsActivityVersion,
1166
+ graphicsOutputVersion,
1167
+ () => renderRect.value.x,
1168
+ () => renderRect.value.y,
1169
+ () => renderRect.value.w,
1170
+ () => renderRect.value.h,
1171
+ () => fullRect.value.x,
1172
+ () => fullRect.value.y,
1173
+ () => fullRect.value.w,
1174
+ () => fullRect.value.h
1175
+ ], () => {
1176
+ if (!alive) return;
1177
+ const deferred = renderDeferReason();
1178
+ if (deferred) {
1179
+ abortCurrentRender(deferred);
1180
+ if (status.value === "loading" || !graphic.value || lastRenderedContent !== props.content) setDeferredFallback(props.content);
1181
+ traceDeferOnce(deferred);
1182
+ }
1183
+ if (!visible.value || !rawCanQueue.value) queueClearLastGraphic();
1184
+ const shouldRetryTemporaryFallback = shouldRetryTemporaryRawFallback();
1185
+ const shouldRerenderForOutputChange = shouldRerenderForGraphicsOutputChange();
1186
+ if (!shouldDeferRender() && (!graphic.value || status.value === "idle" || shouldRetryTemporaryFallback || shouldRerenderForOutputChange)) {
1187
+ scheduleRender();
1188
+ return;
1189
+ }
1190
+ scheduler.invalidate({
1191
+ priority: "low",
1192
+ reason: "data"
1193
+ });
1194
+ }, { flush: "post" });
1195
+ return () => h("span", rootProps);
1196
+ }
1197
+ });
1198
+
1199
+ //#endregion
14
1200
  //#region src/vue/agent/view-models.ts
15
1201
  function resolveTUserMessageViewModel(opts) {
16
1202
  const indent = Math.max(0, Math.floor(opts.indent ?? 0));
@@ -825,4 +2011,505 @@ const TUserMessageView = defineComponent({
825
2011
  });
826
2012
 
827
2013
  //#endregion
828
- export { TTranscriptView as TAgentTranscript, TBox, TCommandPalette, TDialog, TInput, TLogLinksPanel, TLogMinimap, TLogScrollbar, TLogSearchBar, TLogSearchPager, TLogSearchResults, TLogView, TLogVirtualLinksPanel, TLogVirtualSearchResults, TRenderPlane, TSelect, TText, TThinkingView, TToolCallView, TLogView as TToolLogView, TTranscriptView, TUserMessageView, TView, TVirtualList, TVirtualMarkdown, computeCommandPaletteMatchRanges, createAppendOnlyLogStore, createMarkdownBlockSource, createTLogDensityBucketsFromMarkers, createTLogLevelPlugin, createTLogLineMatcherPlugin, createTLogLinkActionPlugin, createTLogOsc8LinkPlugin, createTLogUrlPlugin, detectTLogUrls, dispatchTLogPluginLinkAction, getTLogPluginMetadata, parseTLogAnnotatedText, resolveTLogLinksPanelTheme, resolveTLogMinimapTheme, resolveTLogScrollbarTheme, resolveTLogSearchBarTheme, resolveTLogSearchPagerTheme, resolveTLogSearchResultsTheme, resolveTLogViewTheme, resolveTThinkingViewModel, resolveTToolCallViewModel, resolveTUserMessageViewModel, stripTLogAnsiText, tlogDarkPreset, tlogDarkTheme, tlogDefaultPreset, tlogDefaultTheme, tlogHighContrastPreset, tlogHighContrastTheme, toTLogExternalLinkFromVisibleLink, useTLogLinkController, useTLogRetainedIndex, useTLogSearchController, useTLogSearchResultsPage, useTLogVirtualSearchResults };
2014
+ //#region src/renderer/terminal-graphic-render-queue.ts
2015
+ const CACHE_MISS = Symbol("terminal-graphic-cache-miss");
2016
+ function now() {
2017
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
2018
+ }
2019
+ function createAbortError() {
2020
+ const error = new Error("Terminal graphic render aborted");
2021
+ error.name = "AbortError";
2022
+ return error;
2023
+ }
2024
+ function positiveFiniteInt(value, fallback) {
2025
+ const n = Number(value);
2026
+ if (!Number.isFinite(n)) return fallback;
2027
+ const int = Math.floor(n);
2028
+ return int > 0 ? int : fallback;
2029
+ }
2030
+ function throwIfAborted$1(signal) {
2031
+ if (signal?.aborted) throw createAbortError();
2032
+ }
2033
+ function raceAbort(promise, signal) {
2034
+ if (!signal) return promise;
2035
+ if (signal.aborted) return Promise.reject(createAbortError());
2036
+ return new Promise((resolve, reject) => {
2037
+ const onAbort = () => reject(createAbortError());
2038
+ signal.addEventListener("abort", onAbort, { once: true });
2039
+ promise.then((value) => {
2040
+ signal.removeEventListener("abort", onAbort);
2041
+ resolve(value);
2042
+ }, (error) => {
2043
+ signal.removeEventListener("abort", onAbort);
2044
+ reject(error);
2045
+ });
2046
+ });
2047
+ }
2048
+ function createTerminalGraphicRenderQueue(options = {}) {
2049
+ const maxConcurrency = positiveFiniteInt(options.maxConcurrency, 2);
2050
+ const maxEntries = positiveFiniteInt(options.maxEntries, 128);
2051
+ const maxBytes = positiveFiniteInt(options.maxBytes, 32 * 1024 * 1024);
2052
+ const ttlMs = positiveFiniteInt(options.ttlMs, 5 * 6e4);
2053
+ const dedupeInflight = options.dedupeInflight ?? false;
2054
+ let active = 0;
2055
+ let cacheBytes = 0;
2056
+ let generation = 0;
2057
+ const waiters = [];
2058
+ const cache = new Map();
2059
+ const inflight = new Map();
2060
+ function traceQueueState(event) {
2061
+ recordTerminalGraphicTrace({
2062
+ ...event,
2063
+ active,
2064
+ waiting: waiters.length,
2065
+ cacheEntries: cache.size,
2066
+ cacheBytes
2067
+ });
2068
+ }
2069
+ function evictUntilBudget() {
2070
+ while (cache.size > maxEntries || cacheBytes > maxBytes) {
2071
+ const oldestKey = cache.keys().next().value;
2072
+ if (!oldestKey) break;
2073
+ const entry = cache.get(oldestKey);
2074
+ cache.delete(oldestKey);
2075
+ if (entry) {
2076
+ cacheBytes -= entry.bytes;
2077
+ options.onMetric?.({
2078
+ type: "evict",
2079
+ key: oldestKey,
2080
+ bytes: entry.bytes
2081
+ });
2082
+ }
2083
+ }
2084
+ }
2085
+ function setCache(key, value, bytes) {
2086
+ const prev = cache.get(key);
2087
+ if (prev) {
2088
+ cache.delete(key);
2089
+ cacheBytes -= prev.bytes;
2090
+ }
2091
+ if (bytes > maxBytes) return;
2092
+ cache.set(key, {
2093
+ value,
2094
+ bytes,
2095
+ expiresAt: Date.now() + ttlMs
2096
+ });
2097
+ cacheBytes += bytes;
2098
+ options.onMetric?.({
2099
+ type: "cache-store",
2100
+ key,
2101
+ bytes
2102
+ });
2103
+ traceQueueState({
2104
+ type: "cache-store",
2105
+ id: key,
2106
+ key,
2107
+ bytes
2108
+ });
2109
+ evictUntilBudget();
2110
+ }
2111
+ function getCache(key) {
2112
+ const entry = cache.get(key);
2113
+ if (!entry) return CACHE_MISS;
2114
+ if (entry.expiresAt < Date.now()) {
2115
+ cache.delete(key);
2116
+ cacheBytes -= entry.bytes;
2117
+ return CACHE_MISS;
2118
+ }
2119
+ cache.delete(key);
2120
+ cache.set(key, entry);
2121
+ options.onMetric?.({
2122
+ type: "cache-hit",
2123
+ key
2124
+ });
2125
+ traceQueueState({
2126
+ type: "cache-hit",
2127
+ id: key,
2128
+ key,
2129
+ bytes: entry.bytes
2130
+ });
2131
+ return entry.value;
2132
+ }
2133
+ function release() {
2134
+ active = Math.max(0, active - 1);
2135
+ pump();
2136
+ }
2137
+ function once(fn) {
2138
+ let called = false;
2139
+ return () => {
2140
+ if (called) return;
2141
+ called = true;
2142
+ fn();
2143
+ };
2144
+ }
2145
+ function observeActiveRenderAbort(key, signal) {
2146
+ if (!signal) return () => void 0;
2147
+ const onAbort = () => {
2148
+ options.onMetric?.({
2149
+ type: "render-abort",
2150
+ key
2151
+ });
2152
+ traceQueueState({
2153
+ type: "renderer-abort",
2154
+ id: key,
2155
+ key
2156
+ });
2157
+ };
2158
+ signal.addEventListener("abort", onAbort, { once: true });
2159
+ return () => signal.removeEventListener("abort", onAbort);
2160
+ }
2161
+ function pump() {
2162
+ while (active < maxConcurrency && waiters.length > 0) {
2163
+ const waiter = waiters.shift();
2164
+ active++;
2165
+ traceQueueState({
2166
+ type: "queue-depth",
2167
+ id: waiter.key,
2168
+ key: waiter.key
2169
+ });
2170
+ waiter.start();
2171
+ }
2172
+ }
2173
+ function acquire(key, signal) {
2174
+ throwIfAborted$1(signal);
2175
+ if (active < maxConcurrency) {
2176
+ active++;
2177
+ traceQueueState({
2178
+ type: "queue-depth",
2179
+ id: key,
2180
+ key
2181
+ });
2182
+ return Promise.resolve(release);
2183
+ }
2184
+ const waitStartedAt = now();
2185
+ return new Promise((resolve, reject) => {
2186
+ let onAbort = () => void 0;
2187
+ const cleanup = () => {
2188
+ signal?.removeEventListener("abort", onAbort);
2189
+ };
2190
+ const waiter = {
2191
+ key,
2192
+ start: () => {
2193
+ cleanup();
2194
+ const waitMs = now() - waitStartedAt;
2195
+ options.onMetric?.({
2196
+ type: "queue-wait",
2197
+ key,
2198
+ waitMs
2199
+ });
2200
+ traceQueueState({
2201
+ type: "queue-wait",
2202
+ id: key,
2203
+ key,
2204
+ durationMs: waitMs
2205
+ });
2206
+ resolve(release);
2207
+ },
2208
+ reject: (error) => {
2209
+ cleanup();
2210
+ reject(error);
2211
+ }
2212
+ };
2213
+ onAbort = () => {
2214
+ const index = waiters.indexOf(waiter);
2215
+ if (index >= 0) waiters.splice(index, 1);
2216
+ cleanup();
2217
+ reject(createAbortError());
2218
+ };
2219
+ signal?.addEventListener("abort", onAbort, { once: true });
2220
+ waiters.push(waiter);
2221
+ traceQueueState({
2222
+ type: "queue-depth",
2223
+ id: key,
2224
+ key
2225
+ });
2226
+ });
2227
+ }
2228
+ async function cached(key, signal, render, estimateBytes = () => 0, cachedOptions = {}) {
2229
+ throwIfAborted$1(signal);
2230
+ const cachedValue = getCache(key);
2231
+ if (cachedValue !== CACHE_MISS) return cachedValue;
2232
+ traceQueueState({
2233
+ type: "cache-miss",
2234
+ id: key,
2235
+ key
2236
+ });
2237
+ const shouldDedupeInflight = cachedOptions.dedupeInflight ?? dedupeInflight;
2238
+ const existing = shouldDedupeInflight ? inflight.get(key) : void 0;
2239
+ if (existing) return raceAbort(existing, signal);
2240
+ let promise;
2241
+ promise = (async () => {
2242
+ let releaseSlot = null;
2243
+ let removeAbortObserver = null;
2244
+ const renderGeneration = generation;
2245
+ try {
2246
+ releaseSlot = once(await acquire(key, signal));
2247
+ removeAbortObserver = observeActiveRenderAbort(key, signal);
2248
+ throwIfAborted$1(signal);
2249
+ const cachedAfterWait = getCache(key);
2250
+ if (cachedAfterWait !== CACHE_MISS) return cachedAfterWait;
2251
+ const value = await render();
2252
+ throwIfAborted$1(signal);
2253
+ const rawBytes = Math.floor(Number(estimateBytes(value)));
2254
+ const bytes = Number.isFinite(rawBytes) && rawBytes > 0 ? rawBytes : 0;
2255
+ if (renderGeneration === generation) setCache(key, value, bytes);
2256
+ return value;
2257
+ } finally {
2258
+ removeAbortObserver?.();
2259
+ releaseSlot?.();
2260
+ if (shouldDedupeInflight && inflight.get(key) === promise) inflight.delete(key);
2261
+ }
2262
+ })();
2263
+ if (shouldDedupeInflight) inflight.set(key, promise);
2264
+ return raceAbort(promise, signal);
2265
+ }
2266
+ return {
2267
+ cached,
2268
+ clear() {
2269
+ generation++;
2270
+ cache.clear();
2271
+ inflight.clear();
2272
+ const pending = waiters.splice(0);
2273
+ for (const waiter of pending) waiter.reject(createAbortError());
2274
+ cacheBytes = 0;
2275
+ },
2276
+ stats() {
2277
+ return {
2278
+ active,
2279
+ waiting: waiters.length,
2280
+ cacheEntries: cache.size,
2281
+ cacheBytes
2282
+ };
2283
+ }
2284
+ };
2285
+ }
2286
+
2287
+ //#endregion
2288
+ //#region src/vue/agent/create-png-terminal-graphic-renderer.ts
2289
+ function positiveInt(value) {
2290
+ const n = Math.floor(Number(value));
2291
+ return Number.isFinite(n) && n > 0 ? n : void 0;
2292
+ }
2293
+ function abortError() {
2294
+ const error = new Error("Terminal graphic render aborted");
2295
+ error.name = "AbortError";
2296
+ return error;
2297
+ }
2298
+ function base64PrefixBytes(value, byteCount) {
2299
+ const data = String(value ?? "").replace(/\s+/g, "");
2300
+ const chars = Math.ceil(byteCount / 3) * 4;
2301
+ try {
2302
+ const binary = atob(data.slice(0, chars));
2303
+ const bytes = new Uint8Array(binary.length);
2304
+ for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
2305
+ return bytes;
2306
+ } catch {
2307
+ return null;
2308
+ }
2309
+ }
2310
+ function readPngDimensions(base64) {
2311
+ const bytes = base64PrefixBytes(base64, 24);
2312
+ if (!bytes || bytes.length < 24) return null;
2313
+ if (bytes[0] !== 137 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71 || bytes[4] !== 13 || bytes[5] !== 10 || bytes[6] !== 26 || bytes[7] !== 10) return null;
2314
+ const width = (bytes[16] << 24 | bytes[17] << 16 | bytes[18] << 8 | bytes[19]) >>> 0;
2315
+ const height = (bytes[20] << 24 | bytes[21] << 16 | bytes[22] << 8 | bytes[23]) >>> 0;
2316
+ return width > 0 && height > 0 ? {
2317
+ width,
2318
+ height
2319
+ } : null;
2320
+ }
2321
+ function throwIfAborted(signal) {
2322
+ if (signal.aborted) throw abortError();
2323
+ }
2324
+ function defaultCacheKey(content, context, cacheSalt) {
2325
+ const contentIdentity = context.cacheKey != null ? `cache:${context.cacheKey}` : `content:${hashTerminalGraphicsString(content)}`;
2326
+ return [
2327
+ context.kind,
2328
+ context.width,
2329
+ context.height ?? "",
2330
+ context.final ? "final" : "draft",
2331
+ cacheSalt,
2332
+ contentIdentity
2333
+ ].join("");
2334
+ }
2335
+ function resolveCacheSalt(options, content, context) {
2336
+ const salt = typeof options.cacheSalt === "function" ? options.cacheSalt(content, context) : options.cacheSalt;
2337
+ return salt == null ? "" : String(salt);
2338
+ }
2339
+ function normalizeCachedPngFrame(frame, context) {
2340
+ const fallbackCols = normalizeTerminalGraphicSize(context.width, 1)?.width ?? 1;
2341
+ const requestedCols = positiveInt(frame.cols) ?? fallbackCols;
2342
+ const cols = Math.min(requestedCols, fallbackCols);
2343
+ const rawRows = positiveInt(frame.rows) ?? positiveInt(context.height);
2344
+ const size = normalizeTerminalGraphicSize(cols, rawRows ?? 1);
2345
+ if (rawRows != null && !size) return {
2346
+ base64: "",
2347
+ fallback: frame.fallback == null ? void 0 : sanitizeTerminalFallbackText(frame.fallback),
2348
+ cols: fallbackCols
2349
+ };
2350
+ const base64 = String(frame.base64 ?? "").replace(/\s+/g, "");
2351
+ const dimensions = readPngDimensions(base64);
2352
+ return {
2353
+ base64,
2354
+ fallback: frame.fallback == null ? void 0 : sanitizeTerminalFallbackText(frame.fallback),
2355
+ cols: size?.width ?? fallbackCols,
2356
+ rows: rawRows == null ? void 0 : size?.height,
2357
+ sourceWidth: dimensions?.width,
2358
+ sourceHeight: dimensions?.height
2359
+ };
2360
+ }
2361
+ function resolveKittyViewportPlacement(png, context) {
2362
+ const rect = context.viewport.rect;
2363
+ const full = context.viewport.fullRect;
2364
+ const columns = positiveInt(rect.w) ?? png.cols;
2365
+ const rows = positiveInt(rect.h) ?? png.rows;
2366
+ const sourceWidth = positiveInt(png.sourceWidth);
2367
+ const sourceHeight = positiveInt(png.sourceHeight);
2368
+ if (!sourceWidth || !sourceHeight || full.w <= 0 || full.h <= 0) return {
2369
+ columns,
2370
+ rows
2371
+ };
2372
+ const offsetX = Math.max(0, rect.x - full.x);
2373
+ const offsetY = Math.max(0, rect.y - full.y);
2374
+ const visibleW = Math.max(0, Math.min(rect.w, full.w - offsetX));
2375
+ const visibleH = Math.max(0, Math.min(rect.h, full.h - offsetY));
2376
+ if (offsetX <= 0 && offsetY <= 0 && visibleW >= full.w && visibleH >= full.h) return {
2377
+ columns,
2378
+ rows
2379
+ };
2380
+ const x0 = Math.max(0, Math.min(sourceWidth - 1, Math.floor(offsetX * sourceWidth / full.w)));
2381
+ const y0 = Math.max(0, Math.min(sourceHeight - 1, Math.floor(offsetY * sourceHeight / full.h)));
2382
+ const x1 = Math.max(x0 + 1, Math.min(sourceWidth, Math.ceil((offsetX + visibleW) * sourceWidth / full.w)));
2383
+ const y1 = Math.max(y0 + 1, Math.min(sourceHeight, Math.ceil((offsetY + visibleH) * sourceHeight / full.h)));
2384
+ return {
2385
+ columns,
2386
+ rows,
2387
+ sourceX: x0,
2388
+ sourceY: y0,
2389
+ sourceWidth: x1 - x0,
2390
+ sourceHeight: y1 - y0
2391
+ };
2392
+ }
2393
+ function pngFrameBytes(frame) {
2394
+ return frame.base64.length + (frame.fallback?.length ?? 0);
2395
+ }
2396
+ function stringBytes(value) {
2397
+ return value.length;
2398
+ }
2399
+ async function resolveFallbackText(options, content, context) {
2400
+ throwIfAborted(context.signal);
2401
+ if (!options.fallback) return void 0;
2402
+ const value = await options.fallback(content, context);
2403
+ throwIfAborted(context.signal);
2404
+ return sanitizeTerminalFallbackText(value);
2405
+ }
2406
+ async function resolvePngFallbackText(frame, options, content, context) {
2407
+ if (frame.fallback != null) return frame.fallback;
2408
+ return resolveFallbackText(options, content, context);
2409
+ }
2410
+ function textFallbackResult(text) {
2411
+ return text == null ? null : {
2412
+ type: "text",
2413
+ text
2414
+ };
2415
+ }
2416
+ function createPngTerminalGraphicRenderer(options) {
2417
+ const queue = options.queue ?? createTerminalGraphicRenderQueue({
2418
+ maxConcurrency: 2,
2419
+ maxEntries: 128,
2420
+ maxBytes: 32 * 1024 * 1024,
2421
+ dedupeInflight: options.dedupeInflight ?? false
2422
+ });
2423
+ return async (content, context) => {
2424
+ throwIfAborted(context.signal);
2425
+ const protocol = context.protocol;
2426
+ if (!context.capabilities.supported || protocol === "unicode" || protocol === "none" || !context.visible || !context.rawVisible || protocol === "sixel" && !options.toSixel) return textFallbackResult(await resolveFallbackText(options, content, context));
2427
+ const key = options.cacheKey?.(content, context) ?? defaultCacheKey(content, context, resolveCacheSalt(options, content, context));
2428
+ throwIfAborted(context.signal);
2429
+ const png = await queue.cached(`${key}\x1Fpng`, void 0, async () => {
2430
+ throwIfAborted(context.signal);
2431
+ const frame = await options.toPngBase64(content, context);
2432
+ return normalizeCachedPngFrame(frame, context);
2433
+ }, pngFrameBytes, { dedupeInflight: options.dedupeInflight ?? false });
2434
+ throwIfAborted(context.signal);
2435
+ let fallbackPromise;
2436
+ const fallback = () => fallbackPromise ?? (fallbackPromise = resolvePngFallbackText(png, options, content, context));
2437
+ const sequenceFallback = async () => {
2438
+ if (png.fallback == null && !options.fallback) return {};
2439
+ const text = await fallback();
2440
+ return text == null ? {} : { fallback: text };
2441
+ };
2442
+ if (!png.base64) return textFallbackResult(await fallback());
2443
+ if (protocol === "kitty") {
2444
+ const placement = resolveKittyViewportPlacement(png, context);
2445
+ const sequence = createKittyGraphicsSequence(png.base64, {
2446
+ imageId: context.imageId,
2447
+ placementId: context.placementId,
2448
+ zIndex: options.zIndex,
2449
+ ...placement
2450
+ });
2451
+ const resizeSequence = createKittyPlacementSequence({
2452
+ imageId: context.imageId,
2453
+ placementId: context.placementId,
2454
+ zIndex: options.zIndex,
2455
+ ...placement
2456
+ });
2457
+ if (!isSafeTerminalGraphicsSequence(sequence, "kitty", "draw")) return textFallbackResult(await fallback());
2458
+ return {
2459
+ type: "sequence",
2460
+ protocol: "kitty",
2461
+ sequence,
2462
+ resizeSequence,
2463
+ clearSequence: createKittyDeleteGraphicsSequence({
2464
+ imageId: context.imageId,
2465
+ placementId: context.placementId
2466
+ }),
2467
+ ...await sequenceFallback(),
2468
+ cols: png.cols,
2469
+ rows: png.rows,
2470
+ sourceWidth: png.sourceWidth,
2471
+ sourceHeight: png.sourceHeight,
2472
+ zIndex: options.zIndex
2473
+ };
2474
+ }
2475
+ if (protocol === "iterm2") {
2476
+ const sequence = createIterm2InlineImageSequence(png.base64, {
2477
+ width: png.cols,
2478
+ height: png.rows,
2479
+ preserveAspectRatio: true,
2480
+ doNotMoveCursor: true
2481
+ });
2482
+ if (!isSafeTerminalGraphicsSequence(sequence, "iterm2", "draw")) return textFallbackResult(await fallback());
2483
+ return {
2484
+ type: "sequence",
2485
+ protocol: "iterm2",
2486
+ sequence,
2487
+ ...await sequenceFallback(),
2488
+ cols: png.cols,
2489
+ rows: png.rows
2490
+ };
2491
+ }
2492
+ if (protocol === "sixel") {
2493
+ const sixel = await queue.cached(`${key}\x1Fsixel`, context.signal, async () => {
2494
+ throwIfAborted(context.signal);
2495
+ const sixel$1 = await options.toSixel(png.base64, context);
2496
+ throwIfAborted(context.signal);
2497
+ return sixel$1;
2498
+ }, stringBytes, { dedupeInflight: options.dedupeInflight ?? false });
2499
+ throwIfAborted(context.signal);
2500
+ if (!isSafeTerminalGraphicsSequence(sixel, "sixel", "draw")) return textFallbackResult(await fallback());
2501
+ return {
2502
+ type: "sequence",
2503
+ protocol: "sixel",
2504
+ sequence: sixel,
2505
+ ...await sequenceFallback(),
2506
+ cols: png.cols,
2507
+ rows: png.rows
2508
+ };
2509
+ }
2510
+ return textFallbackResult(await fallback());
2511
+ };
2512
+ }
2513
+
2514
+ //#endregion
2515
+ export { TAgentTerminalGraphic, TTranscriptView as TAgentTranscript, TBox, TCommandPalette, TDialog, TInput, TLogLinksPanel, TLogMinimap, TLogScrollbar, TLogSearchBar, TLogSearchPager, TLogSearchResults, TLogView, TLogVirtualLinksPanel, TLogVirtualSearchResults, TMermaid, TMermaidText, TRenderPlane, TSelect, TText, TThinkingView, TToolCallView, TLogView as TToolLogView, TTranscriptView, TUserMessageView, TView, TVirtualList, TVirtualMarkdown, computeCommandPaletteMatchRanges, createAppendOnlyLogStore, createIterm2InlineImageSequence, createKittyDeleteGraphicsSequence, createKittyGraphicsSequence, createKittyPlacementSequence, createMarkdownBlockSource, createPngTerminalGraphicRenderer, createTLogDensityBucketsFromMarkers, createTLogLevelPlugin, createTLogLineMatcherPlugin, createTLogLinkActionPlugin, createTLogOsc8LinkPlugin, createTLogUrlPlugin, createTerminalGraphicRenderQueue, detectTLogUrls, detectTerminalGraphicsCapabilities, dispatchTLogPluginLinkAction, getTLogPluginMetadata, getTerminalGraphicsOutput, getTerminalGraphicsOutputVersion, isSimpleMermaidFlowchartSource, markMermaidRenderErrorFatal, parseTLogAnnotatedText, resolveTLogLinksPanelTheme, resolveTLogMinimapTheme, resolveTLogScrollbarTheme, resolveTLogSearchBarTheme, resolveTLogSearchPagerTheme, resolveTLogSearchResultsTheme, resolveTLogViewTheme, resolveTThinkingViewModel, resolveTToolCallViewModel, resolveTUserMessageViewModel, stripTLogAnsiText, subscribeTerminalGraphicsOutput, tlogDarkPreset, tlogDarkTheme, tlogDefaultPreset, tlogDefaultTheme, tlogHighContrastPreset, tlogHighContrastTheme, toTLogExternalLinkFromVisibleLink, useTLogLinkController, useTLogRetainedIndex, useTLogSearchController, useTLogSearchResultsPage, useTLogVirtualSearchResults };