langchain_agentx_stream_ui 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-DP7V33X7.js → chunk-6Z4ZF36Z.js} +1 -1
- package/dist/chunk-6Z4ZF36Z.js.map +1 -0
- package/dist/{chunk-2T26L3VT.js → chunk-DGC43A5L.js} +5 -5
- package/dist/chunk-DGC43A5L.js.map +1 -0
- package/dist/{chunk-4RIOBLGB.js → chunk-GBY5DJ7L.js} +1 -1
- package/dist/chunk-GBY5DJ7L.js.map +1 -0
- package/dist/{chunk-ZNXAQ4ZZ.js → chunk-OFXC2GZI.js} +144 -64
- package/dist/chunk-OFXC2GZI.js.map +1 -0
- package/dist/{chunk-6DYISADG.js → chunk-T626YBJX.js} +4 -4
- package/dist/chunk-T626YBJX.js.map +1 -0
- package/dist/{chunk-7CLAU74Y.js → chunk-YUZXTGJJ.js} +2 -2
- package/dist/chunk-YUZXTGJJ.js.map +1 -0
- package/dist/index.d.ts +18 -10
- package/dist/index.js +562 -325
- package/dist/index.js.map +1 -1
- package/dist/multi-session.js +6 -6
- package/dist/tools-presentation.js +2 -2
- package/dist/tools.js +4 -4
- package/dist/virtual.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-2T26L3VT.js.map +0 -1
- package/dist/chunk-4RIOBLGB.js.map +0 -1
- package/dist/chunk-6DYISADG.js.map +0 -1
- package/dist/chunk-7CLAU74Y.js.map +0 -1
- package/dist/chunk-DP7V33X7.js.map +0 -1
- package/dist/chunk-ZNXAQ4ZZ.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/view/tools/presentation/textHelpers.ts"],"sourcesContent":["/**\r\n * textHelpers.ts — 标题预览截断\r\n *\r\n * 对齐参考:CLI widgets/tools/helpers.py truncate_preview\r\n */\r\nexport function truncatePreview(text: string, maxChars = 120): string {\r\n const line = (text || '').trim().split('\\n', 1)[0] ?? '';\r\n if (line.length > maxChars) {\r\n return `${line.slice(0, maxChars - 1)}…`;\r\n }\r\n return line;\r\n}\r\n"],"mappings":";AAKO,SAAS,gBAAgB,MAAc,WAAW,KAAa;AACpE,QAAM,QAAQ,QAAQ,IAAI,KAAK,EAAE,MAAM,MAAM,CAAC,EAAE,CAAC,KAAK;AACtD,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO,GAAG,KAAK,MAAM,GAAG,WAAW,CAAC,CAAC;AAAA,EACvC;AACA,SAAO;AACT;","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
getNoopInteractionBus,
|
|
6
6
|
resolveToolBody,
|
|
7
7
|
useInteractionBus
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-T626YBJX.js";
|
|
9
9
|
import {
|
|
10
10
|
DEFAULT_SESSION_VIEW_OPTIONS,
|
|
11
11
|
MultiSessionStoreContext,
|
|
@@ -24,13 +24,13 @@ import {
|
|
|
24
24
|
useSessionStatus,
|
|
25
25
|
useSessionViewOptions,
|
|
26
26
|
useToolDisplayOptions
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-OFXC2GZI.js";
|
|
28
28
|
import {
|
|
29
29
|
createDefaultToolRegistry
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-YUZXTGJJ.js";
|
|
31
31
|
import {
|
|
32
32
|
MarkdownRendererContext
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-GBY5DJ7L.js";
|
|
34
34
|
|
|
35
35
|
// src/view/markdown/diagramSmartFit.ts
|
|
36
36
|
function parseSvgLength(attr) {
|
|
@@ -1897,4 +1897,4 @@ export {
|
|
|
1897
1897
|
createActiveSessionBridge,
|
|
1898
1898
|
MultiAgentSession
|
|
1899
1899
|
};
|
|
1900
|
-
//# sourceMappingURL=chunk-
|
|
1900
|
+
//# sourceMappingURL=chunk-DGC43A5L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/view/markdown/diagramSmartFit.ts","../src/view/markdown/DiagramZoomShell.tsx","../src/view/markdown/fitDiagramToContainer.ts","../src/view/markdown/DiagramZoomView.tsx","../src/view/markdown/DiagramZoomFullscreenOverlay.tsx","../src/view/markdown/usePointerClick.ts","../src/view/markdown/fixDiagramSvg.ts","../src/view/markdown/mermaidTheme.ts","../src/view/markdown/initMermaid.ts","../src/view/markdown/MermaidDiagram.tsx","../src/view/markdown/mermaidDisplayUtils.ts","../src/view/markdown/useCopyText.ts","../src/view/markdown/copyToClipboard.ts","../src/view/markdown/useDebouncedValue.ts","../src/view/markdown/PlantUMLBlock.tsx","../src/view/markdown/plantumlConfig.ts","../src/view/markdown/PlantUMLDiagram.tsx","../src/view/markdown/plantumlRender.ts","../src/view/markdown/RichMarkdown.tsx","../src/view/markdown/markdownUtils.ts","../src/view/markdown/RichMarkdownStreamContext.tsx","../src/view/markdown/richMarkdownComponents.tsx","../src/view/markdown/headingIds.ts","../src/view/nodes/ReasoningNode.tsx","../src/view/tools/presentation/StreamingMarkdown.tsx","../src/view/nodes/TextNode.tsx","../src/view/nodes/ToolCallNode.tsx","../src/view/nodes/StepNode.tsx","../src/view/nodes/ErrorNode.tsx","../src/view/nodes/UnknownNode.tsx","../src/view/nodes/PermissionNode.tsx","../src/view/nodes/MemorySavedNode.tsx","../src/view/NodeRegistry.ts","../src/view/defaultRegistry.ts","../src/core/sessionStore.ts","../src/core/dedupe.ts","../src/view/MultiAgentSession.tsx"],"sourcesContent":["export interface SvgFitBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** natural:内嵌自然高度;fill:全屏/固定视口 fit */\nexport type DiagramFitLayout = 'natural' | 'fill';\n\nfunction parseSvgLength(attr: string | null): number {\n if (!attr) return NaN;\n const trimmed = attr.trim();\n if (trimmed.endsWith('%')) return NaN;\n const value = parseFloat(trimmed);\n return Number.isFinite(value) && value > 0 ? value : NaN;\n}\n\n/** viewBox / 属性解析(忽略百分比,避免把 100% 当成 100px) */\nexport function resolveSvgContentSize(svg: SVGSVGElement): { width: number; height: number } {\n const baseVal = svg.viewBox?.baseVal;\n if (baseVal && baseVal.width > 0 && baseVal.height > 0) {\n return { width: baseVal.width, height: baseVal.height };\n }\n\n const raw = svg.getAttribute('viewBox');\n if (raw) {\n const parts = raw.trim().split(/[\\s,]+/).map(Number);\n if (parts.length === 4 && parts[2]! > 0 && parts[3]! > 0) {\n return { width: parts[2]!, height: parts[3]! };\n }\n }\n\n const parsedW = parseSvgLength(svg.getAttribute('width'));\n const parsedH = parseSvgLength(svg.getAttribute('height'));\n\n return {\n width: Number.isFinite(parsedW) ? parsedW : svg.clientWidth || 0,\n height: Number.isFinite(parsedH) ? parsedH : svg.clientHeight || 0,\n };\n}\n\nexport function resolveSvgFitBox(svg: SVGSVGElement): SvgFitBox | null {\n try {\n const bbox = svg.getBBox();\n if (bbox.width > 0 && bbox.height > 0) {\n return { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height };\n }\n } catch {\n // 未挂载\n }\n\n const { width, height } = resolveSvgContentSize(svg);\n if (width > 0 && height > 0) {\n return { x: 0, y: 0, width, height };\n }\n\n return null;\n}\n\n/** 交互前轻量规范化 */\nexport function prepareSvgForInteraction(\n svg: SVGSVGElement,\n layout: DiagramFitLayout = 'fill',\n): void {\n svg.style.pointerEvents = 'none';\n svg.style.display = 'block';\n\n if (layout === 'natural') {\n svg.style.maxWidth = '100%';\n svg.style.width = 'auto';\n svg.style.height = 'auto';\n return;\n }\n\n svg.style.maxWidth = 'none';\n\n const { width, height } = resolveSvgContentSize(svg);\n const widthAttr = svg.getAttribute('width') ?? '';\n const heightAttr = svg.getAttribute('height') ?? '';\n\n if (width > 0 && (!widthAttr || widthAttr.includes('%'))) {\n svg.setAttribute('width', String(width));\n svg.style.width = `${width}px`;\n }\n if (height > 0 && (!heightAttr || heightAttr.includes('%'))) {\n svg.setAttribute('height', String(height));\n svg.style.height = `${height}px`;\n }\n}\n\nfunction readElementLayoutSize(element: Element): { width: number; height: number } {\n const rect = element.getBoundingClientRect();\n if (rect.width > 1 && rect.height > 1) {\n return { width: rect.width, height: rect.height };\n }\n if (element instanceof HTMLElement && element.offsetWidth > 1 && element.offsetHeight > 1) {\n return { width: element.offsetWidth, height: element.offsetHeight };\n }\n return { width: 0, height: 0 };\n}\n\n/** 内容在 rzpp content 层的布局尺寸(优先 DOM 实测,fallback viewBox) */\nexport function measureDiagramContentSize(\n svg: SVGSVGElement,\n layout: DiagramFitLayout = 'fill',\n): { width: number; height: number } {\n prepareSvgForInteraction(svg, layout);\n\n const host = svg.parentElement;\n if (host instanceof HTMLElement) {\n const hostSize = readElementLayoutSize(host);\n if (hostSize.width > 1 && hostSize.height > 1) {\n return hostSize;\n }\n }\n\n const svgSize = readElementLayoutSize(svg);\n if (svgSize.width > 1 && svgSize.height > 1) {\n return svgSize;\n }\n\n return resolveSvgContentSize(svg);\n}\n\nexport interface ViewportFitTransform {\n x: number;\n y: number;\n scale: number;\n}\n\nexport interface ViewportFitOptions {\n layout?: DiagramFitLayout;\n padding?: number;\n /** fill 模式:小图放大上限;natural 固定为 1 */\n maxScale?: number;\n}\n\n/**\n * natural:CSS max-width:100% 适配框宽,rzpp 恒等变换\n * fill:等比缩放进容器并居中\n */\nexport function computeViewportFitTransform(\n container: HTMLElement,\n svg: SVGSVGElement,\n options: ViewportFitOptions = {},\n): ViewportFitTransform {\n const layout = options.layout ?? 'fill';\n const padding = options.padding ?? (layout === 'natural' ? 1 : 0.96);\n\n if (layout === 'natural') {\n prepareSvgForInteraction(svg, 'natural');\n return { scale: 1, x: 0, y: 0 };\n }\n\n const { width: contentW, height: contentH } = measureDiagramContentSize(svg, layout);\n const cw = container.clientWidth;\n const ch = container.clientHeight;\n\n if (contentW < 1 || contentH < 1 || cw < 8 || ch < 32) {\n return { x: 0, y: 0, scale: 1 };\n }\n\n const maxScale = options.maxScale ?? Number.POSITIVE_INFINITY;\n const scaleX = (cw * padding) / contentW;\n const scaleY = (ch * padding) / contentH;\n const scale = Math.min(scaleX, scaleY, maxScale);\n\n return {\n scale,\n x: (cw - contentW * scale) / 2,\n y: (ch - contentH * scale) / 2,\n };\n}\n","'use client';\n\nimport {\n useCallback,\n useLayoutEffect,\n useRef,\n useState,\n type PointerEventHandler,\n type ReactNode,\n} from 'react';\nimport {\n TransformComponent,\n TransformWrapper,\n type ReactZoomPanPinchRef,\n} from 'react-zoom-pan-pinch';\n\nimport {\n prepareSvgForInteraction,\n type DiagramFitLayout,\n} from './diagramSmartFit';\nimport { fitDiagramToContainer } from './fitDiagramToContainer';\n\nconst MIN_VIEWPORT_PX = 8;\nconst MAX_INITIAL_FIT_ATTEMPTS = 48;\n\nexport interface DiagramZoomShellProps {\n fixedSvg: string;\n contentHash: string;\n className?: string;\n layout?: DiagramFitLayout;\n viewportPointerHandlers?: {\n onPointerDown?: PointerEventHandler<HTMLDivElement>;\n onPointerMove?: PointerEventHandler<HTMLDivElement>;\n onPointerUp?: PointerEventHandler<HTMLDivElement>;\n onPointerCancel?: PointerEventHandler<HTMLDivElement>;\n };\n toolbarExtra?: ReactNode;\n}\n\n/** react-zoom-pan-pinch@3.6.1 — 内嵌 natural / 全屏 fill */\nexport function DiagramZoomShell({\n fixedSvg,\n contentHash,\n className = '',\n layout = 'fill',\n viewportPointerHandlers,\n toolbarExtra,\n}: DiagramZoomShellProps) {\n const viewportRef = useRef<HTMLDivElement>(null);\n const transformRef = useRef<ReactZoomPanPinchRef | null>(null);\n const fittedForRef = useRef<string | null>(null);\n const fittingRef = useRef(false);\n const [zoomPct, setZoomPct] = useState(100);\n\n const isNatural = layout === 'natural';\n const wrapperStyle = isNatural\n ? ({ width: '100%', height: 'auto' } as const)\n : ({ width: '100%', height: '100%' } as const);\n\n const applyFit = useCallback(() => {\n if (fittingRef.current) return;\n\n const viewport = viewportRef.current;\n const ctx = transformRef.current;\n if (!viewport || !ctx) return;\n\n fittingRef.current = true;\n try {\n const svg = viewport.querySelector('svg');\n if (svg instanceof SVGSVGElement && isNatural) {\n prepareSvgForInteraction(svg, 'natural');\n }\n\n const scale = fitDiagramToContainer(ctx, viewport, {\n layout,\n maxScale: isNatural ? 1 : Number.POSITIVE_INFINITY,\n });\n setZoomPct((prev) => {\n const next = Math.round(scale * 100);\n return prev === next ? prev : next;\n });\n } finally {\n fittingRef.current = false;\n }\n }, [isNatural, layout]);\n\n const runInitialFit = useCallback(() => {\n if (fittedForRef.current === contentHash) return;\n\n const viewport = viewportRef.current;\n const ctx = transformRef.current;\n const svg = viewport?.querySelector('svg');\n\n const minH = isNatural ? MIN_VIEWPORT_PX : 32;\n if (\n !viewport\n || !ctx\n || !(svg instanceof SVGSVGElement)\n || viewport.clientWidth < MIN_VIEWPORT_PX\n || (!isNatural && viewport.clientHeight < minH)\n ) {\n return;\n }\n\n applyFit();\n fittedForRef.current = contentHash;\n }, [applyFit, contentHash, isNatural]);\n\n useLayoutEffect(() => {\n fittedForRef.current = null;\n }, [contentHash, fixedSvg, layout]);\n\n useLayoutEffect(() => {\n if (!fixedSvg) return;\n\n let cancelled = false;\n let attempts = 0;\n\n const tryFit = () => {\n if (cancelled || fittedForRef.current === contentHash) return;\n\n runInitialFit();\n if (fittedForRef.current === contentHash) return;\n\n attempts += 1;\n if (attempts < MAX_INITIAL_FIT_ATTEMPTS) window.requestAnimationFrame(tryFit);\n };\n\n tryFit();\n return () => {\n cancelled = true;\n };\n }, [fixedSvg, contentHash, layout, runInitialFit]);\n\n const zoomIn = useCallback(() => {\n transformRef.current?.zoomIn();\n }, []);\n\n const zoomOut = useCallback(() => {\n transformRef.current?.zoomOut();\n }, []);\n\n return (\n <div\n className={[\n 'diagram-zoom-shell',\n isNatural ? 'diagram-zoom-shell--natural' : 'diagram-zoom-shell--fill',\n className,\n ].filter(Boolean).join(' ')}\n >\n <div\n className=\"diagram-zoom-shell__toolbar\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n >\n <ShellButton label=\"Zoom in\" onClick={zoomIn}>+</ShellButton>\n <span className=\"diagram-zoom-shell__zoom\">{zoomPct}%</span>\n <ShellButton label=\"Zoom out\" onClick={zoomOut}>−</ShellButton>\n <ShellButton label=\"Fit diagram\" onClick={applyFit}>↺</ShellButton>\n {toolbarExtra}\n </div>\n\n <div\n ref={viewportRef}\n className={[\n 'diagram-zoom-shell__viewport',\n isNatural ? 'diagram-zoom-shell__viewport--natural' : '',\n ].filter(Boolean).join(' ')}\n {...viewportPointerHandlers}\n >\n <TransformWrapper\n key={contentHash}\n minScale={0.1}\n maxScale={4}\n centerOnInit={false}\n limitToBounds={false}\n wheel={{ step: 0.07 }}\n panning={{ velocityDisabled: true }}\n doubleClick={{ disabled: true }}\n onInit={(ctx) => {\n transformRef.current = ctx;\n }}\n onTransformed={(_ctx, state) => {\n const next = Math.round(state.scale * 100);\n setZoomPct((prev) => (prev === next ? prev : next));\n }}\n >\n <TransformComponent\n wrapperStyle={wrapperStyle}\n contentClass=\"!block !w-fit !h-fit\"\n >\n <div\n className={[\n 'diagram-zoom-shell__content',\n isNatural\n ? 'block w-full [&_svg]:mx-auto'\n : 'inline-block [&_svg]:block [&_svg]:max-w-none',\n ].join(' ')}\n dangerouslySetInnerHTML={{ __html: fixedSvg }}\n />\n </TransformComponent>\n </TransformWrapper>\n </div>\n </div>\n );\n}\n\nfunction ShellButton({\n label,\n onClick,\n children,\n}: {\n label: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n className=\"diagram-zoom-shell__btn\"\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n","import type { ReactZoomPanPinchRef } from 'react-zoom-pan-pinch';\n\nimport {\n computeViewportFitTransform,\n type DiagramFitLayout,\n} from './diagramSmartFit';\n\nexport interface FitDiagramOptions {\n layout?: DiagramFitLayout;\n maxScale?: number;\n padding?: number;\n}\n\nexport function fitDiagramToContainer(\n ctx: ReactZoomPanPinchRef,\n container: HTMLElement,\n options: FitDiagramOptions = {},\n): number {\n const svg = container.querySelector('svg');\n if (!(svg instanceof SVGSVGElement)) return 1;\n\n const measureContainer = container.querySelector('.react-transform-wrapper');\n const target = measureContainer instanceof HTMLElement ? measureContainer : container;\n\n const { x, y, scale } = computeViewportFitTransform(target, svg, options);\n\n ctx.resetTransform(0);\n ctx.setTransform(x, y, scale, 0);\n return scale;\n}\n","'use client';\n\nimport { useState, type ReactNode, type PointerEvent as ReactPointerEvent } from 'react';\n\nimport { DiagramZoomFullscreenOverlay } from './DiagramZoomFullscreenOverlay';\nimport { DiagramZoomShell } from './DiagramZoomShell';\nimport { usePointerClick } from './usePointerClick';\n\nexport interface DiagramZoomViewProps {\n fixedSvg: string;\n contentHash: string;\n title: string;\n fullscreenEnabled?: boolean;\n className?: string;\n}\n\nexport function DiagramZoomView({\n fixedSvg,\n contentHash,\n title,\n fullscreenEnabled = true,\n className = '',\n}: DiagramZoomViewProps) {\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [inlineRestoreKey, setInlineRestoreKey] = useState(0);\n\n const openFullscreen = () => {\n if (fixedSvg) setIsFullscreen(true);\n };\n\n const closeFullscreen = () => {\n setIsFullscreen(false);\n setInlineRestoreKey((key) => key + 1);\n };\n\n const canvasPointer = usePointerClick(openFullscreen);\n\n return (\n <>\n <div className={`diagram-zoom-inline ${className}`.trim()}>\n <DiagramZoomShell\n key={`inline:${contentHash}:${inlineRestoreKey}`}\n fixedSvg={fixedSvg}\n contentHash={contentHash}\n layout=\"natural\"\n viewportPointerHandlers={fullscreenEnabled ? canvasPointer : undefined}\n toolbarExtra={fullscreenEnabled ? (\n <ShellIconButton label=\"View fullscreen\" onClick={openFullscreen}>\n <FullscreenIcon />\n </ShellIconButton>\n ) : undefined}\n />\n </div>\n\n {fullscreenEnabled ? (\n <DiagramZoomFullscreenOverlay\n isOpen={isFullscreen}\n title={title}\n onClose={closeFullscreen}\n headerControls={(\n <ShellIconButton label=\"Close\" onClick={closeFullscreen}>×</ShellIconButton>\n )}\n >\n <DiagramZoomShell\n fixedSvg={fixedSvg}\n contentHash={`fs:${contentHash}`}\n layout=\"fill\"\n />\n </DiagramZoomFullscreenOverlay>\n ) : null}\n </>\n );\n}\n\nfunction stopPointerPropagation(event: ReactPointerEvent) {\n event.stopPropagation();\n}\n\nfunction ShellIconButton({\n label,\n onClick,\n children,\n}: {\n label: string;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n aria-label={label}\n title={label}\n className=\"diagram-zoom-shell__btn\"\n onClick={onClick}\n onPointerDown={stopPointerPropagation}\n >\n {children}\n </button>\n );\n}\n\nfunction FullscreenIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </svg>\n );\n}\n","'use client';\n\nimport { useEffect, type ReactNode } from 'react';\n\nexport interface DiagramZoomFullscreenOverlayProps {\n isOpen: boolean;\n title: string;\n onClose: () => void;\n headerControls?: ReactNode;\n children: ReactNode;\n}\n\nexport function DiagramZoomFullscreenOverlay({\n isOpen,\n title,\n onClose,\n headerControls,\n children,\n}: DiagramZoomFullscreenOverlayProps) {\n useEffect(() => {\n if (!isOpen) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onClose();\n };\n\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n window.addEventListener('keydown', onKeyDown);\n\n return () => {\n window.removeEventListener('keydown', onKeyDown);\n document.body.style.overflow = prevOverflow;\n };\n }, [isOpen, onClose]);\n\n if (!isOpen) return null;\n\n return (\n <div\n className=\"diagram-zoom-fs-overlay\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n onClick={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n className=\"diagram-zoom-fs-panel\"\n onClick={(event) => event.stopPropagation()}\n >\n <div className=\"diagram-zoom-fs-header\">\n <span className=\"diagram-zoom-fs-title\">{title}</span>\n {headerControls}\n </div>\n <div className=\"diagram-zoom-fs-stage\">{children}</div>\n </div>\n </div>\n );\n}\n","import { useRef, type PointerEvent as ReactPointerEvent } from 'react';\r\n\r\nconst DEFAULT_MOVE_THRESHOLD_PX = 6;\r\n\r\nexport function didPointerDrag(\r\n start: { x: number; y: number },\r\n end: { x: number; y: number },\r\n moveThresholdPx = DEFAULT_MOVE_THRESHOLD_PX,\r\n): boolean {\r\n return Math.hypot(end.x - start.x, end.y - start.y) > moveThresholdPx;\r\n}\r\n\r\n/** Distinguish click from pan/drag — only fire when pointer did not move meaningfully. */\r\nexport function usePointerClick(onClick: () => void, moveThresholdPx = DEFAULT_MOVE_THRESHOLD_PX) {\r\n const startRef = useRef<{ x: number; y: number } | null>(null);\r\n const movedRef = useRef(false);\r\n\r\n return {\r\n onPointerDown(event: ReactPointerEvent) {\r\n startRef.current = { x: event.clientX, y: event.clientY };\r\n movedRef.current = false;\r\n },\r\n onPointerMove(event: ReactPointerEvent) {\r\n const start = startRef.current;\r\n if (!start) return;\r\n const dx = event.clientX - start.x;\r\n const dy = event.clientY - start.y;\r\n if (Math.hypot(dx, dy) > moveThresholdPx) {\r\n movedRef.current = true;\r\n }\r\n },\r\n onPointerUp(event: ReactPointerEvent) {\r\n const start = startRef.current;\r\n if (start && didPointerDrag(start, { x: event.clientX, y: event.clientY }, moveThresholdPx)) {\r\n movedRef.current = true;\r\n }\r\n if (!movedRef.current && startRef.current) {\r\n onClick();\r\n }\r\n startRef.current = null;\r\n movedRef.current = false;\r\n },\r\n onPointerCancel() {\r\n startRef.current = null;\r\n movedRef.current = false;\r\n },\r\n };\r\n}\r\n","/** Mermaid / PlantUML:禁用 SVG 命中,并规范化百分比宽高(避免 fit 把 100% 当成 100px) */\nexport function fixDiagramSvg(svg: string): string {\n if (!svg.includes('<svg')) return svg;\n\n let result = svg;\n if (!/pointer-events\\s*:\\s*none/i.test(result)) {\n result = result.replace('<svg', '<svg style=\"pointer-events:none;\"');\n }\n\n return normalizeSvgPercentDimensions(result);\n}\n\nfunction normalizeSvgPercentDimensions(svg: string): string {\n const openTagMatch = svg.match(/<svg\\b([^>]*)>/i);\n if (!openTagMatch) return svg;\n\n const attrs = openTagMatch[1] ?? '';\n const viewBoxMatch = attrs.match(/\\bviewBox\\s*=\\s*[\"']([^\"']+)[\"']/i);\n if (!viewBoxMatch) return svg;\n\n const parts = viewBoxMatch[1]!.trim().split(/[\\s,]+/).map(Number);\n if (parts.length !== 4 || parts[2]! <= 0 || parts[3]! <= 0) return svg;\n\n const vbW = parts[2]!;\n const vbH = parts[3]!;\n let nextAttrs = attrs;\n\n const widthMatch = nextAttrs.match(/\\bwidth\\s*=\\s*[\"']([^\"']*)[\"']/i);\n if (!widthMatch || widthMatch[1]!.includes('%')) {\n nextAttrs = widthMatch\n ? nextAttrs.replace(/\\bwidth\\s*=\\s*[\"'][^\"']*[\"']/i, `width=\"${vbW}\"`)\n : `${nextAttrs} width=\"${vbW}\"`;\n }\n\n const heightMatch = nextAttrs.match(/\\bheight\\s*=\\s*[\"']([^\"']*)[\"']/i);\n if (!heightMatch || heightMatch[1]!.includes('%')) {\n nextAttrs = heightMatch\n ? nextAttrs.replace(/\\bheight\\s*=\\s*[\"'][^\"']*[\"']/i, `height=\"${vbH}\"`)\n : `${nextAttrs} height=\"${vbH}\"`;\n }\n\n if (nextAttrs === attrs) return svg;\n return svg.replace(openTagMatch[0], `<svg${nextAttrs}>`);\n}\n","/**\n * 浅色:Mermaid `base` + 低饱和 themeVariables(填色区分节点,文字统一中性灰)。\n * 深色:SVG `data-theme=\"dark\"` + themeCSS 接入宿主 --lax-mermaid-* token。\n * 宿主可 configureMermaid({ theme: 'default' }) 恢复 Mermaid 原生高对比配色。\n */\n\n/** 浅色标签字色:中性 slate(GitHub / Notion 文档图 — 字不染色,仅背景/边框分档) */\nexport const MERMAID_LIGHT_LABEL_COLOR = '#334155';\n\n/** 浅色文档风 palette(低饱和填色 + 统一字色) */\nexport const MERMAID_LIGHT_THEME_VARIABLES: Record<string, string | boolean> = {\n darkMode: false,\n background: 'transparent',\n\n /* flowchart 节点三档:muted indigo / sage / violet(仅 fill / stroke) */\n primaryColor: '#eef2ff',\n primaryTextColor: MERMAID_LIGHT_LABEL_COLOR,\n primaryBorderColor: '#c7d2fe',\n\n secondaryColor: '#ecfdf5',\n secondaryTextColor: MERMAID_LIGHT_LABEL_COLOR,\n secondaryBorderColor: '#a7f3d0',\n\n tertiaryColor: '#f5f3ff',\n tertiaryTextColor: MERMAID_LIGHT_LABEL_COLOR,\n tertiaryBorderColor: '#ddd6fe',\n\n mainBkg: '#eef2ff',\n secondBkg: '#ecfdf5',\n tertiaryBkg: '#f5f3ff',\n\n /* 全局与连线标签 */\n lineColor: '#94a3b8',\n textColor: MERMAID_LIGHT_LABEL_COLOR,\n titleColor: MERMAID_LIGHT_LABEL_COLOR,\n edgeLabelBackground: 'transparent',\n\n /* subgraph / cluster */\n clusterBkg: '#f8fafc',\n clusterBorder: '#e2e8f0',\n\n /* sequence */\n actorBkg: '#f8fafc',\n actorBorder: '#cbd5e1',\n actorTextColor: MERMAID_LIGHT_LABEL_COLOR,\n actorLineColor: '#94a3b8',\n signalColor: '#64748b',\n signalTextColor: MERMAID_LIGHT_LABEL_COLOR,\n labelBoxBkgColor: '#f8fafc',\n labelBoxBorderColor: '#e2e8f0',\n labelTextColor: MERMAID_LIGHT_LABEL_COLOR,\n noteBkgColor: '#f1f5f9',\n noteTextColor: MERMAID_LIGHT_LABEL_COLOR,\n noteBorderColor: '#cbd5e1',\n};\n\n/** 标签字色:优先宿主 --lax-mermaid-label-color / --foreground(sync 到 SVG 根) */\nconst MERMAID_LABEL_TEXT_SELECTORS = `\n .edgeLabel,\n .edgeLabel span,\n .edgeLabel p,\n .label,\n .nodeLabel,\n .nodeLabel span,\n .flowchart-label text,\n .cluster-label,\n .cluster-label span,\n text.actor,\n .messageText,\n text.sequenceText,\n .noteText,\n .titleText\n`;\n\nexport const MERMAID_THEME_CSS = `\n .edgeLabel,\n .edgeLabel p {\n background-color: transparent !important;\n }\n\n ${MERMAID_LABEL_TEXT_SELECTORS} {\n fill: var(--lax-mermaid-label-color, var(--lax-foreground, ${MERMAID_LIGHT_LABEL_COLOR})) !important;\n color: var(--lax-mermaid-label-color, var(--lax-foreground, ${MERMAID_LIGHT_LABEL_COLOR})) !important;\n }\n\n [data-theme=\"dark\"] .node rect,\n [data-theme=\"dark\"] .node circle,\n [data-theme=\"dark\"] .node ellipse,\n [data-theme=\"dark\"] .node polygon,\n [data-theme=\"dark\"] .node path,\n [data-theme=\"dark\"] g.node rect,\n [data-theme=\"dark\"] g.node circle,\n [data-theme=\"dark\"] g.node ellipse,\n [data-theme=\"dark\"] g.node polygon,\n [data-theme=\"dark\"] g.node path {\n fill: var(--lax-mermaid-node-fill, var(--lax-card-bg, var(--card-bg, transparent))) !important;\n stroke: var(--lax-border-color, var(--border-color, currentColor)) !important;\n }\n [data-theme=\"dark\"] .edgePath .path,\n [data-theme=\"dark\"] .flowchart-link,\n [data-theme=\"dark\"] .edgePaths path {\n stroke: var(--lax-mermaid-edge-color, var(--lax-accent-primary, var(--accent-primary, currentColor))) !important;\n }\n [data-theme=\"dark\"] .cluster rect,\n [data-theme=\"dark\"] .cluster polygon,\n [data-theme=\"dark\"] .actor {\n fill: var(--lax-mermaid-node-fill, var(--lax-card-bg, var(--card-bg, transparent))) !important;\n stroke: var(--lax-border-color, var(--border-color, currentColor)) !important;\n }\n [data-theme=\"dark\"] .messageLine0,\n [data-theme=\"dark\"] .messageLine1 {\n stroke: var(--lax-mermaid-edge-color, var(--lax-accent-primary, var(--accent-primary, currentColor))) !important;\n }\n`;\n\nexport type MermaidThemeName = 'neutral' | 'default' | 'dark' | 'forest' | 'base';\n\nexport interface MermaidInitOptions {\n theme?: MermaidThemeName;\n maxTextSize?: number;\n /** 仅 `theme: 'base'` 时生效;默认使用 MERMAID_LIGHT_THEME_VARIABLES */\n themeVariables?: Record<string, string | number | boolean>;\n}\n\n/** 文档风低饱和配色(base + themeVariables) */\nexport const DEFAULT_MERMAID_INIT: MermaidInitOptions = {\n theme: 'base',\n maxTextSize: 100_000,\n};\n\n/** 深色 themeCSS 读取的 CSS 变量(由 .lax-mermaid 桥接,宿主可覆盖) */\nexport const MERMAID_THEME_CSS_VAR_NAMES = [\n '--lax-mermaid-node-fill',\n '--lax-mermaid-label-color',\n '--lax-mermaid-edge-color',\n '--lax-bg-surface',\n '--lax-diagram-bg',\n '--lax-card-bg',\n '--lax-foreground',\n '--lax-border-color',\n '--lax-accent-primary',\n] as const;\n","import {\n DEFAULT_MERMAID_INIT,\n MERMAID_LIGHT_THEME_VARIABLES,\n MERMAID_THEME_CSS,\n type MermaidInitOptions,\n} from './mermaidTheme';\n\nlet mermaidInitPromise: Promise<typeof import('mermaid').default | null> | null = null;\nlet activeInitOptions: MermaidInitOptions = { ...DEFAULT_MERMAID_INIT };\n\nfunction buildInitializeConfig(options: MermaidInitOptions) {\n const theme = options.theme ?? DEFAULT_MERMAID_INIT.theme;\n const useBasePalette = theme === 'base';\n\n return {\n startOnLoad: false,\n theme,\n securityLevel: 'strict' as const,\n suppressErrorRendering: true,\n logLevel: 'error' as const,\n maxTextSize: options.maxTextSize ?? DEFAULT_MERMAID_INIT.maxTextSize,\n htmlLabels: true,\n themeCSS: MERMAID_THEME_CSS,\n ...(useBasePalette && {\n themeVariables: {\n ...MERMAID_LIGHT_THEME_VARIABLES,\n ...options.themeVariables,\n },\n }),\n flowchart: {\n htmlLabels: true,\n curve: 'basis' as const,\n nodeSpacing: 60,\n rankSpacing: 60,\n padding: 20,\n },\n };\n}\n\n/** 覆盖默认 mermaid 初始化(需在首次 render 前调用) */\nexport function configureMermaid(options: MermaidInitOptions): void {\n activeInitOptions = { ...DEFAULT_MERMAID_INIT, ...options };\n mermaidInitPromise = null;\n}\n\n/** 懒加载并初始化 mermaid(peer:mermaid) */\nexport async function loadMermaid(): Promise<typeof import('mermaid').default | null> {\n if (typeof window === 'undefined') return null;\n\n if (!mermaidInitPromise) {\n mermaidInitPromise = import('mermaid')\n .then((mod) => {\n const mermaid = mod.default;\n mermaid.initialize(buildInitializeConfig(activeInitOptions));\n return mermaid;\n })\n .catch(() => null);\n }\n\n return mermaidInitPromise;\n}\n","import { useEffect, useId, useRef, useState } from 'react';\n\nimport { DiagramZoomView } from './DiagramZoomView';\nimport { fixDiagramSvg } from './fixDiagramSvg';\nimport { loadMermaid } from './initMermaid';\nimport { syncDarkThemeOnSvgElement, syncMermaidThemeTokensOnSvgElement, useDarkMode } from './mermaidDisplayUtils';\nimport { MERMAID_THEME_CSS_VAR_NAMES } from './mermaidTheme';\nimport { useCopyText } from './useCopyText';\nimport { useDebouncedValue } from './useDebouncedValue';\n\nconst MERMAID_RENDER_DEBOUNCE_MS = 350;\n\nexport interface MermaidDiagramProps {\n chart: string;\n className?: string;\n fullscreenEnabled?: boolean;\n}\n\nexport function MermaidDiagram({\n chart,\n className = '',\n fullscreenEnabled = true,\n}: MermaidDiagramProps) {\n const [rawSvg, setRawSvg] = useState('');\n const [error, setError] = useState<string | null>(null);\n const { copied, copy } = useCopyText(chart);\n const wrapRef = useRef<HTMLDivElement>(null);\n const rawSvgRef = useRef('');\n const reactId = useId().replace(/:/g, '');\n const renderId = `lax-mermaid-${reactId}`;\n const isDark = useDarkMode();\n const debouncedChart = useDebouncedValue(chart.trim(), MERMAID_RENDER_DEBOUNCE_MS);\n\n useEffect(() => {\n rawSvgRef.current = rawSvg;\n }, [rawSvg]);\n\n useEffect(() => {\n if (!debouncedChart) return;\n\n let cancelled = false;\n\n const renderChart = async () => {\n const mermaid = await loadMermaid();\n if (cancelled) return;\n\n if (!mermaid) {\n if (!rawSvgRef.current) {\n setError('mermaid peer dependency is not installed');\n }\n return;\n }\n\n try {\n setError(null);\n const { svg: renderedSvg } = await mermaid.render(renderId, debouncedChart);\n if (!cancelled) {\n setRawSvg(renderedSvg);\n }\n } catch (err) {\n if (!cancelled && !rawSvgRef.current) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n }\n }\n };\n\n void renderChart();\n\n return () => {\n cancelled = true;\n };\n }, [debouncedChart, renderId]);\n\n const fixedSvg = rawSvg ? fixDiagramSvg(rawSvg) : '';\n const contentHash = `mermaid:${debouncedChart}:${fixedSvg.length}`;\n\n useEffect(() => {\n const host = wrapRef.current;\n const svg = host?.querySelector('svg');\n if (!(svg instanceof SVGSVGElement)) return;\n\n syncDarkThemeOnSvgElement(svg, isDark);\n syncMermaidThemeTokensOnSvgElement(svg, host, MERMAID_THEME_CSS_VAR_NAMES);\n }, [isDark, fixedSvg]);\n\n const handleCopy = () => void copy();\n\n const toolbar = (\n <div className=\"lax-mermaid__toolbar\">\n <span className=\"lax-mermaid__label\">Mermaid</span>\n <div className=\"lax-mermaid__actions\">\n <button type=\"button\" className=\"lax-mermaid__copy\" onClick={handleCopy}>\n {copied ? 'Copied' : 'Copy'}\n </button>\n </div>\n </div>\n );\n\n if (error) {\n return (\n <div className={`lax-mermaid lax-mermaid--error ${className}`.trim()}>\n {toolbar}\n <pre className=\"lax-mermaid__fallback\">{chart}</pre>\n <p className=\"lax-mermaid__error-text\">{error}</p>\n </div>\n );\n }\n\n if (!fixedSvg) {\n return (\n <div className={`lax-mermaid lax-mermaid--loading ${className}`.trim()}>\n <span className=\"lax-mermaid__loading-dots\" aria-hidden=\"true\">\n <span /><span /><span />\n </span>\n <span className=\"lax-mermaid__loading-text\">Rendering diagram…</span>\n </div>\n );\n }\n\n return (\n <div className={`lax-mermaid ${className}`.trim()} ref={wrapRef}>\n {toolbar}\n <div className=\"lax-diagram-canvas-wrap\">\n <DiagramZoomView\n fixedSvg={fixedSvg}\n contentHash={contentHash}\n title=\"Diagram\"\n fullscreenEnabled={fullscreenEnabled}\n />\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/** 检测宿主暗色:data-theme / class.dark / prefers-color-scheme */\nexport function isDarkMode(): boolean {\n if (typeof document === 'undefined') return false;\n\n const root = document.documentElement;\n const dataTheme = root.getAttribute('data-theme');\n if (dataTheme === 'dark') return true;\n if (dataTheme === 'light') return false;\n if (root.classList.contains('dark')) return true;\n\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return false;\n }\n\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n}\n\nexport function applyDarkThemeToSvg(svg: string, dark: boolean): string {\n if (!svg) return svg;\n\n const withoutAttr = svg.replace(/\\sdata-theme=\"dark\"/g, '');\n if (!dark) return withoutAttr;\n if (withoutAttr.includes('data-theme=\"dark\"')) return withoutAttr;\n\n return withoutAttr.replace('<svg ', '<svg data-theme=\"dark\" ');\n}\n\n/** Set data-theme on live SVG without replacing markup (keeps pan-zoom DOM intact). */\nexport function syncDarkThemeOnSvgElement(svg: SVGSVGElement | null, dark: boolean): void {\n if (!svg) return;\n if (dark) svg.setAttribute('data-theme', 'dark');\n else svg.removeAttribute('data-theme');\n}\n\n/**\n * 将宿主 .lax-mermaid 上已解析的 --lax-* token 写入 SVG 根节点,\n * 确保内嵌 themeCSS 中 var() 能读到(不硬编码颜色)。\n */\nexport function syncMermaidThemeTokensOnSvgElement(\n svg: SVGSVGElement | null,\n host: HTMLElement | null,\n tokenNames: readonly string[],\n): void {\n if (!svg || !host) return;\n\n const computed = getComputedStyle(host);\n for (const name of tokenNames) {\n const value = computed.getPropertyValue(name).trim();\n if (value) svg.style.setProperty(name, value);\n }\n}\n\nexport function useDarkMode(): boolean {\n const [dark, setDark] = useState(false);\n\n useEffect(() => {\n const update = () => setDark(isDarkMode());\n update();\n\n const mq = typeof window.matchMedia === 'function'\n ? window.matchMedia('(prefers-color-scheme: dark)')\n : null;\n mq?.addEventListener('change', update);\n\n const observer = new MutationObserver(update);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class', 'data-theme'],\n });\n\n return () => {\n mq?.removeEventListener('change', update);\n observer.disconnect();\n };\n }, []);\n\n return dark;\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\n\r\nimport { copyToClipboard } from './copyToClipboard';\r\n\r\n/** 带 Copied 反馈的拷贝 hook */\r\nexport function useCopyText(text: string, resetMs = 2000) {\r\n const [copied, setCopied] = useState(false);\r\n const timerRef = useRef<number>();\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timerRef.current !== undefined) {\r\n window.clearTimeout(timerRef.current);\r\n }\r\n };\r\n }, []);\r\n\r\n const copy = useCallback(async () => {\r\n const ok = await copyToClipboard(text);\r\n if (!ok) return;\r\n\r\n setCopied(true);\r\n if (timerRef.current !== undefined) {\r\n window.clearTimeout(timerRef.current);\r\n }\r\n timerRef.current = window.setTimeout(() => setCopied(false), resetMs);\r\n }, [text, resetMs]);\r\n\r\n return { copied, copy };\r\n}\r\n","/** 拷贝文本到剪贴板;clipboard API 失败时降级 execCommand */\r\nexport async function copyToClipboard(text: string): Promise<boolean> {\r\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n } catch {\r\n // fall through\r\n }\r\n }\r\n\r\n if (typeof document === 'undefined') return false;\r\n\r\n try {\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.left = '-9999px';\r\n document.body.appendChild(textArea);\r\n textArea.select();\r\n const ok = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n return ok;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n","import { useEffect, useState } from 'react';\r\n\r\nexport function useDebouncedValue<T>(value: T, delayMs: number): T {\r\n const [debounced, setDebounced] = useState(value);\r\n\r\n useEffect(() => {\r\n const timer = window.setTimeout(() => setDebounced(value), delayMs);\r\n return () => window.clearTimeout(timer);\r\n }, [value, delayMs]);\r\n\r\n return debounced;\r\n}\r\n","import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\r\nimport { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';\r\n\r\nimport { useCopyText } from './useCopyText';\r\n\r\nexport interface PlantUMLBlockProps {\r\n content: string;\r\n className?: string;\r\n}\r\n\r\n/** PlantUML 源码块(高亮 + 拷贝;供 sourceOnly / 降级展示) */\r\nexport function PlantUMLBlock({ content, className = '' }: PlantUMLBlockProps) {\r\n const { copied, copy } = useCopyText(content);\r\n\r\n return (\r\n <div className={`lax-plantuml lax-code-block lax-code-block--rich ${className}`.trim()}>\r\n <div className=\"lax-code-block__header\">\r\n <span className=\"lax-code-block__lang\">PlantUML</span>\r\n <button\r\n type=\"button\"\r\n className={`lax-code-block__copy ${copied ? 'lax-code-block__copy--copied' : ''}`}\r\n onClick={() => void copy()}\r\n >\r\n {copied ? 'Copied' : 'Copy'}\r\n </button>\r\n </div>\r\n <SyntaxHighlighter\r\n language=\"text\"\r\n style={oneDark}\r\n customStyle={{ margin: 0, padding: '0.75rem 1rem', background: 'transparent' }}\r\n showLineNumbers\r\n wrapLongLines\r\n >\r\n {content}\r\n </SyntaxHighlighter>\r\n </div>\r\n );\r\n}\r\n","const DEFAULT_PLANTUML_SERVER_URL = 'https://kroki.io';\n\nlet plantumlServerUrl = DEFAULT_PLANTUML_SERVER_URL;\nconst configListeners = new Set<() => void>();\n\nfunction notifyConfigListeners(): void {\n configListeners.forEach((listener) => listener());\n}\n\n/** 配置 PlantUML 渲染服务(默认 Kroki:https://kroki.io) */\nexport function configurePlantumlServer(url: string): void {\n const next = url.replace(/\\/$/, '');\n if (next === plantumlServerUrl) return;\n plantumlServerUrl = next;\n notifyConfigListeners();\n}\n\nexport function getPlantumlServerUrl(): string {\n return plantumlServerUrl;\n}\n\nexport function resetPlantumlServerUrl(): void {\n plantumlServerUrl = DEFAULT_PLANTUML_SERVER_URL;\n notifyConfigListeners();\n}\n\n/** 服务端 URL 变更时通知(供 PlantUMLDiagram 重新拉取) */\nexport function subscribePlantumlServerConfig(listener: () => void): () => void {\n configListeners.add(listener);\n return () => {\n configListeners.delete(listener);\n };\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { DiagramZoomView } from './DiagramZoomView';\nimport { PlantUMLBlock } from './PlantUMLBlock';\nimport { fetchPlantumlSvg } from './plantumlRender';\nimport { subscribePlantumlServerConfig } from './plantumlConfig';\nimport { useCopyText } from './useCopyText';\nimport { useDebouncedValue } from './useDebouncedValue';\n\nconst PLANTUML_RENDER_DEBOUNCE_MS = 350;\n\nexport interface PlantUMLDiagramProps {\n content: string;\n className?: string;\n serverUrl?: string;\n fullscreenEnabled?: boolean;\n sourceOnly?: boolean;\n}\n\nexport function PlantUMLDiagram({\n content,\n className = '',\n serverUrl,\n fullscreenEnabled = true,\n sourceOnly = false,\n}: PlantUMLDiagramProps) {\n const [fixedSvg, setFixedSvg] = useState('');\n const [error, setError] = useState<string | null>(null);\n const { copied, copy } = useCopyText(content);\n const svgRef = useRef('');\n const debouncedContent = useDebouncedValue(content.trim(), PLANTUML_RENDER_DEBOUNCE_MS);\n const [serverConfigRev, setServerConfigRev] = useState(0);\n\n useEffect(() => subscribePlantumlServerConfig(() => {\n setServerConfigRev((rev) => rev + 1);\n }), []);\n\n useEffect(() => {\n svgRef.current = fixedSvg;\n }, [fixedSvg]);\n\n useEffect(() => {\n if (!debouncedContent || sourceOnly) return;\n\n let cancelled = false;\n\n const render = async () => {\n if (typeof window === 'undefined') return;\n\n try {\n setError(null);\n const rendered = await fetchPlantumlSvg(\n debouncedContent,\n serverUrl,\n );\n if (!cancelled) setFixedSvg(rendered);\n } catch (err) {\n if (!cancelled) {\n const message = err instanceof Error ? err.message : String(err);\n setError(message);\n }\n }\n };\n\n void render();\n\n return () => {\n cancelled = true;\n };\n }, [debouncedContent, serverUrl, sourceOnly, serverConfigRev]);\n\n if (sourceOnly) {\n return <PlantUMLBlock content={content} className={className} />;\n }\n\n const handleCopy = () => void copy();\n const contentHash = `plantuml:${debouncedContent}:${fixedSvg.length}`;\n\n const toolbar = (\n <div className=\"lax-plantuml__toolbar\">\n <span className=\"lax-plantuml__label\">PlantUML</span>\n <div className=\"lax-plantuml__actions\">\n <button type=\"button\" className=\"lax-plantuml__copy\" onClick={handleCopy}>\n {copied ? 'Copied' : 'Copy'}\n </button>\n </div>\n </div>\n );\n\n if (error) {\n return (\n <div className={`lax-plantuml lax-plantuml--error ${className}`.trim()}>\n {toolbar}\n <pre className=\"lax-plantuml__fallback\">{content}</pre>\n <p className=\"lax-plantuml__error-text\">{error}</p>\n </div>\n );\n }\n\n if (!fixedSvg) {\n return (\n <div className={`lax-plantuml lax-plantuml--loading ${className}`.trim()}>\n <span className=\"lax-plantuml__loading-dots\" aria-hidden=\"true\">\n <span /><span /><span />\n </span>\n <span className=\"lax-plantuml__loading-text\">Rendering diagram…</span>\n </div>\n );\n }\n\n return (\n <div className={`lax-plantuml ${className}`.trim()}>\n {toolbar}\n <div className=\"lax-diagram-canvas-wrap\">\n <DiagramZoomView\n fixedSvg={fixedSvg}\n contentHash={contentHash}\n title=\"PlantUML\"\n fullscreenEnabled={fullscreenEnabled}\n />\n </div>\n </div>\n );\n}\n","import { fixDiagramSvg } from './fixDiagramSvg';\nimport { getPlantumlServerUrl } from './plantumlConfig';\n\n/** 补全 @startuml / @enduml 包裹 */\nexport function normalizePlantumlSource(source: string): string {\n const trimmed = source.trim();\n if (!trimmed) return trimmed;\n if (trimmed.includes('@startuml')) return trimmed;\n return `@startuml\\n${trimmed}\\n@enduml`;\n}\n\n/** 通过 Kroki(或兼容服务)POST 渲染 PlantUML → SVG 文本 */\nexport async function fetchPlantumlSvg(\n source: string,\n serverUrl = getPlantumlServerUrl(),\n): Promise<string> {\n const base = serverUrl.replace(/\\/$/, '');\n const url = base.startsWith('/') ? base : `${base}/`;\n const diagramSource = normalizePlantumlSource(source);\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'image/svg+xml',\n },\n body: JSON.stringify({\n diagram_source: diagramSource,\n diagram_type: 'plantuml',\n output_format: 'svg',\n }),\n });\n\n if (!res.ok) {\n const detail = await res.text().catch(() => '');\n const suffix = detail ? `: ${detail.slice(0, 200)}` : '';\n throw new Error(`PlantUML render failed (${res.status})${suffix}`);\n }\n\n const svg = await res.text();\n if (!svg.includes('<svg')) {\n throw new Error('PlantUML render returned non-SVG response');\n }\n\n return fixDiagramSvg(svg);\n}\n","import { useMemo } from 'react';\r\nimport ReactMarkdown from 'react-markdown';\r\nimport remarkGfm from 'remark-gfm';\r\n\r\nimport {\r\n collapseExcessiveBlankLines,\r\n hasMarkdownSyntax,\r\n} from './markdownUtils';\r\nimport { RichMarkdownStreamContext } from './RichMarkdownStreamContext';\r\nimport { RICH_MARKDOWN_COMPONENTS } from './richMarkdownComponents';\r\n\r\nexport interface RichMarkdownProps {\r\n content: string;\r\n className?: string;\r\n /** 流式未稳定后缀:diagram fence 暂以源码展示 */\r\n deferDiagrams?: boolean;\r\n}\r\n\r\n/** Web 向富 Markdown(TextNode S1);含 Mermaid、GFM、代码高亮。 */\r\nexport function RichMarkdown({\r\n content,\r\n className = '',\r\n deferDiagrams = false,\r\n}: RichMarkdownProps) {\r\n const processed = useMemo(() => collapseExcessiveBlankLines(content), [content]);\r\n\r\n if (!processed) {\r\n return null;\r\n }\r\n\r\n if (!hasMarkdownSyntax(processed)) {\r\n return (\r\n <p className={`lax-markdown__paragraph ${className}`.trim()}>{processed}</p>\r\n );\r\n }\r\n\r\n return (\r\n <RichMarkdownStreamContext.Provider value={{ deferDiagrams }}>\r\n <div className={className || undefined}>\r\n <ReactMarkdown remarkPlugins={[remarkGfm]} components={RICH_MARKDOWN_COMPONENTS}>\r\n {processed}\r\n </ReactMarkdown>\r\n </div>\r\n </RichMarkdownStreamContext.Provider>\r\n );\r\n}\r\n","/** 检测 markdown 语法(快速路径,检查前 500 字符) */\r\nconst MD_SYNTAX_RE = /[#*`|[>\\-_~]|\\n\\n|^\\d+\\. |\\n\\d+\\. /;\r\n\r\nexport function hasMarkdownSyntax(content: string): boolean {\r\n const sample = content.length > 500 ? content.slice(0, 500) : content;\r\n return MD_SYNTAX_RE.test(sample);\r\n}\r\n\r\nexport function hashContent(content: string): string {\r\n let hash = 5381;\r\n for (let i = 0; i < content.length; i++) {\r\n hash = ((hash << 5) + hash + content.charCodeAt(i)) & 0xffffffff;\r\n }\r\n return hash.toString(36);\r\n}\r\n\r\nexport function collapseExcessiveBlankLines(text: string): string {\r\n return text.replace(/\\n{3,}/g, '\\n\\n').trim();\r\n}\r\n\r\nexport function paragraphHasContent(children: unknown): boolean {\r\n if (children == null || children === false) return false;\r\n if (typeof children === 'string') return children.trim().length > 0;\r\n if (typeof children === 'number') return true;\r\n if (Array.isArray(children)) return children.some(paragraphHasContent);\r\n return true;\r\n}\r\n","import { createContext, useContext } from 'react';\r\n\r\nexport interface RichMarkdownStreamOptions {\r\n /** 流式未稳定后缀:diagram 以源码展示,避免半句 mermaid/plantuml 反复渲染闪烁 */\r\n deferDiagrams: boolean;\r\n}\r\n\r\nconst DEFAULT_OPTIONS: RichMarkdownStreamOptions = { deferDiagrams: false };\r\n\r\nexport const RichMarkdownStreamContext = createContext(DEFAULT_OPTIONS);\r\n\r\nexport function useRichMarkdownStream(): RichMarkdownStreamOptions {\r\n return useContext(RichMarkdownStreamContext);\r\n}\r\n","import { type ReactNode } from 'react';\r\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\r\nimport { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';\r\n\r\nimport { generateHeadingId } from './headingIds';\r\nimport { MermaidDiagram } from './MermaidDiagram';\r\nimport { PlantUMLDiagram } from './PlantUMLDiagram';\r\nimport { paragraphHasContent } from './markdownUtils';\r\nimport { useRichMarkdownStream } from './RichMarkdownStreamContext';\r\nimport { useCopyText } from './useCopyText';\r\n\r\ninterface CodeBlockProps {\r\n language: string;\r\n content: string;\r\n}\r\n\r\nfunction RichCodeBlock({ language, content }: CodeBlockProps) {\r\n const { copied, copy } = useCopyText(content);\r\n\r\n return (\r\n <div className=\"lax-code-block lax-code-block--rich\">\r\n <div className=\"lax-code-block__header\">\r\n <span className=\"lax-code-block__lang\">{language || 'code'}</span>\r\n <button\r\n type=\"button\"\r\n className={`lax-code-block__copy ${copied ? 'lax-code-block__copy--copied' : ''}`}\r\n onClick={() => void copy()}\r\n >\r\n {copied ? 'Copied' : 'Copy'}\r\n </button>\r\n </div>\r\n <SyntaxHighlighter\r\n language={language || 'text'}\r\n style={oneDark}\r\n customStyle={{ margin: 0, padding: '0.75rem 1rem', background: 'transparent' }}\r\n showLineNumbers\r\n wrapLongLines\r\n >\r\n {content}\r\n </SyntaxHighlighter>\r\n </div>\r\n );\r\n}\r\n\r\nfunction heading(children: ReactNode, level: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6', className: string) {\r\n const text = children != null ? String(children) : '';\r\n const id = generateHeadingId(text);\r\n const Tag = level;\r\n return (\r\n <Tag id={id} className={`lax-markdown__heading ${className}`}>\r\n {children}\r\n </Tag>\r\n );\r\n}\r\n\r\nfunction RichMarkdownCode(props: {\r\n inline?: boolean;\r\n className?: string;\r\n children?: ReactNode;\r\n}) {\r\n const { deferDiagrams } = useRichMarkdownStream();\r\n const { inline, className, children, ...rest } = props;\r\n const match = /language-(\\w+)/.exec(className || '');\r\n const codeContent = children != null ? String(children).replace(/\\n$/, '') : '';\r\n\r\n if (!inline && match?.[1] === 'mermaid' && codeContent.trim()) {\r\n if (deferDiagrams) {\r\n return <RichCodeBlock language=\"mermaid\" content={codeContent} />;\r\n }\r\n return <MermaidDiagram chart={codeContent} />;\r\n }\r\n\r\n if (!inline && match?.[1] === 'plantuml' && codeContent.trim()) {\r\n if (deferDiagrams) {\r\n return <RichCodeBlock language=\"plantuml\" content={codeContent} />;\r\n }\r\n return <PlantUMLDiagram content={codeContent} />;\r\n }\r\n\r\n if (!inline && match) {\r\n return <RichCodeBlock language={match[1]!} content={codeContent} />;\r\n }\r\n\r\n return (\r\n <code className=\"lax-markdown__inline-code\" {...rest}>\r\n {children}\r\n </code>\r\n );\r\n}\r\n\r\nexport const RICH_MARKDOWN_COMPONENTS = {\r\n code: RichMarkdownCode,\r\n h1({ children }: { children?: ReactNode }) {\r\n return heading(children, 'h1', 'lax-markdown__h1');\r\n },\r\n h2({ children }: { children?: ReactNode }) {\r\n return heading(children, 'h2', 'lax-markdown__h2');\r\n },\r\n h3({ children }: { children?: ReactNode }) {\r\n return heading(children, 'h3', 'lax-markdown__h3');\r\n },\r\n h4({ children }: { children?: ReactNode }) {\r\n return heading(children, 'h4', 'lax-markdown__h4');\r\n },\r\n h5({ children }: { children?: ReactNode }) {\r\n return heading(children, 'h5', 'lax-markdown__h5');\r\n },\r\n h6({ children }: { children?: ReactNode }) {\r\n return heading(children, 'h6', 'lax-markdown__h6');\r\n },\r\n p({ children }: { children?: ReactNode }) {\r\n if (!paragraphHasContent(children)) return null;\r\n return <p className=\"lax-markdown__paragraph\">{children}</p>;\r\n },\r\n ul({ children }: { children?: ReactNode }) {\r\n return <ul className=\"lax-markdown__list lax-markdown__ul\">{children}</ul>;\r\n },\r\n ol({ children }: { children?: ReactNode }) {\r\n return <ol className=\"lax-markdown__list lax-markdown__ol\">{children}</ol>;\r\n },\r\n li({ children }: { children?: ReactNode }) {\r\n return <li className=\"lax-markdown__li\">{children}</li>;\r\n },\r\n a({ children, href }: { children?: ReactNode; href?: string }) {\r\n return (\r\n <a href={href} className=\"lax-markdown__link\" target=\"_blank\" rel=\"noopener noreferrer\">\r\n {children}\r\n </a>\r\n );\r\n },\r\n blockquote({ children }: { children?: ReactNode }) {\r\n return <blockquote className=\"lax-markdown__blockquote\">{children}</blockquote>;\r\n },\r\n table({ children }: { children?: ReactNode }) {\r\n return (\r\n <div className=\"lax-markdown__table-wrapper\">\r\n <table className=\"lax-markdown__table\">{children}</table>\r\n </div>\r\n );\r\n },\r\n thead({ children }: { children?: ReactNode }) {\r\n return <thead className=\"lax-markdown__thead\">{children}</thead>;\r\n },\r\n tbody({ children }: { children?: ReactNode }) {\r\n return <tbody className=\"lax-markdown__tbody\">{children}</tbody>;\r\n },\r\n tr({ children }: { children?: ReactNode }) {\r\n return <tr className=\"lax-markdown__tr\">{children}</tr>;\r\n },\r\n th({ children }: { children?: ReactNode }) {\r\n return <th className=\"lax-markdown__th\">{children}</th>;\r\n },\r\n td({ children }: { children?: ReactNode }) {\r\n return <td className=\"lax-markdown__td\">{children}</td>;\r\n },\r\n hr() {\r\n return <hr className=\"lax-markdown__hr\" />;\r\n },\r\n strong({ children }: { children?: ReactNode }) {\r\n return <strong className=\"lax-markdown__strong\">{children}</strong>;\r\n },\r\n em({ children }: { children?: ReactNode }) {\r\n return <em className=\"lax-markdown__em\">{children}</em>;\r\n },\r\n};\r\n","let headingCounter = 0;\r\n\r\n/** 为 Markdown 标题生成稳定 id(锚点 / TOC 用) */\r\nexport function generateHeadingId(text: string): string {\r\n const slug = text\r\n .trim()\r\n .toLowerCase()\r\n .replace(/[^\\w\\u4e00-\\u9fff]+/g, '-')\r\n .replace(/^-+|-+$/g, '');\r\n\r\n if (slug) return slug;\r\n headingCounter += 1;\r\n return `heading-${headingCounter}`;\r\n}\r\n\r\nexport function resetHeadingIds(): void {\r\n headingCounter = 0;\r\n}\r\n","/**\n * 职责:ReasoningNode — 对齐 CC AssistantTextMessage / CLI assistant_message。\n * 正文前加 BLACK_CIRCLE(●);streaming 时圆点闪烁;正常字色、不折叠。\n */\nimport { useNodeTyped } from '../../core/hooks';\n\n/** 对齐 CC constants/figures.ts BLACK_CIRCLE · CLI assistant_message._BLACK_CIRCLE */\nexport const REASONING_DOT = '●';\n\nexport interface ReasoningBubbleProps {\n nodeId: string;\n}\n\nexport function ReasoningBubble({ nodeId }: ReasoningBubbleProps) {\n const node = useNodeTyped(nodeId, 'reasoning');\n if (!node) return null;\n\n const text = node.accumulated.trim();\n if (!text) return null;\n\n return (\n <div className=\"lax-reasoning-bubble\" data-status={node.status} data-round-id={node.roundId}>\n <div className=\"lax-reasoning-bubble__body\">\n <span className=\"lax-reasoning-bubble__dot\" aria-hidden=\"true\">\n {REASONING_DOT}\n </span>\n <span className=\"lax-reasoning-bubble__content\">{node.accumulated}</span>\n </div>\n </div>\n );\n}\n","/**\n * StreamingMarkdown.tsx — 流式 Rich Markdown(S1:稳定/不稳定后缀均 RichMarkdown)\n *\n * 链路位置:TextNode 正式结果渲染。\n */\nimport { useRef } from 'react';\nimport { marked, type Token } from 'marked';\n\nimport { RichMarkdown } from '../../markdown/RichMarkdown';\nimport { hashContent, hasMarkdownSyntax } from '../../markdown/markdownUtils';\n\nconst TOKEN_CACHE_MAX = 500;\nconst tokenCache = new Map<string, Token[]>();\n\nfunction cachedLexer(content: string): Token[] {\n if (!hasMarkdownSyntax(content)) {\n return [{\n type: 'paragraph',\n raw: content,\n text: content,\n tokens: [{\n type: 'text',\n raw: content,\n text: content,\n }],\n } as Token];\n }\n\n const key = hashContent(content);\n const hit = tokenCache.get(key);\n\n if (hit) {\n tokenCache.delete(key);\n tokenCache.set(key, hit);\n return hit;\n }\n\n const tokens = marked.lexer(content);\n\n if (tokenCache.size >= TOKEN_CACHE_MAX) {\n const first = tokenCache.keys().next().value;\n if (first !== undefined) tokenCache.delete(first);\n }\n\n tokenCache.set(key, tokens);\n return tokens;\n}\n\nexport interface StreamingMarkdownProps {\n children: string;\n}\n\nexport function StreamingMarkdown({ children }: StreamingMarkdownProps) {\n 'use no memo';\n\n const stablePrefixRef = useRef('');\n\n if (!children.startsWith(stablePrefixRef.current)) {\n stablePrefixRef.current = '';\n }\n\n const boundary = stablePrefixRef.current.length;\n const tokens = cachedLexer(children.substring(boundary));\n\n let lastContentIdx = tokens.length - 1;\n while (lastContentIdx >= 0 && tokens[lastContentIdx]!.type === 'space') {\n lastContentIdx--;\n }\n\n let advance = 0;\n for (let i = 0; i < lastContentIdx; i++) {\n advance += tokens[i]!.raw.length;\n }\n\n if (advance > 0) {\n stablePrefixRef.current = children.substring(0, boundary + advance);\n }\n\n const stablePrefix = stablePrefixRef.current;\n const unstableSuffix = children.substring(stablePrefix.length);\n\n return (\n <div className=\"lax-markdown lax-markdown--rich\">\n {stablePrefix ? (\n <RichMarkdown key={`stable-${hashContent(stablePrefix)}`} content={stablePrefix} />\n ) : null}\n {unstableSuffix ? (\n <RichMarkdown\n key={`unstable-${hashContent(unstableSuffix)}`}\n content={unstableSuffix}\n deferDiagrams\n />\n ) : null}\n </div>\n );\n}\n","/**\n * 职责:默认 TextNode 主舞台 widget。\n * 链路位置:NodeRegistry → Timeline 渲染。\n *\n * 渲染策略(对齐 CC):\n * - Streaming 时显示纯文本(避免高频 markdown 解析)\n * - Done 时使用边界跟踪优化的流式 markdown 渲染\n */\nimport { useNodeTyped } from '../../core/hooks';\n\n// 内置流式 markdown 渲染\nimport { StreamingMarkdown } from '../tools/presentation/StreamingMarkdown';\nimport { REASONING_DOT } from './ReasoningNode';\n\nexport interface TextBubbleProps {\n nodeId: string;\n}\n\nexport function TextBubble({ nodeId }: TextBubbleProps) {\n const node = useNodeTyped(nodeId, 'text');\n if (!node) return null;\n\n // 使用流式 markdown 渲染(对齐 CC:流式过程中就渲染 markdown)\n return (\n <div className=\"lax-text-bubble\" data-status={node.status}>\n <div className=\"lax-text-bubble__body\">\n <span className=\"lax-text-bubble__dot\" aria-hidden=\"true\">\n {REASONING_DOT}\n </span>\n <div className=\"lax-text-bubble__content lax-text-bubble__content--markdown\">\n <StreamingMarkdown>\n {node.accumulated}\n </StreamingMarkdown>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * 职责:默认 ToolCallNode 主舞台 widget(V3 Shell + resolveToolBody)。\n * 链路位置:NodeRegistry → Timeline。\n * 当前裁剪范围:T4.6 内嵌 permission 等待态(permissionUiMode 控制)。\n */\nimport { useEffect, useState } from 'react';\n\nimport {\n useSessionViewOptions,\n useToolDisplayOptions,\n} from '../../core/context/SessionContext';\nimport { useNodeTyped, usePendingPermissionForTool } from '../../core/hooks';\nimport { resolveEffectiveToolBodyMode } from '../sessionViewOptions';\nimport { formatToolTitle } from '../tools/formatToolTitle';\nimport { resolveToolBody } from '../tools/resolveToolBody';\nimport { ToolCallShell } from '../tools/ToolCallShell';\nimport type { ToolDisplayProps } from '../tools/types';\n\nexport interface ToolCallCardProps {\n nodeId: string;\n layout?: 'default' | 'grouped';\n}\n\nexport function ToolCallCard({ nodeId, layout = 'default' }: ToolCallCardProps) {\n const node = useNodeTyped(nodeId, 'tool_call');\n const { registry, defaultBodyMode } = useToolDisplayOptions();\n const viewOptions = useSessionViewOptions();\n const pendingPermission = usePendingPermissionForTool(node?.toolName ?? '');\n const effectiveDefault = resolveEffectiveToolBodyMode(viewOptions, defaultBodyMode);\n const [bodyMode, setBodyMode] = useState(effectiveDefault);\n\n useEffect(() => {\n setBodyMode(resolveEffectiveToolBodyMode(viewOptions, defaultBodyMode));\n }, [viewOptions.displayMode, viewOptions.verbose, defaultBodyMode]);\n\n if (!node) return null;\n\n // 内部工具(Task* 等)不在 Timeline 显示(对齐 CC renderToolUseMessage 返回 null)\n if (node.hidden) return null;\n\n const details = node.details;\n const inputStream = details?.inputStream ?? node.inputDelta;\n const result = node.result;\n const displayBody = result?.display ?? null;\n const hasSubagentProgress = (node.subagentProgress?.length ?? 0) > 0;\n const hasSubagentTranscript = (node.subagentTranscript?.length ?? 0) > 0;\n const showBody =\n hasSubagentProgress || hasSubagentTranscript || !(node.status === 'running' && result == null);\n\n const BodyComponent = resolveToolBody(node.toolName, displayBody, registry);\n const title = formatToolTitle(\n node.toolName,\n details?.input ?? node.input,\n displayBody,\n result?.summary,\n result?.meta,\n );\n\n const bodyProps: ToolDisplayProps = {\n nodeId,\n toolName: node.toolName,\n status: node.status,\n input: details?.input ?? node.input,\n inputStream,\n result,\n progress: node.progress ?? undefined,\n subagentProgress: node.subagentProgress,\n subagentTranscript: node.subagentTranscript,\n subagentSessions: node.subagentSessions,\n bodyMode,\n onBodyModeChange: setBodyMode,\n };\n\n const errorMessage = result?.error?.message ?? null;\n const permissionWait =\n viewOptions.permissionUiMode !== 'standalone' && node.status === 'running'\n ? pendingPermission\n : undefined;\n\n return (\n <ToolCallShell\n status={node.status}\n title={title}\n progress={node.progress ?? undefined}\n errorMessage={errorMessage}\n layout={layout}\n permissionWait={permissionWait}\n permissionUiMode={viewOptions.permissionUiMode}\n >\n {showBody ? (\n <div className=\"lax-tool-shell__body\">\n <BodyComponent {...bodyProps} />\n </div>\n ) : null}\n\n </ToolCallShell>\n );\n}\n","/**\r\n * 职责:默认 StepNode 折叠详情 widget。\r\n * 链路位置:NodeRegistry;MVP 折叠展示。\r\n * 当前裁剪范围:简单 label/status;不含复杂编排 UI。\r\n */\r\nimport { useNodeTyped } from '../../core/hooks';\r\n\r\nexport interface StepCardProps {\r\n nodeId: string;\r\n}\r\n\r\nexport function StepCard({ nodeId }: StepCardProps) {\r\n const node = useNodeTyped(nodeId, 'step');\r\n if (!node) return null;\r\n return (\r\n <details className=\"lax-step-card\" data-status={node.status}>\r\n <summary className=\"lax-step-card__summary\">{node.label}</summary>\r\n </details>\r\n );\r\n}\r\n","/**\r\n * 职责:默认 ErrorNode 主舞台 widget。\r\n * 链路位置:NodeRegistry → Timeline 渲染。\r\n * 当前裁剪范围:展示 message/type;不打断流。\r\n */\r\nimport { useNodeTyped } from '../../core/hooks';\r\n\r\nexport interface ErrorCardProps {\r\n nodeId: string;\r\n}\r\n\r\nexport function ErrorCard({ nodeId }: ErrorCardProps) {\r\n const node = useNodeTyped(nodeId, 'error');\r\n if (!node) return null;\r\n return (\r\n <div className=\"lax-error-card\" role=\"alert\">\r\n <div className=\"lax-error-card__message\">{node.message}</div>\r\n {node.errorType ? (\r\n <div className=\"lax-error-card__type\">{node.errorType}</div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * 职责:未知 event_type 兜底 widget。\r\n * 链路位置:NodeRegistry → Timeline 渲染。\r\n * 当前裁剪范围:展示 eventType 与原始 data JSON。\r\n */\r\nimport { useNodeTyped } from '../../core/hooks';\r\n\r\nexport interface UnknownCardProps {\r\n nodeId: string;\r\n}\r\n\r\nexport function UnknownCard({ nodeId }: UnknownCardProps) {\r\n const node = useNodeTyped(nodeId, 'unknown');\r\n if (!node) return null;\r\n return (\r\n <div className=\"lax-unknown-card\">\r\n <div className=\"lax-unknown-card__type\">Unknown: {node.eventType}</div>\r\n <pre className=\"lax-unknown-card__data\">\r\n {JSON.stringify(node.rawData, null, 2)}\r\n </pre>\r\n </div>\r\n );\r\n}\r\n","/**\r\n * 职责:默认 PermissionNode 主舞台 widget(V2-D)。\r\n * 链路位置:NodeRegistry → Timeline;Allow/Deny 经 InteractionBus 回写业务 HTTP。\r\n * 当前裁剪范围:pending 态按钮;不含 suggestions 列表与 HITL 表单。\r\n */\r\nimport { useState } from 'react';\r\n\r\nimport { useInteractionBus } from '../../core/context/InteractionContext';\r\nimport { useNodeTyped } from '../../core/hooks';\r\n\r\nexport interface PermissionCardProps {\r\n nodeId: string;\r\n}\r\n\r\nexport function PermissionCard({ nodeId }: PermissionCardProps) {\r\n const node = useNodeTyped(nodeId, 'permission');\r\n const bus = useInteractionBus();\r\n const [resolvedLocally, setResolvedLocally] = useState(false);\r\n\r\n if (!node) return null;\r\n\r\n const pending = node.status === 'pending' && !resolvedLocally;\r\n\r\n const onAllow = () => {\r\n void bus.resolvePermission({ requestId: node.requestId, allow: true });\r\n setResolvedLocally(true);\r\n };\r\n\r\n const onDeny = () => {\r\n void bus.resolvePermission({ requestId: node.requestId, allow: false });\r\n setResolvedLocally(true);\r\n };\r\n\r\n return (\r\n <div\r\n className=\"lax-permission-card\"\r\n data-status={pending ? 'pending' : 'resolved'}\r\n data-request-id={node.requestId}\r\n >\r\n <div className=\"lax-permission-card__header\">\r\n <span className=\"lax-permission-card__label\">Permission</span>\r\n <span className=\"lax-permission-card__tool\">{node.toolName}</span>\r\n </div>\r\n <div className=\"lax-permission-card__message\">{node.message}</div>\r\n {node.askPrompt && node.askPrompt !== node.message ? (\r\n <div className=\"lax-permission-card__prompt\">{node.askPrompt}</div>\r\n ) : null}\r\n {pending ? (\r\n <div className=\"lax-permission-card__actions\">\r\n <button type=\"button\" className=\"lax-permission-card__allow\" onClick={onAllow}>\r\n Allow\r\n </button>\r\n <button type=\"button\" className=\"lax-permission-card__deny\" onClick={onDeny}>\r\n Deny\r\n </button>\r\n </div>\r\n ) : (\r\n <div className=\"lax-permission-card__resolved\">Resolved</div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","/**\n * 职责:MEMORY_SAVED 摘要节点 widget — \"Saved N memories\" 一行折叠展示。\n *\n * 链路位置:\n * NodeRegistry → TimelineItem → 主舞台。\n *\n * 当前裁剪范围:\n * 默认折叠态;writtenPaths 非空时可展开列出路径。\n * 不解析路径语义(绝对 / 相对 / index 文件),由后端 SDK 契约保证。\n *\n * CLI 对照:\n * langchain_agentx_cli/screens/repl.py MemorySavedSummary 一行渲染。\n */\nimport { useNodeTyped } from '../../core/hooks';\n\nexport interface MemorySavedRowProps {\n nodeId: string;\n}\n\nexport function MemorySavedRow({ nodeId }: MemorySavedRowProps) {\n const node = useNodeTyped(nodeId, 'memory_saved');\n if (!node) return null;\n const hasPaths = node.writtenPaths.length > 0;\n return (\n <details\n className=\"lax-memory-saved\"\n data-testid=\"lax-memory-saved\"\n data-node-id={nodeId}\n >\n <summary className=\"lax-memory-saved__summary\">\n <span className=\"lax-memory-saved__icon\" aria-hidden=\"true\">\n 💾\n </span>\n <span className=\"lax-memory-saved__hint\">{node.displayHint}</span>\n </summary>\n {hasPaths ? (\n <ul className=\"lax-memory-saved__paths\">\n {node.writtenPaths.map((p) => (\n <li key={p} className=\"lax-memory-saved__path\">\n <code>{p}</code>\n </li>\n ))}\n </ul>\n ) : null}\n </details>\n );\n}\n","/**\n * 职责:kind → React widget 映射,支持 override/register 扩展。\n * 链路位置:Timeline 按节点 kind 查找 widget;业务通过 override 替换。\n * 当前裁剪范围:8 类内置 kind + 自定义 register;无插件系统。\n */\nimport type { ComponentType } from 'react';\n\nimport type { SessionNodeKind } from '../types/nodes';\nimport { TextBubble } from './nodes/TextNode';\nimport { ReasoningBubble } from './nodes/ReasoningNode';\nimport { ToolCallCard } from './nodes/ToolCallNode';\nimport { StepCard } from './nodes/StepNode';\nimport { ErrorCard } from './nodes/ErrorNode';\nimport { UnknownCard } from './nodes/UnknownNode';\nimport { PermissionCard } from './nodes/PermissionNode';\nimport { MemorySavedRow } from './nodes/MemorySavedNode';\n\nconst DEFAULT_WIDGETS = new Map<string, NodeWidget>([\n ['text', TextBubble],\n ['reasoning', ReasoningBubble],\n ['tool_call', ToolCallCard],\n ['step', StepCard],\n ['error', ErrorCard],\n ['unknown', UnknownCard],\n ['permission', PermissionCard],\n ['memory_saved', MemorySavedRow],\n]);\n\nexport interface NodeWidgetProps {\n nodeId: string;\n}\n\nexport type NodeWidget = ComponentType<NodeWidgetProps>;\n\nexport class NodeRegistry {\n private readonly widgets: Map<string, NodeWidget>;\n\n constructor(widgets: Map<string, NodeWidget>) {\n this.widgets = widgets;\n }\n\n static default(): NodeRegistry {\n return new NodeRegistry(new Map(DEFAULT_WIDGETS));\n }\n\n override(kind: SessionNodeKind | string, widget: NodeWidget): NodeRegistry {\n const next = new Map(this.widgets);\n next.set(kind, widget);\n return new NodeRegistry(next);\n }\n\n register(kind: string, widget: NodeWidget): NodeRegistry {\n return this.override(kind, widget);\n }\n\n get(kind: string): NodeWidget | undefined {\n return this.widgets.get(kind);\n }\n\n has(kind: string): boolean {\n return this.widgets.has(kind);\n }\n}\n","/**\r\n * 职责:默认 registry 工厂别名,供 AgentSession 内部使用。\r\n * 链路位置:AgentSession 未传 registry 时的 fallback。\r\n * 当前裁剪范围:委托 NodeRegistry.default()。\r\n */\r\nimport { NodeRegistry } from './NodeRegistry';\r\n\r\nexport function createDefaultRegistry(): NodeRegistry {\r\n return NodeRegistry.default();\r\n}\r\n","/**\r\n * 职责:多会话顶层 store,按 sessionId 路由事件到独立 SessionTree。\r\n * 链路位置:MultiAgentSession 消费;业务也可直接 createMultiSessionStore。\r\n * 当前裁剪范围:进程内 LRU(默认 10);不含 Source 生命周期管理。\r\n */\r\nimport { createStore, type StoreApi } from 'zustand/vanilla';\r\n\r\nimport type { LangchainAgentEvent, TierOverrides } from '../types/events';\r\nimport { createEmptyTree, type ReducerError, type SessionTree } from '../types/tree';\r\nimport { replayEvents } from './replay';\r\nimport { reduceTree, type ReduceOptions } from './reducer';\r\nimport { markEventIdSeen, shouldSkipDuplicateEvent } from './dedupe';\r\nimport type { SessionStoreState } from './store';\r\nimport type { SourceEventContext } from '../transport/types';\r\n\r\nexport interface SessionSlice {\r\n tree: SessionTree;\r\n eventCount: number;\r\n}\r\n\r\nexport interface MultiSessionStoreOptions {\r\n maxSessions?: number;\r\n tierOverrides?: TierOverrides;\r\n debug?: boolean;\r\n /** 初始活跃 session;默认 null */\r\n activeSessionId?: string | null;\r\n}\r\n\r\nexport interface MultiSessionStoreState {\r\n sessions: Record<string, SessionSlice>;\r\n activeSessionId: string | null;\r\n order: string[];\r\n applyEvent: (sessionId: string, event: LangchainAgentEvent, ctx?: SourceEventContext) => void;\r\n applyEvents: (sessionId: string, events: LangchainAgentEvent[]) => void;\r\n setActiveSessionId: (id: string | null) => void;\r\n removeSession: (id: string) => void;\r\n replaySession: (sessionId: string, events: LangchainAgentEvent[]) => void;\r\n ensureSession: (sessionId: string, initialEvents?: LangchainAgentEvent[]) => void;\r\n getSessionTree: (sessionId: string) => SessionTree | undefined;\r\n}\r\n\r\nconst DEFAULT_MAX_SESSIONS = 10;\r\n\r\nfunction touchOrder(order: string[], sessionId: string): string[] {\r\n return [...order.filter((id) => id !== sessionId), sessionId];\r\n}\r\n\r\nfunction safeReduce(\r\n tree: SessionTree,\r\n event: LangchainAgentEvent,\r\n eventIndex: number,\r\n options?: ReduceOptions,\r\n): SessionTree {\r\n try {\r\n return reduceTree(tree, event, eventIndex, options);\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : String(err);\r\n const stack = err instanceof Error ? err.stack : undefined;\r\n if (import.meta.env?.DEV) {\r\n console.error('[langchain_agentx_stream_ui] reducer error:', err);\r\n }\r\n const reducerError: ReducerError = {\r\n eventIndex,\r\n eventType: event.event_type,\r\n message,\r\n stack,\r\n };\r\n return {\r\n ...tree,\r\n internalErrors: [...tree.internalErrors, reducerError],\r\n };\r\n }\r\n}\r\n\r\nfunction evictSessions(\r\n sessions: Record<string, SessionSlice>,\r\n order: string[],\r\n maxSessions: number,\r\n activeSessionId: string | null,\r\n): { sessions: Record<string, SessionSlice>; order: string[] } {\r\n let nextSessions = { ...sessions };\r\n let nextOrder = [...order];\r\n while (nextOrder.length > maxSessions) {\r\n const candidate = nextOrder.find((id) => id !== activeSessionId) ?? nextOrder[0];\r\n if (!candidate) break;\r\n const { [candidate]: _removed, ...rest } = nextSessions;\r\n nextSessions = rest;\r\n nextOrder = nextOrder.filter((id) => id !== candidate);\r\n }\r\n return { sessions: nextSessions, order: nextOrder };\r\n}\r\n\r\nexport function createMultiSessionStore(\r\n options?: MultiSessionStoreOptions,\r\n): StoreApi<MultiSessionStoreState> {\r\n const maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;\r\n const reduceOpts: ReduceOptions = {\r\n tierOverrides: options?.tierOverrides,\r\n collectDebug: options?.debug === true,\r\n };\r\n const replayOpts = {\r\n tierOverrides: options?.tierOverrides,\r\n collectDebug: options?.debug === true,\r\n };\r\n const seenBySession = new Map<string, Set<string>>();\r\n\r\n function getSeenSet(sessionId: string): Set<string> {\r\n let set = seenBySession.get(sessionId);\r\n if (!set) {\r\n set = new Set<string>();\r\n seenBySession.set(sessionId, set);\r\n }\r\n return set;\r\n }\r\n\r\n return createStore<MultiSessionStoreState>((set, get) => ({\r\n sessions: {},\r\n activeSessionId: options?.activeSessionId ?? null,\r\n order: [],\r\n\r\n getSessionTree(sessionId) {\r\n return get().sessions[sessionId]?.tree;\r\n },\r\n\r\n ensureSession(sessionId, initialEvents) {\r\n const state = get();\r\n if (state.sessions[sessionId]) return;\r\n\r\n const tree =\r\n initialEvents && initialEvents.length > 0\r\n ? replayEvents(initialEvents, replayOpts)\r\n : createEmptyTree();\r\n const slice: SessionSlice = {\r\n tree,\r\n eventCount: initialEvents?.length ?? 0,\r\n };\r\n let order = touchOrder(state.order, sessionId);\r\n let sessions = { ...state.sessions, [sessionId]: slice };\r\n ({ sessions, order } = evictSessions(sessions, order, maxSessions, state.activeSessionId));\r\n\r\n set({\r\n sessions,\r\n order,\r\n activeSessionId: state.activeSessionId ?? sessionId,\r\n });\r\n },\r\n\r\n applyEvent(sessionId, event, ctx) {\r\n const sseEventId = ctx?.sseEventId;\r\n const seen = getSeenSet(sessionId);\r\n if (shouldSkipDuplicateEvent(seen, sseEventId)) return;\r\n\r\n const state = get();\r\n let slice = state.sessions[sessionId];\r\n if (!slice) {\r\n get().ensureSession(sessionId);\r\n slice = get().sessions[sessionId]!;\r\n }\r\n const reduced = safeReduce(slice.tree, event, slice.eventCount, reduceOpts);\r\n const nextTree: SessionTree =\r\n sseEventId\r\n ? { ...reduced, meta: { ...reduced.meta, lastEventId: sseEventId } }\r\n : reduced;\r\n const nextSlice: SessionSlice = {\r\n tree: nextTree,\r\n eventCount: slice.eventCount + 1,\r\n };\r\n markEventIdSeen(seen, sseEventId);\r\n let sessions = { ...state.sessions, [sessionId]: nextSlice };\r\n let order = touchOrder(state.order, sessionId);\r\n ({ sessions, order } = evictSessions(sessions, order, maxSessions, state.activeSessionId));\r\n set({ sessions, order });\r\n },\r\n\r\n applyEvents(sessionId, events) {\r\n for (const event of events) {\r\n get().applyEvent(sessionId, event);\r\n }\r\n },\r\n\r\n setActiveSessionId(id) {\r\n set({ activeSessionId: id });\r\n },\r\n\r\n removeSession(sessionId) {\r\n const state = get();\r\n if (!state.sessions[sessionId]) return;\r\n seenBySession.delete(sessionId);\r\n const { [sessionId]: _removed, ...sessions } = state.sessions;\r\n const order = state.order.filter((id) => id !== sessionId);\r\n const activeSessionId =\r\n state.activeSessionId === sessionId\r\n ? (order[order.length - 1] ?? null)\r\n : state.activeSessionId;\r\n set({ sessions, order, activeSessionId });\r\n },\r\n\r\n replaySession(sessionId, events) {\r\n const tree = replayEvents(events, replayOpts);\r\n const slice: SessionSlice = { tree, eventCount: events.length };\r\n const state = get();\r\n let order = touchOrder(state.order, sessionId);\r\n let sessions = { ...state.sessions, [sessionId]: slice };\r\n ({ sessions, order } = evictSessions(sessions, order, maxSessions, state.activeSessionId));\r\n set({ sessions, order });\r\n },\r\n }));\r\n}\r\n\r\nexport type MultiSessionStore = StoreApi<MultiSessionStoreState>;\r\n\r\n/** 将 MultiSessionStore 活跃会话投影为 SessionStore,供 Timeline hooks 复用。 */\r\nexport function createActiveSessionBridge(multiStore: MultiSessionStore): StoreApi<SessionStoreState> {\r\n type BridgeState = Pick<SessionStoreState, 'tree' | 'eventCount' | 'applyEvent' | 'applyEvents' | 'reset'>;\r\n\r\n const bridge = createStore<BridgeState>(() => ({\r\n tree: createEmptyTree(),\r\n eventCount: 0,\r\n applyEvent(event, ctx) {\r\n const id = multiStore.getState().activeSessionId;\r\n if (id) multiStore.getState().applyEvent(id, event, ctx);\r\n },\r\n applyEvents(events) {\r\n const id = multiStore.getState().activeSessionId;\r\n if (id) multiStore.getState().applyEvents(id, events);\r\n },\r\n reset() {\r\n const id = multiStore.getState().activeSessionId;\r\n if (id) multiStore.getState().replaySession(id, []);\r\n },\r\n }));\r\n\r\n const sync = (): void => {\r\n const { activeSessionId, sessions } = multiStore.getState();\r\n const slice = activeSessionId ? sessions[activeSessionId] : undefined;\r\n bridge.setState({\r\n tree: slice?.tree ?? createEmptyTree(),\r\n eventCount: slice?.eventCount ?? 0,\r\n });\r\n };\r\n\r\n multiStore.subscribe(sync);\r\n sync();\r\n return bridge as StoreApi<SessionStoreState>;\r\n}\r\n","/**\r\n * 职责:SSE 事件 id 幂等去重(M4 续传重叠帧)。\r\n * 链路位置:SessionStore / MultiSessionStore applyEvent 前置检查。\r\n * 当前裁剪范围:按 sseEventId 字符串去重;无 id 时始终应用。\r\n */\r\n\r\nexport function shouldSkipDuplicateEvent(\r\n seenEventIds: ReadonlySet<string>,\r\n sseEventId: string | undefined,\r\n): boolean {\r\n if (!sseEventId) return false;\r\n return seenEventIds.has(sseEventId);\r\n}\r\n\r\nexport function markEventIdSeen(\r\n seenEventIds: Set<string>,\r\n sseEventId: string | undefined,\r\n): void {\r\n if (sseEventId) seenEventIds.add(sseEventId);\r\n}\r\n","/**\n * 职责:多会话顶层容器,每 session 独立 Source + initialEvents,共享 MultiSessionStore。\n * 链路位置:业务多 Tab / 双路 SSE;Timeline 只渲染 activeSessionId 对应树。\n * 当前裁剪范围:薄封装;Source 生命周期由本组件管理;LRU 默认 10。\n */\nimport { useEffect, useMemo, useRef, type ReactNode } from 'react';\n\nimport {\n createMultiSessionStore,\n createActiveSessionBridge,\n type MultiSessionStore,\n} from '../core/sessionStore';\nimport {\n MultiSessionStoreContext,\n SessionStoreContext,\n NodeRegistryContext,\n ToolDisplayOptionsContext,\n SessionViewOptionsContext,\n} from '../core/context/SessionContext';\nimport type { Source } from '../transport/types';\nimport type { LangchainAgentEvent, TierOverrides } from '../types/events';\nimport type { ReducerError } from '../types/tree';\nimport { createDefaultRegistry } from './defaultRegistry';\nimport type { NodeRegistry } from './NodeRegistry';\nimport { SessionTimeline } from './SessionTimeline';\nimport { InteractionBusContext } from '../core/context/InteractionContext';\nimport type { InteractionBus } from '../core/interaction/InteractionBus';\nimport { getNoopInteractionBus } from '../core/interaction/InteractionBus';\nimport { useInternalErrors, useSessionStatus } from '../core/hooks';\nimport {\n createDefaultToolRegistry,\n type ToolDisplayRegistry,\n} from './tools/registry';\nimport type { ToolBodyMode } from './tools/types';\nimport type { MarkdownRenderer } from '../core/context/MarkdownRendererContext';\nimport { MarkdownRendererContext } from '../core/context/MarkdownRendererContext';\nimport type { PermissionUiMode } from './sessionViewOptions';\nimport { DEFAULT_SESSION_VIEW_OPTIONS } from './sessionViewOptions';\n\nexport interface MultiSessionSourceConfig {\n sessionId: string;\n source: Source;\n /** EventBuffer ingest 快照或历史事件;挂载时 replay 后再接 source 续流(M3) */\n initialEvents?: LangchainAgentEvent[];\n}\n\nexport interface MultiAgentSessionProps {\n sessions: MultiSessionSourceConfig[];\n /** 受控活跃 session */\n activeSessionId?: string | null;\n /** 非受控默认活跃 session */\n defaultActiveSessionId?: string | null;\n onActiveSessionChange?: (sessionId: string | null) => void;\n maxSessions?: number;\n tierOverrides?: TierOverrides;\n debug?: boolean;\n registry?: NodeRegistry;\n onError?: (error: Error, sessionId: string) => void;\n virtualized?: boolean;\n virtualizeThreshold?: number;\n interactionBus?: InteractionBus;\n toolDisplayRegistry?: ToolDisplayRegistry;\n defaultBodyMode?: ToolBodyMode;\n groupParallelTools?: boolean;\n permissionUiMode?: PermissionUiMode;\n markdownRenderer?: MarkdownRenderer;\n children?: ReactNode;\n}\n\nfunction DebugPanel() {\n const status = useSessionStatus();\n const errors = useInternalErrors();\n if (errors.length === 0) return null;\n return (\n <div className=\"lax-debug-panel\" data-testid=\"lax-debug-panel\">\n <div>status: {status}</div>\n <ul>\n {errors.map((err: ReducerError, i: number) => (\n <li key={`${err.eventIndex}-${i}`}>\n [{err.eventType}] {err.message}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n\nexport function MultiAgentSession({\n sessions,\n activeSessionId: controlledActiveId,\n defaultActiveSessionId,\n onActiveSessionChange,\n maxSessions,\n tierOverrides,\n debug = false,\n registry,\n onError,\n virtualized = false,\n virtualizeThreshold,\n interactionBus,\n toolDisplayRegistry,\n defaultBodyMode = 'preview',\n groupParallelTools = false,\n permissionUiMode = 'standalone',\n markdownRenderer,\n children,\n}: MultiAgentSessionProps) {\n const multiStoreRef = useRef<MultiSessionStore | null>(null);\n const bridgeRef = useRef<ReturnType<typeof createActiveSessionBridge> | null>(null);\n\n if (multiStoreRef.current === null) {\n const defaultId =\n defaultActiveSessionId ??\n controlledActiveId ??\n sessions[0]?.sessionId ??\n null;\n multiStoreRef.current = createMultiSessionStore({\n maxSessions,\n tierOverrides,\n debug,\n activeSessionId: defaultId,\n });\n bridgeRef.current = createActiveSessionBridge(multiStoreRef.current);\n for (const cfg of sessions) {\n multiStoreRef.current.getState().ensureSession(cfg.sessionId, cfg.initialEvents);\n }\n }\n\n const registryRef = useMemo(() => registry ?? createDefaultRegistry(), [registry]);\n const busRef = useMemo(\n () => interactionBus ?? getNoopInteractionBus(),\n [interactionBus],\n );\n const toolDisplayRef = useMemo(\n () => ({\n registry: toolDisplayRegistry ?? createDefaultToolRegistry(),\n defaultBodyMode,\n }),\n [toolDisplayRegistry, defaultBodyMode],\n );\n const sessionViewRef = useMemo(\n () => ({\n ...DEFAULT_SESSION_VIEW_OPTIONS,\n groupParallelTools,\n permissionUiMode,\n verboseReasoning: debug,\n }),\n [groupParallelTools, permissionUiMode, debug],\n );\n\n useEffect(() => {\n if (controlledActiveId === undefined) return;\n multiStoreRef.current!.getState().setActiveSessionId(controlledActiveId);\n }, [controlledActiveId]);\n\n useEffect(() => {\n if (!onActiveSessionChange) return;\n return multiStoreRef.current!.subscribe((state) => {\n onActiveSessionChange(state.activeSessionId);\n });\n }, [onActiveSessionChange]);\n\n useEffect(() => {\n const multiStore = multiStoreRef.current!;\n const controllers = sessions.map((cfg) => {\n const controller = new AbortController();\n multiStore.getState().ensureSession(cfg.sessionId, cfg.initialEvents);\n void cfg.source.start((event, ctx) => {\n multiStore.getState().applyEvent(cfg.sessionId, event, ctx);\n }, controller.signal).catch((err: unknown) => {\n const error = err instanceof Error ? err : new Error(String(err));\n onError?.(error, cfg.sessionId);\n });\n return controller;\n });\n return () => {\n for (const c of controllers) c.abort();\n };\n }, [sessions, onError]);\n\n return (\n <MultiSessionStoreContext.Provider value={multiStoreRef.current!}>\n <SessionStoreContext.Provider value={bridgeRef.current!}>\n <InteractionBusContext.Provider value={busRef}>\n <NodeRegistryContext.Provider value={registryRef}>\n <MarkdownRendererContext.Provider value={markdownRenderer}>\n <ToolDisplayOptionsContext.Provider value={toolDisplayRef}>\n <SessionViewOptionsContext.Provider value={sessionViewRef}>\n <div className=\"lax-agent-session lax-multi-agent-session\" data-testid=\"lax-multi-agent-session\">\n {children ?? (\n <SessionTimeline\n virtualized={virtualized}\n virtualizeThreshold={virtualizeThreshold}\n groupParallelTools={groupParallelTools}\n />\n )}\n {debug ? <DebugPanel /> : null}\n </div>\n </SessionViewOptionsContext.Provider>\n </ToolDisplayOptionsContext.Provider>\n </MarkdownRendererContext.Provider>\n </NodeRegistryContext.Provider>\n </InteractionBusContext.Provider>\n </SessionStoreContext.Provider>\n </MultiSessionStoreContext.Provider>\n );\n}\n"],"mappings":"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","names":["useState","jsx","jsxs","useRef","jsx","jsxs","useState","useEffect","useRef","useState","useEffect","useState","useState","useEffect","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","useEffect","useState","jsx","jsxs","useState","useRef","useEffect","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","SyntaxHighlighter","oneDark","jsx","jsxs","SyntaxHighlighter","oneDark","jsx","jsx","jsxs","useRef","jsx","jsxs","useRef","jsx","jsxs","useEffect","useState","jsx","useState","useEffect","jsx","jsx","jsxs","jsx","jsxs","useState","jsx","jsxs","useState","jsx","jsxs","useEffect","useMemo","useRef","jsx","jsxs","useRef","useMemo","useEffect"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/view/tools/presentation/paths.ts","../src/view/tools/presentation/searchHelpers.ts","../src/view/tools/presentation/TruncatedContent.tsx","../src/view/tools/presentation/bashHelpers.ts","../src/view/tools/presentation/BodyBlockList.tsx","../src/view/tools/presentation/diffHelpers.ts","../src/view/tools/presentation/DiffView.tsx","../src/view/tools/presentation/MarkdownBlock.tsx","../src/core/context/MarkdownRendererContext.tsx"],"sourcesContent":["/**\r\n * paths.ts — 路径展示 helper\r\n *\r\n * 职责:\r\n * 将绝对路径转为较短展示字符串(Web 无 cwd 时仅 normalize 分隔符)。\r\n *\r\n * 链路位置:\r\n * T1+ Read/Edit Widget title。\r\n *\r\n * 当前裁剪范围:\r\n * 不做 relpath(浏览器无 process.cwd);仅 slash 归一化。\r\n *\r\n * 对齐参考:\r\n * CLI widgets/tools/helpers.py display_path\r\n */\r\n\r\nexport function displayPath(filePath: string): string {\r\n if (!filePath) return '';\r\n return filePath.replace(/\\\\/g, '/');\r\n}\r\n","/**\r\n * searchHelpers.ts — grep/glob 标题与列表正文 helper\r\n *\r\n * 对齐参考:CLI widgets/tools/helpers.py format_pattern_title、format_search_result_body\r\n */\r\n\r\nimport { displayPath } from './paths';\r\n\r\nexport const SEARCH_LIST_PREVIEW_LINES = 20;\r\n\r\nconst FOUND_SUMMARY_RE = /^(Found .+|No files found|No matches found)/i;\r\n\r\nexport function formatPatternTitle(pattern: string, path?: string | null): string {\r\n const parts = [`pattern: \"${pattern}\"`];\r\n if (path) {\r\n parts.push(`path: \"${displayPath(path)}\"`);\r\n }\r\n return parts.join(', ');\r\n}\r\n\r\nexport function extractSearchSummary(output: string): string {\r\n const text = output.trim();\r\n if (!text) return '';\r\n const match = text.match(FOUND_SUMMARY_RE);\r\n if (match) return match[1].trim();\r\n const first = text.split('\\n', 1)[0]?.trim() ?? '';\r\n if (/^(found |no files|no matches)/i.test(first)) return first;\r\n return '';\r\n}\r\n\r\nexport function truncateLines(\r\n text: string,\r\n maxLines: number,\r\n): { text: string; truncated: boolean } {\r\n const lines = text.split('\\n');\r\n if (lines.length <= maxLines) {\r\n return { text, truncated: false };\r\n }\r\n return {\r\n text: lines.slice(0, maxLines).join('\\n'),\r\n truncated: true,\r\n };\r\n}\r\n\r\nexport function formatSearchResultBody(\r\n output: string,\r\n maxListLines = SEARCH_LIST_PREVIEW_LINES,\r\n): string {\r\n const text = output.trim();\r\n if (!text) return '(No output)';\r\n\r\n const summary = extractSearchSummary(text);\r\n const lines = text.split('\\n');\r\n let listLines: string[];\r\n\r\n if (summary && lines[0]?.trim() === summary) {\r\n listLines = lines.slice(1);\r\n } else if (summary) {\r\n listLines = lines.filter((ln) => ln.trim() !== summary);\r\n } else {\r\n listLines = lines;\r\n }\r\n\r\n const listText = listLines\r\n .map((ln) => ln.trim())\r\n .filter(Boolean)\r\n .join('\\n');\r\n\r\n if (listText) {\r\n const { text: truncated, truncated: wasTruncated } = truncateLines(\r\n listText,\r\n maxListLines,\r\n );\r\n const suffix = wasTruncated ? `\\n… 列表超过 ${maxListLines} 行,已截断` : '';\r\n if (summary) return `${summary}\\n${truncated}${suffix}`;\r\n return `${truncated}${suffix}`;\r\n }\r\n\r\n return summary || text.slice(0, 500);\r\n}\r\n","/**\n * TruncatedContent.tsx — PREVIEW 行数截断\n *\n * 职责:\n * 默认 3 行预览 + expand 控件;FULL 模式展示全文。\n *\n * 链路位置:\n * DefaultToolBody、T1+ 各 ToolBody 正文。\n *\n * 当前裁剪范围:\n * 纯文本;不做 ANSI / 终端 wrap。\n *\n * 对齐参考:\n * CLI presentation/shell_output.py · CC utils/terminal.ts MAX_LINES_TO_SHOW=3\n */\nimport type { ToolBodyMode } from '../types';\n\nexport const MAX_PREVIEW_LINES = 3;\n\nexport interface TruncatedContentProps {\n text: string;\n mode: ToolBodyMode;\n maxLines?: number;\n onExpand?: () => void;\n}\n\nexport function TruncatedContent({\n text,\n mode,\n maxLines = MAX_PREVIEW_LINES,\n onExpand,\n}: TruncatedContentProps) {\n const lines = text.split('\\n');\n const needsTruncate = mode === 'preview' && lines.length > maxLines;\n\n if (!needsTruncate) {\n return (\n <div className=\"lax-tool-body__block\" data-variant=\"normal\">\n <pre className=\"lax-tool-body__text\">{text}</pre>\n </div>\n );\n }\n\n const preview = lines.slice(0, maxLines).join('\\n');\n const remaining = lines.length - maxLines;\n\n return (\n <div className=\"lax-tool-body__block\" data-variant=\"normal\">\n <pre className=\"lax-tool-body__text\">{preview}</pre>\n <button\n type=\"button\"\n className=\"lax-tool-body__expand\"\n onClick={onExpand}\n >\n +{remaining} lines (点击展开)\n </button>\n </div>\n );\n}\n","/**\r\n * bashHelpers.ts — bash 命令与输出解析\r\n *\r\n * 对齐参考:CLI widgets/tools/helpers.py · bash/widget.py format_body_blocks\r\n */\r\nimport type { ToolBodyMode } from '../types';\r\nimport { MAX_PREVIEW_LINES } from './TruncatedContent';\r\nimport type { BodyBlock } from './BodyBlockList';\r\n\r\nexport const MAX_COMMAND_DISPLAY_CHARS = 160;\r\nexport const MAX_COMMAND_DISPLAY_LINES = 2;\r\n\r\nconst CWD_RESET_PATTERN = /(?:^|\\n)(Shell cwd was reset to .+)$/m;\r\nconst EXIT_CODE_PATTERN = /(?:^|\\n)Exit code:\\s*(\\d+)/m;\r\n\r\nexport function truncateCommand(command: string, maxChars = MAX_COMMAND_DISPLAY_CHARS): string {\r\n let text = command.trim();\r\n if (!text) return '';\r\n const lines = text.split('\\n');\r\n if (lines.length > MAX_COMMAND_DISPLAY_LINES) {\r\n text = lines.slice(0, MAX_COMMAND_DISPLAY_LINES).join('\\n');\r\n }\r\n if (text.length > maxChars) {\r\n text = `${text.slice(0, maxChars)}…`;\r\n }\r\n return text;\r\n}\r\n\r\nexport function formatBashTitle(input: unknown): string {\r\n const inp =\r\n input != null && typeof input === 'object' && !Array.isArray(input)\r\n ? (input as Record<string, unknown>)\r\n : {};\r\n const command = String(inp.command ?? '').trim();\r\n if (!command) return 'Bash';\r\n return `Bash(${truncateCommand(command)})`;\r\n}\r\n\r\nexport function splitBashStreams(output: string): {\r\n stdout: string;\r\n stderr: string;\r\n cwdWarning: string | null;\r\n} {\r\n let text = output ?? '';\r\n let cwdWarning: string | null = null;\r\n const cwdMatch = text.match(CWD_RESET_PATTERN);\r\n if (cwdMatch) {\r\n cwdWarning = cwdMatch[1]?.trim() ?? null;\r\n text = text.replace(CWD_RESET_PATTERN, '').trim();\r\n }\r\n\r\n let stdout = text;\r\n let stderr = '';\r\n if (text.includes('\\n--- stderr ---\\n')) {\r\n const parts = text.split('\\n--- stderr ---\\n');\r\n stdout = parts[0] ?? '';\r\n stderr = parts[1] ?? '';\r\n } else if (text.startsWith('stderr:')) {\r\n stderr = text.slice(7).trim();\r\n stdout = '';\r\n }\r\n\r\n return { stdout: stdout.trim(), stderr: stderr.trim(), cwdWarning };\r\n}\r\n\r\nexport function parseExitCode(output: string, fallback?: number | null): number | null {\r\n const match = (output ?? '').match(EXIT_CODE_PATTERN);\r\n if (match) return Number.parseInt(match[1], 10);\r\n return fallback ?? null;\r\n}\r\n\r\nexport function formatDuration(seconds: number): string {\r\n if (seconds < 1) return `${seconds.toFixed(1)}s`;\r\n if (seconds < 60) return `${Math.floor(seconds)}s`;\r\n if (seconds < 3600) {\r\n const minutes = Math.floor(seconds / 60);\r\n const secs = Math.floor(seconds % 60);\r\n return secs === 0 ? `${minutes}m` : `${minutes}m ${secs}s`;\r\n }\r\n const hours = Math.floor(seconds / 3600);\r\n const minutes = Math.floor((seconds % 3600) / 60);\r\n return minutes === 0 ? `${hours}h` : `${hours}h ${minutes}m`;\r\n}\r\n\r\nexport function formatTimeoutFooter(timeoutMs: number | null | undefined): string | null {\r\n if (!timeoutMs) return null;\r\n return `(timeout ${formatDuration(timeoutMs / 1000)})`;\r\n}\r\n\r\nfunction previewStreamText(text: string, mode: ToolBodyMode): string {\r\n if (mode === 'full' || !text.trim()) return text;\r\n const lines = text.split('\\n');\r\n if (lines.length <= MAX_PREVIEW_LINES) return text;\r\n // 对齐 CLI ShellOutputPreviewer:PREVIEW 只保留前 N 行;expand hint 由 UI 层单独渲染\r\n return lines.slice(0, MAX_PREVIEW_LINES).join('\\n');\r\n}\r\n\r\nfunction resolveStreams(\r\n display: Record<string, unknown> | null,\r\n summary: string,\r\n): { stdout: string; stderr: string; cwdWarning: string | null } {\r\n if (display && ('stdout' in display || 'stderr' in display)) {\r\n return {\r\n stdout: String(display.stdout ?? ''),\r\n stderr: String(display.stderr ?? ''),\r\n cwdWarning: null,\r\n };\r\n }\r\n return splitBashStreams(summary);\r\n}\r\n\r\nfunction resolveExitCode(\r\n display: Record<string, unknown> | null,\r\n summary: string,\r\n): number | null {\r\n if (display && 'exit_code' in display) {\r\n const code = display.exit_code;\r\n if (typeof code === 'number') return code;\r\n if (typeof code === 'string' && code.trim()) {\r\n const n = Number.parseInt(code, 10);\r\n if (Number.isFinite(n)) return n;\r\n }\r\n return null;\r\n }\r\n return parseExitCode(summary);\r\n}\r\n\r\nfunction resolveTimeoutMs(\r\n display: Record<string, unknown> | null,\r\n meta: unknown,\r\n): number | null {\r\n if (display?.timeout_ms != null) {\r\n const n = Number(display.timeout_ms);\r\n return Number.isFinite(n) ? n : null;\r\n }\r\n if (meta != null && typeof meta === 'object' && !Array.isArray(meta)) {\r\n const ms = (meta as Record<string, unknown>).timeout_ms;\r\n if (ms != null) {\r\n const n = Number(ms);\r\n return Number.isFinite(n) ? n : null;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nexport function buildBashBodyBlocks(\r\n display: unknown,\r\n summary: string,\r\n meta: unknown,\r\n mode: ToolBodyMode,\r\n isError: boolean,\r\n): { blocks: BodyBlock[]; truncated: boolean; remainingLines: number } {\r\n const d =\r\n display != null && typeof display === 'object' && !Array.isArray(display)\r\n ? (display as Record<string, unknown>)\r\n : null;\r\n\r\n if (isError) {\r\n const blocks: BodyBlock[] = [\r\n { text: summary.trim() || 'Error', variant: 'error' },\r\n ];\r\n const footer = formatTimeoutFooter(resolveTimeoutMs(d, meta));\r\n if (footer) blocks.push({ text: footer, variant: 'dim' });\r\n return { blocks, truncated: false, remainingLines: 0 };\r\n }\r\n\r\n const { stdout, stderr, cwdWarning } = resolveStreams(d, summary);\r\n const code = resolveExitCode(d, summary);\r\n const blocks: BodyBlock[] = [];\r\n let truncated = false;\r\n let remainingLines = 0;\r\n\r\n const addStream = (text: string, variant: BodyBlock['variant']) => {\r\n if (!text.trim()) return;\r\n const lines = text.split('\\n');\r\n const rendered = previewStreamText(text, mode);\r\n if (mode === 'preview' && lines.length > MAX_PREVIEW_LINES) {\r\n truncated = true;\r\n remainingLines += lines.length - MAX_PREVIEW_LINES;\r\n }\r\n blocks.push({ text: rendered, variant });\r\n };\r\n\r\n addStream(stdout, 'normal');\r\n addStream(stderr, 'error');\r\n\r\n if (cwdWarning) {\r\n blocks.push({ text: cwdWarning, variant: 'dim' });\r\n }\r\n\r\n if (code != null && code !== 0) {\r\n blocks.push({ text: `Exit code: ${code}`, variant: 'error' });\r\n }\r\n\r\n if (blocks.length === 0) {\r\n const noOutputExpected = Boolean(d?.no_output_expected);\r\n blocks.push({\r\n text: noOutputExpected ? 'Done' : '(No output)',\r\n variant: 'dim',\r\n });\r\n }\r\n\r\n const footer = formatTimeoutFooter(resolveTimeoutMs(d, meta));\r\n if (footer) {\r\n blocks.push({ text: footer, variant: 'dim' });\r\n }\r\n\r\n if (d?.truncated && d?.overflow_file) {\r\n blocks.push({\r\n text: `Output truncated; see ${String(d.overflow_file)}`,\r\n variant: 'dim',\r\n });\r\n }\r\n\r\n return { blocks, truncated, remainingLines };\r\n}\r\n","/**\r\n * BodyBlockList.tsx — ⎿ 多块正文布局\r\n *\r\n * 职责:\r\n * 多块平面文本,支持 normal / error / dim 变体。\r\n *\r\n * 链路位置:\r\n * T3 bash stdout/stderr 分块;DefaultToolBody 可复用。\r\n *\r\n * 当前裁剪范围:\r\n * 块内不做 TruncatedContent(由调用方传入已截断文本)。\r\n *\r\n * 对齐参考:\r\n * CLI presentation/message_layout.py · CC MessageResponse.tsx ⎿ 前缀\r\n */\r\n\r\nexport interface BodyBlock {\r\n text: string;\r\n variant?: 'normal' | 'error' | 'dim';\r\n}\r\n\r\nexport interface BodyBlockListProps {\r\n blocks: BodyBlock[];\r\n}\r\n\r\nexport function BodyBlockList({ blocks }: BodyBlockListProps) {\r\n if (blocks.length === 0) return null;\r\n\r\n return (\r\n <div className=\"lax-tool-body__blocks\">\r\n {blocks.map((block, index) => (\r\n <div\r\n key={index}\r\n className=\"lax-tool-body__block\"\r\n data-variant={block.variant ?? 'normal'}\r\n >\r\n <pre className=\"lax-tool-body__text\">{block.text}</pre>\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * diffHelpers.ts — unified diff 生成与解析\r\n *\r\n * 对齐参考:CLI widgets/tools/helpers.py format_diff_from_strings\r\n */\r\n\r\nexport const WRITE_PREVIEW_LINES = 10;\r\nexport const DIFF_PREVIEW_LINES = 12;\r\n\r\nexport type DiffLineKind = 'add' | 'remove' | 'context' | 'meta';\r\n\r\nexport interface ParsedDiffLine {\r\n kind: DiffLineKind;\r\n text: string;\r\n}\r\n\r\nexport function countLines(text: string): number {\r\n if (!text) return 0;\r\n return text.split('\\n').length;\r\n}\r\n\r\nexport function formatDiffFromStrings(oldText: string, newText: string): string {\r\n if (oldText === newText) return '(no changes)';\r\n\r\n const oldLines = oldText.split('\\n');\r\n const newLines = newText.split('\\n');\r\n const body: string[] = [];\r\n let i = 0;\r\n let j = 0;\r\n\r\n while (i < oldLines.length || j < newLines.length) {\r\n const oldLine = oldLines[i];\r\n const newLine = newLines[j];\r\n\r\n if (i < oldLines.length && j < newLines.length && oldLine === newLine) {\r\n body.push(` ${oldLine}`);\r\n i += 1;\r\n j += 1;\r\n continue;\r\n }\r\n\r\n if (i < oldLines.length && (j >= newLines.length || oldLine !== newLine)) {\r\n body.push(`-${oldLine}`);\r\n i += 1;\r\n continue;\r\n }\r\n\r\n if (j < newLines.length) {\r\n body.push(`+${newLine}`);\r\n j += 1;\r\n }\r\n }\r\n\r\n if (body.length === 0) return '(no changes)';\r\n\r\n return ['--- old', '+++ new', '@@', ...body].join('\\n');\r\n}\r\n\r\nexport function parseDiffText(diff: string): ParsedDiffLine[] {\r\n if (diff === '(no changes)') {\r\n return [{ kind: 'meta', text: diff }];\r\n }\r\n\r\n const result: ParsedDiffLine[] = [];\r\n for (const line of diff.split('\\n')) {\r\n if (!line && result.length > 0) {\r\n result.push({ kind: 'context', text: '' });\r\n continue;\r\n }\r\n if (line.startsWith('+++') || line.startsWith('---') || line.startsWith('@@')) {\r\n result.push({ kind: 'meta', text: line });\r\n } else if (line.startsWith('+')) {\r\n result.push({ kind: 'add', text: line.slice(1) });\r\n } else if (line.startsWith('-')) {\r\n result.push({ kind: 'remove', text: line.slice(1) });\r\n } else if (line.startsWith(' ')) {\r\n result.push({ kind: 'context', text: line.slice(1) });\r\n } else {\r\n result.push({ kind: 'context', text: line });\r\n }\r\n }\r\n return result;\r\n}\r\n\r\nexport function resolveEditDiffText(\r\n display: unknown,\r\n input: unknown,\r\n summary: string,\r\n): string {\r\n const d =\r\n display != null && typeof display === 'object' && !Array.isArray(display)\r\n ? (display as Record<string, unknown>)\r\n : null;\r\n const inp =\r\n input != null && typeof input === 'object' && !Array.isArray(input)\r\n ? (input as Record<string, unknown>)\r\n : {};\r\n\r\n const diffField = d?.diff;\r\n if (typeof diffField === 'string' && diffField.trim()) {\r\n return diffField.trim();\r\n }\r\n\r\n const oldStr =\r\n (typeof d?.old_string === 'string' ? d.old_string : '') ||\r\n (typeof inp.old_string === 'string' ? inp.old_string : '');\r\n const newStr =\r\n (typeof d?.new_string === 'string' ? d.new_string : '') ||\r\n (typeof inp.new_string === 'string' ? inp.new_string : '');\r\n\r\n if (oldStr || newStr) {\r\n return formatDiffFromStrings(oldStr, newStr);\r\n }\r\n\r\n const trimmed = summary.trim();\r\n if (trimmed) return trimmed;\r\n return '(done)';\r\n}\r\n","/**\r\n * DiffView.tsx — unified diff 渲染(纯 CSS +/- 行前缀)\r\n *\r\n * 对齐参考:CC components/FileEditToolDiff.tsx · CLI format_diff_from_strings\r\n */\r\nimport type { ToolBodyMode } from '../types';\r\nimport {\r\n DIFF_PREVIEW_LINES,\r\n parseDiffText,\r\n type ParsedDiffLine,\r\n} from './diffHelpers';\r\n\r\nexport interface DiffViewProps {\r\n diff: string;\r\n mode: ToolBodyMode;\r\n maxPreviewLines?: number;\r\n onExpand?: () => void;\r\n}\r\n\r\nfunction renderLine(line: ParsedDiffLine, index: number) {\r\n const prefix =\r\n line.kind === 'add' ? '+' : line.kind === 'remove' ? '-' : line.kind === 'meta' ? '' : ' ';\r\n\r\n return (\r\n <div\r\n key={index}\r\n className=\"lax-tool-diff__line\"\r\n data-kind={line.kind}\r\n >\r\n {prefix ? (\r\n <span className=\"lax-tool-diff__prefix\" aria-hidden>\r\n {prefix}\r\n </span>\r\n ) : null}\r\n <span className=\"lax-tool-diff__text\">{line.text}</span>\r\n </div>\r\n );\r\n}\r\n\r\nexport function DiffView({\r\n diff,\r\n mode,\r\n maxPreviewLines = DIFF_PREVIEW_LINES,\r\n onExpand,\r\n}: DiffViewProps) {\r\n const lines = parseDiffText(diff);\r\n const needsTruncate = mode === 'preview' && lines.length > maxPreviewLines;\r\n const visible = needsTruncate ? lines.slice(0, maxPreviewLines) : lines;\r\n\r\n return (\r\n <div className=\"lax-tool-diff\">\r\n {visible.map(renderLine)}\r\n {needsTruncate ? (\r\n <button\r\n type=\"button\"\r\n className=\"lax-tool-body__expand\"\r\n onClick={onExpand}\r\n >\r\n +{lines.length - maxPreviewLines} diff lines (点击展开)\r\n </button>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","/**\n * MarkdownBlock.tsx — 完整 markdown 渲染(带性能优化)\n *\n * 职责:display.type=markdown 等场景的段落/列表/代码块/表格。\n * 链路位置:ReadToolBody 等 ToolBody。\n *\n * 性能优化(参考 CC):\n * - 快速路径:纯文本跳过 markdown 解析\n * - 内容哈希缓存:相同内容不重复解析\n * - 组件记忆化:避免不必要的重渲染\n *\n * 功能:\n * - 完整 GFM 支持 (GitHub Flavored Markdown)\n * - 代码语法高亮\n * - 表格渲染\n * - 拷贝按钮\n */\nimport { memo, useMemo, useState } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';\n\nimport { useMarkdownRenderer } from '../../../core/context/MarkdownRendererContext';\nimport type { ToolBodyMode } from '../types';\nimport { MAX_PREVIEW_LINES } from './TruncatedContent';\n\nexport interface MarkdownBlockProps {\n text: string;\n mode: ToolBodyMode;\n maxLines?: number;\n onExpand?: () => void;\n className?: string;\n}\n\n/**\n * 简单的内容哈希函数(用于缓存)\n * 使用 djb2 算法,性能好且冲突率低\n */\nfunction hashContent(content: string): string {\n let hash = 5381;\n for (let i = 0; i < content.length; i++) {\n hash = ((hash << 5) + hash + content.charCodeAt(i)) & 0xffffffff;\n }\n return hash.toString(36);\n}\n\n/**\n * 检测是否包含 markdown 语法\n * 快速路径:如果没有任何 markdown 标记,直接渲染为纯文本\n * 检查前 500 字符即可(markdown 语法通常在前面)\n */\nfunction hasMarkdownSyntax(content: string): boolean {\n const sample = content.length > 500 ? content.slice(0, 500) : content;\n // 检测常见的 markdown 语法标记\n const MD_SYNTAX_RE = /[#*`|[>\\-_~]|\\n\\n|^\\d+\\. |\\n\\d+\\. /;\n return MD_SYNTAX_RE.test(sample);\n}\n\n// 代码块组件(带拷贝功能)- 记忆化\ninterface CodeBlockProps {\n language: string;\n content: string;\n}\n\nconst CodeBlock = memo(function CodeBlock({ language, content }: CodeBlockProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(content);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error('Failed to copy:', err);\n }\n };\n\n return (\n <div className=\"lax-code-block\">\n <div className=\"lax-code-block__header\">\n <span className=\"lax-code-block__lang\">{language || 'code'}</span>\n <button\n type=\"button\"\n className={`lax-code-block__copy ${copied ? 'lax-code-block__copy--copied' : ''}`}\n onClick={handleCopy}\n title={copied ? '已拷贝!' : '拷贝代码'}\n >\n {copied ? (\n <>\n <svg className=\"lax-code-block__icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={3}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n <span>已拷贝</span>\n </>\n ) : (\n <>\n <svg className=\"lax-code-block__icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n 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\"\n />\n </svg>\n <span>拷贝</span>\n </>\n )}\n </button>\n </div>\n <SyntaxHighlighter\n language={language}\n style={oneDark}\n customStyle={{\n margin: 0,\n padding: 0,\n background: 'transparent',\n }}\n showLineNumbers={false}\n wrapLongLines={true}\n >\n {content}\n </SyntaxHighlighter>\n </div>\n );\n});\n\n// Markdown 组件配置 - 缓存在组件外部,避免重复创建\nconst MARKDOWN_COMPONENTS = {\n // 代码块\n code({ node, className, children, ...props }: any) {\n const match = /language-(\\w+)/.exec(className || '');\n const codeContent = String(children).replace(/\\n$/, '');\n const inline = !className;\n\n if (!inline && match) {\n return <CodeBlock language={match[1]} content={codeContent} />;\n }\n\n return (\n <code className=\"lax-markdown__inline-code\" {...props}>\n {children}\n </code>\n );\n },\n // 标题\n h1({ children }: any) { return <h1 className=\"lax-markdown__heading lax-markdown__h1\">{children}</h1>; },\n h2({ children }: any) { return <h2 className=\"lax-markdown__heading lax-markdown__h2\">{children}</h2>; },\n h3({ children }: any) { return <h3 className=\"lax-markdown__heading lax-markdown__h3\">{children}</h3>; },\n h4({ children }: any) { return <h4 className=\"lax-markdown__heading lax-markdown__h4\">{children}</h4>; },\n h5({ children }: any) { return <h5 className=\"lax-markdown__heading lax-markdown__h5\">{children}</h5>; },\n h6({ children }: any) { return <h6 className=\"lax-markdown__heading lax-markdown__h6\">{children}</h6>; },\n // 段落\n p({ children }: any) { return <p className=\"lax-markdown__paragraph\">{children}</p>; },\n // 列表\n ul({ children }: any) { return <ul className=\"lax-markdown__list lax-markdown__ul\">{children}</ul>; },\n ol({ children }: any) { return <ol className=\"lax-markdown__list lax-markdown__ol\">{children}</ol>; },\n li({ children }: any) { return <li className=\"lax-markdown__li\">{children}</li>; },\n // 链接\n a({ children, href }: any) {\n return (\n <a href={href} className=\"lax-markdown__link\" target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n </a>\n );\n },\n // 引用\n blockquote({ children }: any) { return <blockquote className=\"lax-markdown__blockquote\">{children}</blockquote>; },\n // 表格\n table({ children }: any) {\n return (\n <div className=\"lax-markdown__table-wrapper\">\n <table className=\"lax-markdown__table\">{children}</table>\n </div>\n );\n },\n thead({ children }: any) { return <thead className=\"lax-markdown__thead\">{children}</thead>; },\n tbody({ children }: any) { return <tbody className=\"lax-markdown__tbody\">{children}</tbody>; },\n tr({ children }: any) { return <tr className=\"lax-markdown__tr\">{children}</tr>; },\n th({ children }: any) { return <th className=\"lax-markdown__th\">{children}</th>; },\n td({ children }: any) { return <td className=\"lax-markdown__td\">{children}</td>; },\n // 分隔线\n hr() { return <hr className=\"lax-markdown__hr\" />; },\n // 强调\n strong({ children }: any) { return <strong className=\"lax-markdown__strong\">{children}</strong>; },\n em({ children }: any) { return <em className=\"lax-markdown__em\">{children}</em>; },\n};\n\n// 纯文本渲染组件(快速路径)\nconst PureTextRenderer = memo(function PureTextRenderer({ content, className }: { content: string; className?: string }) {\n return (\n <div className={['lax-markdown', 'lax-markdown--pure', className].filter(Boolean).join(' ')}>\n <p className=\"lax-markdown__paragraph\">{content}</p>\n </div>\n );\n});\n\n// Markdown 渲染组件(记忆化)\nconst MarkdownRenderer = memo(function MarkdownRenderer({ content, className }: { content: string; className?: string }) {\n return (\n <div className={['lax-markdown', className].filter(Boolean).join(' ')}>\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={MARKDOWN_COMPONENTS}\n >\n {content}\n </ReactMarkdown>\n </div>\n );\n});\n\nexport function MarkdownBlock({\n text,\n mode,\n maxLines = MAX_PREVIEW_LINES,\n onExpand,\n className,\n}: MarkdownBlockProps) {\n const markdownRenderer = useMarkdownRenderer();\n\n // 使用 useMemo 缓存截断和哈希计算\n const { visible, remaining, needsTruncate, contentHash } = useMemo(() => {\n const lines = text.split('\\n');\n const needsTruncate = mode === 'preview' && lines.length > maxLines;\n const visible = needsTruncate ? lines.slice(0, maxLines).join('\\n') : text;\n const remaining = lines.length - maxLines;\n const contentHash = hashContent(visible);\n return { visible, remaining, needsTruncate, contentHash };\n }, [text, mode, maxLines]);\n\n // 如果应用层提供了 markdownRenderer,使用它\n if (markdownRenderer) {\n return (\n <div className={['lax-markdown', className].filter(Boolean).join(' ')}>\n {markdownRenderer({ content: visible, className: 'lax-markdown__rich' })}\n {needsTruncate ? (\n <button\n type=\"button\"\n className=\"lax-tool-body__expand\"\n onClick={onExpand}\n >\n +{remaining} 行 (点击展开)\n </button>\n ) : null}\n </div>\n );\n }\n\n // 使用内容哈希作为 key 来利用 React 的 diff 算法\n // 相同内容不会重新渲染\n const rendererKey = `md-${contentHash}`;\n\n // 快速路径:纯文本直接渲染,跳过 markdown 解析\n if (!hasMarkdownSyntax(visible)) {\n return (\n <>\n <PureTextRenderer key={rendererKey} content={visible} className={className} />\n {needsTruncate ? (\n <button\n type=\"button\"\n className=\"lax-tool-body__expand\"\n onClick={onExpand}\n >\n +{remaining} 行 (点击展开)\n </button>\n ) : null}\n </>\n );\n }\n\n // 完整 markdown 渲染\n return (\n <>\n <MarkdownRenderer key={rendererKey} content={visible} className={className} />\n {needsTruncate ? (\n <button\n type=\"button\"\n className=\"lax-tool-body__expand\"\n onClick={onExpand}\n >\n +{remaining} 行 (点击展开)\n </button>\n ) : null}\n </>\n );\n}\n","/**\r\n * MarkdownRendererContext — 富 Markdown 注入(与 ToolDisplayRegistry 解耦,避免循环依赖)\r\n */\r\nimport { createContext, useContext, type ReactNode } from 'react';\r\n\r\nexport interface MarkdownRendererProps {\r\n content: string;\r\n className?: string;\r\n}\r\n\r\nexport type MarkdownRenderer = (props: MarkdownRendererProps) => ReactNode;\r\n\r\nexport const MarkdownRendererContext = createContext<MarkdownRenderer | undefined>(\r\n undefined,\r\n);\r\n\r\nexport function useMarkdownRenderer(): MarkdownRenderer | undefined {\r\n return useContext(MarkdownRendererContext);\r\n}\r\n"],"mappings":"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","names":["minutes","blocks","footer","jsx","jsx","jsxs","jsx","jsxs","CodeBlock","PureTextRenderer","MarkdownRenderer","needsTruncate","visible","remaining","contentHash"]}
|