langchain_agentx_stream_ui 0.1.0

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.
@@ -0,0 +1,666 @@
1
+ // src/view/tools/presentation/paths.ts
2
+ function displayPath(filePath) {
3
+ if (!filePath) return "";
4
+ return filePath.replace(/\\/g, "/");
5
+ }
6
+
7
+ // src/view/tools/presentation/searchHelpers.ts
8
+ var SEARCH_LIST_PREVIEW_LINES = 20;
9
+ var FOUND_SUMMARY_RE = /^(Found .+|No files found|No matches found)/i;
10
+ function formatPatternTitle(pattern, path) {
11
+ const parts = [`pattern: "${pattern}"`];
12
+ if (path) {
13
+ parts.push(`path: "${displayPath(path)}"`);
14
+ }
15
+ return parts.join(", ");
16
+ }
17
+ function extractSearchSummary(output) {
18
+ const text = output.trim();
19
+ if (!text) return "";
20
+ const match = text.match(FOUND_SUMMARY_RE);
21
+ if (match) return match[1].trim();
22
+ const first = text.split("\n", 1)[0]?.trim() ?? "";
23
+ if (/^(found |no files|no matches)/i.test(first)) return first;
24
+ return "";
25
+ }
26
+ function truncateLines(text, maxLines) {
27
+ const lines = text.split("\n");
28
+ if (lines.length <= maxLines) {
29
+ return { text, truncated: false };
30
+ }
31
+ return {
32
+ text: lines.slice(0, maxLines).join("\n"),
33
+ truncated: true
34
+ };
35
+ }
36
+ function formatSearchResultBody(output, maxListLines = SEARCH_LIST_PREVIEW_LINES) {
37
+ const text = output.trim();
38
+ if (!text) return "(No output)";
39
+ const summary = extractSearchSummary(text);
40
+ const lines = text.split("\n");
41
+ let listLines;
42
+ if (summary && lines[0]?.trim() === summary) {
43
+ listLines = lines.slice(1);
44
+ } else if (summary) {
45
+ listLines = lines.filter((ln) => ln.trim() !== summary);
46
+ } else {
47
+ listLines = lines;
48
+ }
49
+ const listText = listLines.map((ln) => ln.trim()).filter(Boolean).join("\n");
50
+ if (listText) {
51
+ const { text: truncated, truncated: wasTruncated } = truncateLines(
52
+ listText,
53
+ maxListLines
54
+ );
55
+ const suffix = wasTruncated ? `
56
+ \u2026 \u5217\u8868\u8D85\u8FC7 ${maxListLines} \u884C\uFF0C\u5DF2\u622A\u65AD` : "";
57
+ if (summary) return `${summary}
58
+ ${truncated}${suffix}`;
59
+ return `${truncated}${suffix}`;
60
+ }
61
+ return summary || text.slice(0, 500);
62
+ }
63
+
64
+ // src/view/tools/presentation/TruncatedContent.tsx
65
+ import { jsx, jsxs } from "react/jsx-runtime";
66
+ var MAX_PREVIEW_LINES = 3;
67
+ function TruncatedContent({
68
+ text,
69
+ mode,
70
+ maxLines = MAX_PREVIEW_LINES,
71
+ onExpand
72
+ }) {
73
+ const lines = text.split("\n");
74
+ const needsTruncate = mode === "preview" && lines.length > maxLines;
75
+ if (!needsTruncate) {
76
+ return /* @__PURE__ */ jsx("div", { className: "lax-tool-body__block", "data-variant": "normal", children: /* @__PURE__ */ jsx("pre", { className: "lax-tool-body__text", children: text }) });
77
+ }
78
+ const preview = lines.slice(0, maxLines).join("\n");
79
+ const remaining = lines.length - maxLines;
80
+ return /* @__PURE__ */ jsxs("div", { className: "lax-tool-body__block", "data-variant": "normal", children: [
81
+ /* @__PURE__ */ jsx("pre", { className: "lax-tool-body__text", children: preview }),
82
+ /* @__PURE__ */ jsxs(
83
+ "button",
84
+ {
85
+ type: "button",
86
+ className: "lax-tool-body__expand",
87
+ onClick: onExpand,
88
+ children: [
89
+ "+",
90
+ remaining,
91
+ " lines (\u70B9\u51FB\u5C55\u5F00)"
92
+ ]
93
+ }
94
+ )
95
+ ] });
96
+ }
97
+
98
+ // src/view/tools/presentation/bashHelpers.ts
99
+ var MAX_COMMAND_DISPLAY_CHARS = 160;
100
+ var MAX_COMMAND_DISPLAY_LINES = 2;
101
+ var CWD_RESET_PATTERN = /(?:^|\n)(Shell cwd was reset to .+)$/m;
102
+ var EXIT_CODE_PATTERN = /(?:^|\n)Exit code:\s*(\d+)/m;
103
+ function truncateCommand(command, maxChars = MAX_COMMAND_DISPLAY_CHARS) {
104
+ let text = command.trim();
105
+ if (!text) return "";
106
+ const lines = text.split("\n");
107
+ if (lines.length > MAX_COMMAND_DISPLAY_LINES) {
108
+ text = lines.slice(0, MAX_COMMAND_DISPLAY_LINES).join("\n");
109
+ }
110
+ if (text.length > maxChars) {
111
+ text = `${text.slice(0, maxChars)}\u2026`;
112
+ }
113
+ return text;
114
+ }
115
+ function formatBashTitle(input) {
116
+ const inp = input != null && typeof input === "object" && !Array.isArray(input) ? input : {};
117
+ const command = String(inp.command ?? "").trim();
118
+ if (!command) return "Bash";
119
+ return `Bash(${truncateCommand(command)})`;
120
+ }
121
+ function splitBashStreams(output) {
122
+ let text = output ?? "";
123
+ let cwdWarning = null;
124
+ const cwdMatch = text.match(CWD_RESET_PATTERN);
125
+ if (cwdMatch) {
126
+ cwdWarning = cwdMatch[1]?.trim() ?? null;
127
+ text = text.replace(CWD_RESET_PATTERN, "").trim();
128
+ }
129
+ let stdout = text;
130
+ let stderr = "";
131
+ if (text.includes("\n--- stderr ---\n")) {
132
+ const parts = text.split("\n--- stderr ---\n");
133
+ stdout = parts[0] ?? "";
134
+ stderr = parts[1] ?? "";
135
+ } else if (text.startsWith("stderr:")) {
136
+ stderr = text.slice(7).trim();
137
+ stdout = "";
138
+ }
139
+ return { stdout: stdout.trim(), stderr: stderr.trim(), cwdWarning };
140
+ }
141
+ function parseExitCode(output, fallback) {
142
+ const match = (output ?? "").match(EXIT_CODE_PATTERN);
143
+ if (match) return Number.parseInt(match[1], 10);
144
+ return fallback ?? null;
145
+ }
146
+ function formatDuration(seconds) {
147
+ if (seconds < 1) return `${seconds.toFixed(1)}s`;
148
+ if (seconds < 60) return `${Math.floor(seconds)}s`;
149
+ if (seconds < 3600) {
150
+ const minutes2 = Math.floor(seconds / 60);
151
+ const secs = Math.floor(seconds % 60);
152
+ return secs === 0 ? `${minutes2}m` : `${minutes2}m ${secs}s`;
153
+ }
154
+ const hours = Math.floor(seconds / 3600);
155
+ const minutes = Math.floor(seconds % 3600 / 60);
156
+ return minutes === 0 ? `${hours}h` : `${hours}h ${minutes}m`;
157
+ }
158
+ function formatTimeoutFooter(timeoutMs) {
159
+ if (!timeoutMs) return null;
160
+ return `(timeout ${formatDuration(timeoutMs / 1e3)})`;
161
+ }
162
+ function previewStreamText(text, mode) {
163
+ if (mode === "full" || !text.trim()) return text;
164
+ const lines = text.split("\n");
165
+ if (lines.length <= MAX_PREVIEW_LINES) return text;
166
+ return lines.slice(0, MAX_PREVIEW_LINES).join("\n");
167
+ }
168
+ function resolveStreams(display, summary) {
169
+ if (display && ("stdout" in display || "stderr" in display)) {
170
+ return {
171
+ stdout: String(display.stdout ?? ""),
172
+ stderr: String(display.stderr ?? ""),
173
+ cwdWarning: null
174
+ };
175
+ }
176
+ return splitBashStreams(summary);
177
+ }
178
+ function resolveExitCode(display, summary) {
179
+ if (display && "exit_code" in display) {
180
+ const code = display.exit_code;
181
+ if (typeof code === "number") return code;
182
+ if (typeof code === "string" && code.trim()) {
183
+ const n = Number.parseInt(code, 10);
184
+ if (Number.isFinite(n)) return n;
185
+ }
186
+ return null;
187
+ }
188
+ return parseExitCode(summary);
189
+ }
190
+ function resolveTimeoutMs(display, meta) {
191
+ if (display?.timeout_ms != null) {
192
+ const n = Number(display.timeout_ms);
193
+ return Number.isFinite(n) ? n : null;
194
+ }
195
+ if (meta != null && typeof meta === "object" && !Array.isArray(meta)) {
196
+ const ms = meta.timeout_ms;
197
+ if (ms != null) {
198
+ const n = Number(ms);
199
+ return Number.isFinite(n) ? n : null;
200
+ }
201
+ }
202
+ return null;
203
+ }
204
+ function buildBashBodyBlocks(display, summary, meta, mode, isError) {
205
+ const d = display != null && typeof display === "object" && !Array.isArray(display) ? display : null;
206
+ if (isError) {
207
+ const blocks2 = [
208
+ { text: summary.trim() || "Error", variant: "error" }
209
+ ];
210
+ const footer2 = formatTimeoutFooter(resolveTimeoutMs(d, meta));
211
+ if (footer2) blocks2.push({ text: footer2, variant: "dim" });
212
+ return { blocks: blocks2, truncated: false, remainingLines: 0 };
213
+ }
214
+ const { stdout, stderr, cwdWarning } = resolveStreams(d, summary);
215
+ const code = resolveExitCode(d, summary);
216
+ const blocks = [];
217
+ let truncated = false;
218
+ let remainingLines = 0;
219
+ const addStream = (text, variant) => {
220
+ if (!text.trim()) return;
221
+ const lines = text.split("\n");
222
+ const rendered = previewStreamText(text, mode);
223
+ if (mode === "preview" && lines.length > MAX_PREVIEW_LINES) {
224
+ truncated = true;
225
+ remainingLines += lines.length - MAX_PREVIEW_LINES;
226
+ }
227
+ blocks.push({ text: rendered, variant });
228
+ };
229
+ addStream(stdout, "normal");
230
+ addStream(stderr, "error");
231
+ if (cwdWarning) {
232
+ blocks.push({ text: cwdWarning, variant: "dim" });
233
+ }
234
+ if (code != null && code !== 0) {
235
+ blocks.push({ text: `Exit code: ${code}`, variant: "error" });
236
+ }
237
+ if (blocks.length === 0) {
238
+ const noOutputExpected = Boolean(d?.no_output_expected);
239
+ blocks.push({
240
+ text: noOutputExpected ? "Done" : "(No output)",
241
+ variant: "dim"
242
+ });
243
+ }
244
+ const footer = formatTimeoutFooter(resolveTimeoutMs(d, meta));
245
+ if (footer) {
246
+ blocks.push({ text: footer, variant: "dim" });
247
+ }
248
+ if (d?.truncated && d?.overflow_file) {
249
+ blocks.push({
250
+ text: `Output truncated; see ${String(d.overflow_file)}`,
251
+ variant: "dim"
252
+ });
253
+ }
254
+ return { blocks, truncated, remainingLines };
255
+ }
256
+
257
+ // src/view/tools/presentation/BodyBlockList.tsx
258
+ import { jsx as jsx2 } from "react/jsx-runtime";
259
+ function BodyBlockList({ blocks }) {
260
+ if (blocks.length === 0) return null;
261
+ return /* @__PURE__ */ jsx2("div", { className: "lax-tool-body__blocks", children: blocks.map((block, index) => /* @__PURE__ */ jsx2(
262
+ "div",
263
+ {
264
+ className: "lax-tool-body__block",
265
+ "data-variant": block.variant ?? "normal",
266
+ children: /* @__PURE__ */ jsx2("pre", { className: "lax-tool-body__text", children: block.text })
267
+ },
268
+ index
269
+ )) });
270
+ }
271
+
272
+ // src/view/tools/presentation/diffHelpers.ts
273
+ var WRITE_PREVIEW_LINES = 10;
274
+ var DIFF_PREVIEW_LINES = 12;
275
+ function countLines(text) {
276
+ if (!text) return 0;
277
+ return text.split("\n").length;
278
+ }
279
+ function formatDiffFromStrings(oldText, newText) {
280
+ if (oldText === newText) return "(no changes)";
281
+ const oldLines = oldText.split("\n");
282
+ const newLines = newText.split("\n");
283
+ const body = [];
284
+ let i = 0;
285
+ let j = 0;
286
+ while (i < oldLines.length || j < newLines.length) {
287
+ const oldLine = oldLines[i];
288
+ const newLine = newLines[j];
289
+ if (i < oldLines.length && j < newLines.length && oldLine === newLine) {
290
+ body.push(` ${oldLine}`);
291
+ i += 1;
292
+ j += 1;
293
+ continue;
294
+ }
295
+ if (i < oldLines.length && (j >= newLines.length || oldLine !== newLine)) {
296
+ body.push(`-${oldLine}`);
297
+ i += 1;
298
+ continue;
299
+ }
300
+ if (j < newLines.length) {
301
+ body.push(`+${newLine}`);
302
+ j += 1;
303
+ }
304
+ }
305
+ if (body.length === 0) return "(no changes)";
306
+ return ["--- old", "+++ new", "@@", ...body].join("\n");
307
+ }
308
+ function parseDiffText(diff) {
309
+ if (diff === "(no changes)") {
310
+ return [{ kind: "meta", text: diff }];
311
+ }
312
+ const result = [];
313
+ for (const line of diff.split("\n")) {
314
+ if (!line && result.length > 0) {
315
+ result.push({ kind: "context", text: "" });
316
+ continue;
317
+ }
318
+ if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("@@")) {
319
+ result.push({ kind: "meta", text: line });
320
+ } else if (line.startsWith("+")) {
321
+ result.push({ kind: "add", text: line.slice(1) });
322
+ } else if (line.startsWith("-")) {
323
+ result.push({ kind: "remove", text: line.slice(1) });
324
+ } else if (line.startsWith(" ")) {
325
+ result.push({ kind: "context", text: line.slice(1) });
326
+ } else {
327
+ result.push({ kind: "context", text: line });
328
+ }
329
+ }
330
+ return result;
331
+ }
332
+ function resolveEditDiffText(display, input, summary) {
333
+ const d = display != null && typeof display === "object" && !Array.isArray(display) ? display : null;
334
+ const inp = input != null && typeof input === "object" && !Array.isArray(input) ? input : {};
335
+ const diffField = d?.diff;
336
+ if (typeof diffField === "string" && diffField.trim()) {
337
+ return diffField.trim();
338
+ }
339
+ const oldStr = (typeof d?.old_string === "string" ? d.old_string : "") || (typeof inp.old_string === "string" ? inp.old_string : "");
340
+ const newStr = (typeof d?.new_string === "string" ? d.new_string : "") || (typeof inp.new_string === "string" ? inp.new_string : "");
341
+ if (oldStr || newStr) {
342
+ return formatDiffFromStrings(oldStr, newStr);
343
+ }
344
+ const trimmed = summary.trim();
345
+ if (trimmed) return trimmed;
346
+ return "(done)";
347
+ }
348
+
349
+ // src/view/tools/presentation/DiffView.tsx
350
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
351
+ function renderLine(line, index) {
352
+ const prefix = line.kind === "add" ? "+" : line.kind === "remove" ? "-" : line.kind === "meta" ? "" : " ";
353
+ return /* @__PURE__ */ jsxs2(
354
+ "div",
355
+ {
356
+ className: "lax-tool-diff__line",
357
+ "data-kind": line.kind,
358
+ children: [
359
+ prefix ? /* @__PURE__ */ jsx3("span", { className: "lax-tool-diff__prefix", "aria-hidden": true, children: prefix }) : null,
360
+ /* @__PURE__ */ jsx3("span", { className: "lax-tool-diff__text", children: line.text })
361
+ ]
362
+ },
363
+ index
364
+ );
365
+ }
366
+ function DiffView({
367
+ diff,
368
+ mode,
369
+ maxPreviewLines = DIFF_PREVIEW_LINES,
370
+ onExpand
371
+ }) {
372
+ const lines = parseDiffText(diff);
373
+ const needsTruncate = mode === "preview" && lines.length > maxPreviewLines;
374
+ const visible = needsTruncate ? lines.slice(0, maxPreviewLines) : lines;
375
+ return /* @__PURE__ */ jsxs2("div", { className: "lax-tool-diff", children: [
376
+ visible.map(renderLine),
377
+ needsTruncate ? /* @__PURE__ */ jsxs2(
378
+ "button",
379
+ {
380
+ type: "button",
381
+ className: "lax-tool-body__expand",
382
+ onClick: onExpand,
383
+ children: [
384
+ "+",
385
+ lines.length - maxPreviewLines,
386
+ " diff lines (\u70B9\u51FB\u5C55\u5F00)"
387
+ ]
388
+ }
389
+ ) : null
390
+ ] });
391
+ }
392
+
393
+ // src/view/tools/presentation/MarkdownBlock.tsx
394
+ import { memo, useMemo, useState } from "react";
395
+ import ReactMarkdown from "react-markdown";
396
+ import remarkGfm from "remark-gfm";
397
+ import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
398
+ import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
399
+
400
+ // src/core/context/MarkdownRendererContext.tsx
401
+ import { createContext, useContext } from "react";
402
+ var MarkdownRendererContext = createContext(
403
+ void 0
404
+ );
405
+ function useMarkdownRenderer() {
406
+ return useContext(MarkdownRendererContext);
407
+ }
408
+
409
+ // src/view/tools/presentation/MarkdownBlock.tsx
410
+ import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
411
+ function hashContent(content) {
412
+ let hash = 5381;
413
+ for (let i = 0; i < content.length; i++) {
414
+ hash = (hash << 5) + hash + content.charCodeAt(i) & 4294967295;
415
+ }
416
+ return hash.toString(36);
417
+ }
418
+ function hasMarkdownSyntax(content) {
419
+ const sample = content.length > 500 ? content.slice(0, 500) : content;
420
+ const MD_SYNTAX_RE = /[#*`|[>\-_~]|\n\n|^\d+\. |\n\d+\. /;
421
+ return MD_SYNTAX_RE.test(sample);
422
+ }
423
+ var CodeBlock = memo(function CodeBlock2({ language, content }) {
424
+ const [copied, setCopied] = useState(false);
425
+ const handleCopy = async () => {
426
+ try {
427
+ await navigator.clipboard.writeText(content);
428
+ setCopied(true);
429
+ setTimeout(() => setCopied(false), 2e3);
430
+ } catch (err) {
431
+ console.error("Failed to copy:", err);
432
+ }
433
+ };
434
+ return /* @__PURE__ */ jsxs3("div", { className: "lax-code-block", children: [
435
+ /* @__PURE__ */ jsxs3("div", { className: "lax-code-block__header", children: [
436
+ /* @__PURE__ */ jsx4("span", { className: "lax-code-block__lang", children: language || "code" }),
437
+ /* @__PURE__ */ jsx4(
438
+ "button",
439
+ {
440
+ type: "button",
441
+ className: `lax-code-block__copy ${copied ? "lax-code-block__copy--copied" : ""}`,
442
+ onClick: handleCopy,
443
+ title: copied ? "\u5DF2\u62F7\u8D1D\uFF01" : "\u62F7\u8D1D\u4EE3\u7801",
444
+ children: copied ? /* @__PURE__ */ jsxs3(Fragment, { children: [
445
+ /* @__PURE__ */ jsx4("svg", { className: "lax-code-block__icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3, children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }),
446
+ /* @__PURE__ */ jsx4("span", { children: "\u5DF2\u62F7\u8D1D" })
447
+ ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
448
+ /* @__PURE__ */ jsx4("svg", { className: "lax-code-block__icon", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx4(
449
+ "path",
450
+ {
451
+ strokeLinecap: "round",
452
+ strokeLinejoin: "round",
453
+ d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
454
+ }
455
+ ) }),
456
+ /* @__PURE__ */ jsx4("span", { children: "\u62F7\u8D1D" })
457
+ ] })
458
+ }
459
+ )
460
+ ] }),
461
+ /* @__PURE__ */ jsx4(
462
+ SyntaxHighlighter,
463
+ {
464
+ language,
465
+ style: oneDark,
466
+ customStyle: {
467
+ margin: 0,
468
+ padding: 0,
469
+ background: "transparent"
470
+ },
471
+ showLineNumbers: false,
472
+ wrapLongLines: true,
473
+ children: content
474
+ }
475
+ )
476
+ ] });
477
+ });
478
+ var MARKDOWN_COMPONENTS = {
479
+ // 代码块
480
+ code({ node, className, children, ...props }) {
481
+ const match = /language-(\w+)/.exec(className || "");
482
+ const codeContent = String(children).replace(/\n$/, "");
483
+ const inline = !className;
484
+ if (!inline && match) {
485
+ return /* @__PURE__ */ jsx4(CodeBlock, { language: match[1], content: codeContent });
486
+ }
487
+ return /* @__PURE__ */ jsx4("code", { className: "lax-markdown__inline-code", ...props, children });
488
+ },
489
+ // 标题
490
+ h1({ children }) {
491
+ return /* @__PURE__ */ jsx4("h1", { className: "lax-markdown__heading lax-markdown__h1", children });
492
+ },
493
+ h2({ children }) {
494
+ return /* @__PURE__ */ jsx4("h2", { className: "lax-markdown__heading lax-markdown__h2", children });
495
+ },
496
+ h3({ children }) {
497
+ return /* @__PURE__ */ jsx4("h3", { className: "lax-markdown__heading lax-markdown__h3", children });
498
+ },
499
+ h4({ children }) {
500
+ return /* @__PURE__ */ jsx4("h4", { className: "lax-markdown__heading lax-markdown__h4", children });
501
+ },
502
+ h5({ children }) {
503
+ return /* @__PURE__ */ jsx4("h5", { className: "lax-markdown__heading lax-markdown__h5", children });
504
+ },
505
+ h6({ children }) {
506
+ return /* @__PURE__ */ jsx4("h6", { className: "lax-markdown__heading lax-markdown__h6", children });
507
+ },
508
+ // 段落
509
+ p({ children }) {
510
+ return /* @__PURE__ */ jsx4("p", { className: "lax-markdown__paragraph", children });
511
+ },
512
+ // 列表
513
+ ul({ children }) {
514
+ return /* @__PURE__ */ jsx4("ul", { className: "lax-markdown__list lax-markdown__ul", children });
515
+ },
516
+ ol({ children }) {
517
+ return /* @__PURE__ */ jsx4("ol", { className: "lax-markdown__list lax-markdown__ol", children });
518
+ },
519
+ li({ children }) {
520
+ return /* @__PURE__ */ jsx4("li", { className: "lax-markdown__li", children });
521
+ },
522
+ // 链接
523
+ a({ children, href }) {
524
+ return /* @__PURE__ */ jsx4("a", { href, className: "lax-markdown__link", target: "_blank", rel: "noopener noreferrer", children });
525
+ },
526
+ // 引用
527
+ blockquote({ children }) {
528
+ return /* @__PURE__ */ jsx4("blockquote", { className: "lax-markdown__blockquote", children });
529
+ },
530
+ // 表格
531
+ table({ children }) {
532
+ return /* @__PURE__ */ jsx4("div", { className: "lax-markdown__table-wrapper", children: /* @__PURE__ */ jsx4("table", { className: "lax-markdown__table", children }) });
533
+ },
534
+ thead({ children }) {
535
+ return /* @__PURE__ */ jsx4("thead", { className: "lax-markdown__thead", children });
536
+ },
537
+ tbody({ children }) {
538
+ return /* @__PURE__ */ jsx4("tbody", { className: "lax-markdown__tbody", children });
539
+ },
540
+ tr({ children }) {
541
+ return /* @__PURE__ */ jsx4("tr", { className: "lax-markdown__tr", children });
542
+ },
543
+ th({ children }) {
544
+ return /* @__PURE__ */ jsx4("th", { className: "lax-markdown__th", children });
545
+ },
546
+ td({ children }) {
547
+ return /* @__PURE__ */ jsx4("td", { className: "lax-markdown__td", children });
548
+ },
549
+ // 分隔线
550
+ hr() {
551
+ return /* @__PURE__ */ jsx4("hr", { className: "lax-markdown__hr" });
552
+ },
553
+ // 强调
554
+ strong({ children }) {
555
+ return /* @__PURE__ */ jsx4("strong", { className: "lax-markdown__strong", children });
556
+ },
557
+ em({ children }) {
558
+ return /* @__PURE__ */ jsx4("em", { className: "lax-markdown__em", children });
559
+ }
560
+ };
561
+ var PureTextRenderer = memo(function PureTextRenderer2({ content, className }) {
562
+ return /* @__PURE__ */ jsx4("div", { className: ["lax-markdown", "lax-markdown--pure", className].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx4("p", { className: "lax-markdown__paragraph", children: content }) });
563
+ });
564
+ var MarkdownRenderer = memo(function MarkdownRenderer2({ content, className }) {
565
+ return /* @__PURE__ */ jsx4("div", { className: ["lax-markdown", className].filter(Boolean).join(" "), children: /* @__PURE__ */ jsx4(
566
+ ReactMarkdown,
567
+ {
568
+ remarkPlugins: [remarkGfm],
569
+ components: MARKDOWN_COMPONENTS,
570
+ children: content
571
+ }
572
+ ) });
573
+ });
574
+ function MarkdownBlock({
575
+ text,
576
+ mode,
577
+ maxLines = MAX_PREVIEW_LINES,
578
+ onExpand,
579
+ className
580
+ }) {
581
+ const markdownRenderer = useMarkdownRenderer();
582
+ const { visible, remaining, needsTruncate, contentHash } = useMemo(() => {
583
+ const lines = text.split("\n");
584
+ const needsTruncate2 = mode === "preview" && lines.length > maxLines;
585
+ const visible2 = needsTruncate2 ? lines.slice(0, maxLines).join("\n") : text;
586
+ const remaining2 = lines.length - maxLines;
587
+ const contentHash2 = hashContent(visible2);
588
+ return { visible: visible2, remaining: remaining2, needsTruncate: needsTruncate2, contentHash: contentHash2 };
589
+ }, [text, mode, maxLines]);
590
+ if (markdownRenderer) {
591
+ return /* @__PURE__ */ jsxs3("div", { className: ["lax-markdown", className].filter(Boolean).join(" "), children: [
592
+ markdownRenderer({ content: visible, className: "lax-markdown__rich" }),
593
+ needsTruncate ? /* @__PURE__ */ jsxs3(
594
+ "button",
595
+ {
596
+ type: "button",
597
+ className: "lax-tool-body__expand",
598
+ onClick: onExpand,
599
+ children: [
600
+ "+",
601
+ remaining,
602
+ " \u884C (\u70B9\u51FB\u5C55\u5F00)"
603
+ ]
604
+ }
605
+ ) : null
606
+ ] });
607
+ }
608
+ const rendererKey = `md-${contentHash}`;
609
+ if (!hasMarkdownSyntax(visible)) {
610
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
611
+ /* @__PURE__ */ jsx4(PureTextRenderer, { content: visible, className }, rendererKey),
612
+ needsTruncate ? /* @__PURE__ */ jsxs3(
613
+ "button",
614
+ {
615
+ type: "button",
616
+ className: "lax-tool-body__expand",
617
+ onClick: onExpand,
618
+ children: [
619
+ "+",
620
+ remaining,
621
+ " \u884C (\u70B9\u51FB\u5C55\u5F00)"
622
+ ]
623
+ }
624
+ ) : null
625
+ ] });
626
+ }
627
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
628
+ /* @__PURE__ */ jsx4(MarkdownRenderer, { content: visible, className }, rendererKey),
629
+ needsTruncate ? /* @__PURE__ */ jsxs3(
630
+ "button",
631
+ {
632
+ type: "button",
633
+ className: "lax-tool-body__expand",
634
+ onClick: onExpand,
635
+ children: [
636
+ "+",
637
+ remaining,
638
+ " \u884C (\u70B9\u51FB\u5C55\u5F00)"
639
+ ]
640
+ }
641
+ ) : null
642
+ ] });
643
+ }
644
+
645
+ export {
646
+ displayPath,
647
+ formatPatternTitle,
648
+ truncateLines,
649
+ formatSearchResultBody,
650
+ MAX_PREVIEW_LINES,
651
+ TruncatedContent,
652
+ truncateCommand,
653
+ formatBashTitle,
654
+ formatTimeoutFooter,
655
+ buildBashBodyBlocks,
656
+ BodyBlockList,
657
+ WRITE_PREVIEW_LINES,
658
+ countLines,
659
+ formatDiffFromStrings,
660
+ parseDiffText,
661
+ resolveEditDiffText,
662
+ DiffView,
663
+ MarkdownRendererContext,
664
+ MarkdownBlock
665
+ };
666
+ //# sourceMappingURL=chunk-4RIOBLGB.js.map