langchain_agentx_stream_ui 0.6.0 → 0.6.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-GBY5DJ7L.js → chunk-4RIOBLGB.js} +1 -1
- package/dist/chunk-4RIOBLGB.js.map +1 -0
- package/dist/{chunk-GGPYP2VK.js → chunk-4TG4TGIL.js} +4 -4
- package/dist/chunk-4TG4TGIL.js.map +1 -0
- package/dist/{chunk-RAOW6Z6R.js → chunk-DJPNJBFL.js} +21 -29
- package/dist/chunk-DJPNJBFL.js.map +1 -0
- package/dist/{chunk-6Z4ZF36Z.js → chunk-DP7V33X7.js} +1 -1
- package/dist/chunk-DP7V33X7.js.map +1 -0
- package/dist/{chunk-32H5OCBB.js → chunk-ED67MXSG.js} +5 -5
- package/dist/chunk-ED67MXSG.js.map +1 -0
- package/dist/{chunk-UFRVQZBD.js → chunk-ZR37OKV6.js} +209 -49
- package/dist/chunk-ZR37OKV6.js.map +1 -0
- package/dist/default.css +91 -18
- package/dist/index.js +150 -105
- 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-32H5OCBB.js.map +0 -1
- package/dist/chunk-6Z4ZF36Z.js.map +0 -1
- package/dist/chunk-GBY5DJ7L.js.map +0 -1
- package/dist/chunk-GGPYP2VK.js.map +0 -1
- package/dist/chunk-RAOW6Z6R.js.map +0 -1
- package/dist/chunk-UFRVQZBD.js.map +0 -1
|
@@ -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":["/**\n * paths.ts — 路径展示 helper\n *\n * 职责:\n * 将绝对路径转为较短展示字符串(Web 无 cwd 时仅 normalize 分隔符)。\n *\n * 链路位置:\n * T1+ Read/Edit Widget title。\n *\n * 当前裁剪范围:\n * 不做 relpath(浏览器无 process.cwd);仅 slash 归一化。\n *\n * 对齐参考:\n * CLI widgets/tools/helpers.py display_path\n */\n\nexport function displayPath(filePath: string): string {\n if (!filePath) return '';\n return filePath.replace(/\\\\/g, '/');\n}\n","/**\n * searchHelpers.ts — grep/glob 标题与列表正文 helper\n *\n * 对齐参考:CLI widgets/tools/helpers.py format_pattern_title、format_search_result_body\n */\n\nimport { displayPath } from './paths';\n\nexport const SEARCH_LIST_PREVIEW_LINES = 20;\n\nconst FOUND_SUMMARY_RE = /^(Found .+|No files found|No matches found)/i;\n\nexport function formatPatternTitle(pattern: string, path?: string | null): string {\n const parts = [`pattern: \"${pattern}\"`];\n if (path) {\n parts.push(`path: \"${displayPath(path)}\"`);\n }\n return parts.join(', ');\n}\n\nexport function extractSearchSummary(output: string): string {\n const text = output.trim();\n if (!text) return '';\n const match = text.match(FOUND_SUMMARY_RE);\n if (match) return match[1].trim();\n const first = text.split('\\n', 1)[0]?.trim() ?? '';\n if (/^(found |no files|no matches)/i.test(first)) return first;\n return '';\n}\n\nexport function truncateLines(\n text: string,\n maxLines: number,\n): { text: string; truncated: boolean } {\n const lines = text.split('\\n');\n if (lines.length <= maxLines) {\n return { text, truncated: false };\n }\n return {\n text: lines.slice(0, maxLines).join('\\n'),\n truncated: true,\n };\n}\n\nexport function formatSearchResultBody(\n output: string,\n maxListLines = SEARCH_LIST_PREVIEW_LINES,\n): string {\n const text = output.trim();\n if (!text) return '(No output)';\n\n const summary = extractSearchSummary(text);\n const lines = text.split('\\n');\n let listLines: string[];\n\n if (summary && lines[0]?.trim() === summary) {\n listLines = lines.slice(1);\n } else if (summary) {\n listLines = lines.filter((ln) => ln.trim() !== summary);\n } else {\n listLines = lines;\n }\n\n const listText = listLines\n .map((ln) => ln.trim())\n .filter(Boolean)\n .join('\\n');\n\n if (listText) {\n const { text: truncated, truncated: wasTruncated } = truncateLines(\n listText,\n maxListLines,\n );\n const suffix = wasTruncated ? `\\n… 列表超过 ${maxListLines} 行,已截断` : '';\n if (summary) return `${summary}\\n${truncated}${suffix}`;\n return `${truncated}${suffix}`;\n }\n\n return summary || text.slice(0, 500);\n}\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","/**\n * bashHelpers.ts — bash 命令与输出解析\n *\n * 对齐参考:CLI widgets/tools/helpers.py · bash/widget.py format_body_blocks\n */\nimport type { ToolBodyMode } from '../types';\nimport { MAX_PREVIEW_LINES } from './TruncatedContent';\nimport type { BodyBlock } from './BodyBlockList';\n\nexport const MAX_COMMAND_DISPLAY_CHARS = 160;\nexport const MAX_COMMAND_DISPLAY_LINES = 2;\n\nconst CWD_RESET_PATTERN = /(?:^|\\n)(Shell cwd was reset to .+)$/m;\nconst EXIT_CODE_PATTERN = /(?:^|\\n)Exit code:\\s*(\\d+)/m;\n\nexport function truncateCommand(command: string, maxChars = MAX_COMMAND_DISPLAY_CHARS): string {\n let text = command.trim();\n if (!text) return '';\n const lines = text.split('\\n');\n if (lines.length > MAX_COMMAND_DISPLAY_LINES) {\n text = lines.slice(0, MAX_COMMAND_DISPLAY_LINES).join('\\n');\n }\n if (text.length > maxChars) {\n text = `${text.slice(0, maxChars)}…`;\n }\n return text;\n}\n\nexport function formatBashTitle(input: unknown): string {\n const inp =\n input != null && typeof input === 'object' && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : {};\n const command = String(inp.command ?? '').trim();\n if (!command) return 'Bash';\n return `Bash(${truncateCommand(command)})`;\n}\n\nexport function splitBashStreams(output: string): {\n stdout: string;\n stderr: string;\n cwdWarning: string | null;\n} {\n let text = output ?? '';\n let cwdWarning: string | null = null;\n const cwdMatch = text.match(CWD_RESET_PATTERN);\n if (cwdMatch) {\n cwdWarning = cwdMatch[1]?.trim() ?? null;\n text = text.replace(CWD_RESET_PATTERN, '').trim();\n }\n\n let stdout = text;\n let stderr = '';\n if (text.includes('\\n--- stderr ---\\n')) {\n const parts = text.split('\\n--- stderr ---\\n');\n stdout = parts[0] ?? '';\n stderr = parts[1] ?? '';\n } else if (text.startsWith('stderr:')) {\n stderr = text.slice(7).trim();\n stdout = '';\n }\n\n return { stdout: stdout.trim(), stderr: stderr.trim(), cwdWarning };\n}\n\nexport function parseExitCode(output: string, fallback?: number | null): number | null {\n const match = (output ?? '').match(EXIT_CODE_PATTERN);\n if (match) return Number.parseInt(match[1], 10);\n return fallback ?? null;\n}\n\nexport function formatDuration(seconds: number): string {\n if (seconds < 1) return `${seconds.toFixed(1)}s`;\n if (seconds < 60) return `${Math.floor(seconds)}s`;\n if (seconds < 3600) {\n const minutes = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return secs === 0 ? `${minutes}m` : `${minutes}m ${secs}s`;\n }\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n return minutes === 0 ? `${hours}h` : `${hours}h ${minutes}m`;\n}\n\nexport function formatTimeoutFooter(timeoutMs: number | null | undefined): string | null {\n if (!timeoutMs) return null;\n return `(timeout ${formatDuration(timeoutMs / 1000)})`;\n}\n\nfunction previewStreamText(text: string, mode: ToolBodyMode): string {\n if (mode === 'full' || !text.trim()) return text;\n const lines = text.split('\\n');\n if (lines.length <= MAX_PREVIEW_LINES) return text;\n // 对齐 CLI ShellOutputPreviewer:PREVIEW 只保留前 N 行;expand hint 由 UI 层单独渲染\n return lines.slice(0, MAX_PREVIEW_LINES).join('\\n');\n}\n\nfunction resolveStreams(\n display: Record<string, unknown> | null,\n summary: string,\n): { stdout: string; stderr: string; cwdWarning: string | null } {\n if (display && ('stdout' in display || 'stderr' in display)) {\n return {\n stdout: String(display.stdout ?? ''),\n stderr: String(display.stderr ?? ''),\n cwdWarning: null,\n };\n }\n return splitBashStreams(summary);\n}\n\nfunction resolveExitCode(\n display: Record<string, unknown> | null,\n summary: string,\n): number | null {\n if (display && 'exit_code' in display) {\n const code = display.exit_code;\n if (typeof code === 'number') return code;\n if (typeof code === 'string' && code.trim()) {\n const n = Number.parseInt(code, 10);\n if (Number.isFinite(n)) return n;\n }\n return null;\n }\n return parseExitCode(summary);\n}\n\nfunction resolveTimeoutMs(\n display: Record<string, unknown> | null,\n meta: unknown,\n): number | null {\n if (display?.timeout_ms != null) {\n const n = Number(display.timeout_ms);\n return Number.isFinite(n) ? n : null;\n }\n if (meta != null && typeof meta === 'object' && !Array.isArray(meta)) {\n const ms = (meta as Record<string, unknown>).timeout_ms;\n if (ms != null) {\n const n = Number(ms);\n return Number.isFinite(n) ? n : null;\n }\n }\n return null;\n}\n\nexport function buildBashBodyBlocks(\n display: unknown,\n summary: string,\n meta: unknown,\n mode: ToolBodyMode,\n isError: boolean,\n): { blocks: BodyBlock[]; truncated: boolean; remainingLines: number } {\n const d =\n display != null && typeof display === 'object' && !Array.isArray(display)\n ? (display as Record<string, unknown>)\n : null;\n\n if (isError) {\n const blocks: BodyBlock[] = [\n { text: summary.trim() || 'Error', variant: 'error' },\n ];\n const footer = formatTimeoutFooter(resolveTimeoutMs(d, meta));\n if (footer) blocks.push({ text: footer, variant: 'dim' });\n return { blocks, truncated: false, remainingLines: 0 };\n }\n\n const { stdout, stderr, cwdWarning } = resolveStreams(d, summary);\n const code = resolveExitCode(d, summary);\n const blocks: BodyBlock[] = [];\n let truncated = false;\n let remainingLines = 0;\n\n const addStream = (text: string, variant: BodyBlock['variant']) => {\n if (!text.trim()) return;\n const lines = text.split('\\n');\n const rendered = previewStreamText(text, mode);\n if (mode === 'preview' && lines.length > MAX_PREVIEW_LINES) {\n truncated = true;\n remainingLines += lines.length - MAX_PREVIEW_LINES;\n }\n blocks.push({ text: rendered, variant });\n };\n\n addStream(stdout, 'normal');\n addStream(stderr, 'error');\n\n if (cwdWarning) {\n blocks.push({ text: cwdWarning, variant: 'dim' });\n }\n\n if (code != null && code !== 0) {\n blocks.push({ text: `Exit code: ${code}`, variant: 'error' });\n }\n\n if (blocks.length === 0) {\n const noOutputExpected = Boolean(d?.no_output_expected);\n blocks.push({\n text: noOutputExpected ? 'Done' : '(No output)',\n variant: 'dim',\n });\n }\n\n const footer = formatTimeoutFooter(resolveTimeoutMs(d, meta));\n if (footer) {\n blocks.push({ text: footer, variant: 'dim' });\n }\n\n if (d?.truncated && d?.overflow_file) {\n blocks.push({\n text: `Output truncated; see ${String(d.overflow_file)}`,\n variant: 'dim',\n });\n }\n\n return { blocks, truncated, remainingLines };\n}\n","/**\n * BodyBlockList.tsx — ⎿ 多块正文布局\n *\n * 职责:\n * 多块平面文本,支持 normal / error / dim 变体。\n *\n * 链路位置:\n * T3 bash stdout/stderr 分块;DefaultToolBody 可复用。\n *\n * 当前裁剪范围:\n * 块内不做 TruncatedContent(由调用方传入已截断文本)。\n *\n * 对齐参考:\n * CLI presentation/message_layout.py · CC MessageResponse.tsx ⎿ 前缀\n */\n\nexport interface BodyBlock {\n text: string;\n variant?: 'normal' | 'error' | 'dim';\n}\n\nexport interface BodyBlockListProps {\n blocks: BodyBlock[];\n}\n\nexport function BodyBlockList({ blocks }: BodyBlockListProps) {\n if (blocks.length === 0) return null;\n\n return (\n <div className=\"lax-tool-body__blocks\">\n {blocks.map((block, index) => (\n <div\n key={index}\n className=\"lax-tool-body__block\"\n data-variant={block.variant ?? 'normal'}\n >\n <pre className=\"lax-tool-body__text\">{block.text}</pre>\n </div>\n ))}\n </div>\n );\n}\n","/**\n * diffHelpers.ts — unified diff 生成与解析\n *\n * 对齐参考:CLI widgets/tools/helpers.py format_diff_from_strings\n */\n\nexport const WRITE_PREVIEW_LINES = 10;\nexport const DIFF_PREVIEW_LINES = 12;\n\nexport type DiffLineKind = 'add' | 'remove' | 'context' | 'meta';\n\nexport interface ParsedDiffLine {\n kind: DiffLineKind;\n text: string;\n}\n\nexport function countLines(text: string): number {\n if (!text) return 0;\n return text.split('\\n').length;\n}\n\nexport function formatDiffFromStrings(oldText: string, newText: string): string {\n if (oldText === newText) return '(no changes)';\n\n const oldLines = oldText.split('\\n');\n const newLines = newText.split('\\n');\n const body: string[] = [];\n let i = 0;\n let j = 0;\n\n while (i < oldLines.length || j < newLines.length) {\n const oldLine = oldLines[i];\n const newLine = newLines[j];\n\n if (i < oldLines.length && j < newLines.length && oldLine === newLine) {\n body.push(` ${oldLine}`);\n i += 1;\n j += 1;\n continue;\n }\n\n if (i < oldLines.length && (j >= newLines.length || oldLine !== newLine)) {\n body.push(`-${oldLine}`);\n i += 1;\n continue;\n }\n\n if (j < newLines.length) {\n body.push(`+${newLine}`);\n j += 1;\n }\n }\n\n if (body.length === 0) return '(no changes)';\n\n return ['--- old', '+++ new', '@@', ...body].join('\\n');\n}\n\nexport function parseDiffText(diff: string): ParsedDiffLine[] {\n if (diff === '(no changes)') {\n return [{ kind: 'meta', text: diff }];\n }\n\n const result: ParsedDiffLine[] = [];\n for (const line of diff.split('\\n')) {\n if (!line && result.length > 0) {\n result.push({ kind: 'context', text: '' });\n continue;\n }\n if (line.startsWith('+++') || line.startsWith('---') || line.startsWith('@@')) {\n result.push({ kind: 'meta', text: line });\n } else if (line.startsWith('+')) {\n result.push({ kind: 'add', text: line.slice(1) });\n } else if (line.startsWith('-')) {\n result.push({ kind: 'remove', text: line.slice(1) });\n } else if (line.startsWith(' ')) {\n result.push({ kind: 'context', text: line.slice(1) });\n } else {\n result.push({ kind: 'context', text: line });\n }\n }\n return result;\n}\n\nexport function resolveEditDiffText(\n display: unknown,\n input: unknown,\n summary: string,\n): string {\n const d =\n display != null && typeof display === 'object' && !Array.isArray(display)\n ? (display as Record<string, unknown>)\n : null;\n const inp =\n input != null && typeof input === 'object' && !Array.isArray(input)\n ? (input as Record<string, unknown>)\n : {};\n\n const diffField = d?.diff;\n if (typeof diffField === 'string' && diffField.trim()) {\n return diffField.trim();\n }\n\n const oldStr =\n (typeof d?.old_string === 'string' ? d.old_string : '') ||\n (typeof inp.old_string === 'string' ? inp.old_string : '');\n const newStr =\n (typeof d?.new_string === 'string' ? d.new_string : '') ||\n (typeof inp.new_string === 'string' ? inp.new_string : '');\n\n if (oldStr || newStr) {\n return formatDiffFromStrings(oldStr, newStr);\n }\n\n const trimmed = summary.trim();\n if (trimmed) return trimmed;\n return '(done)';\n}\n","/**\n * DiffView.tsx — unified diff 渲染(纯 CSS +/- 行前缀)\n *\n * 对齐参考:CC components/FileEditToolDiff.tsx · CLI format_diff_from_strings\n */\nimport type { ToolBodyMode } from '../types';\nimport {\n DIFF_PREVIEW_LINES,\n parseDiffText,\n type ParsedDiffLine,\n} from './diffHelpers';\n\nexport interface DiffViewProps {\n diff: string;\n mode: ToolBodyMode;\n maxPreviewLines?: number;\n onExpand?: () => void;\n}\n\nfunction renderLine(line: ParsedDiffLine, index: number) {\n const prefix =\n line.kind === 'add' ? '+' : line.kind === 'remove' ? '-' : line.kind === 'meta' ? '' : ' ';\n\n return (\n <div\n key={index}\n className=\"lax-tool-diff__line\"\n data-kind={line.kind}\n >\n {prefix ? (\n <span className=\"lax-tool-diff__prefix\" aria-hidden>\n {prefix}\n </span>\n ) : null}\n <span className=\"lax-tool-diff__text\">{line.text}</span>\n </div>\n );\n}\n\nexport function DiffView({\n diff,\n mode,\n maxPreviewLines = DIFF_PREVIEW_LINES,\n onExpand,\n}: DiffViewProps) {\n const lines = parseDiffText(diff);\n const needsTruncate = mode === 'preview' && lines.length > maxPreviewLines;\n const visible = needsTruncate ? lines.slice(0, maxPreviewLines) : lines;\n\n return (\n <div className=\"lax-tool-diff\">\n {visible.map(renderLine)}\n {needsTruncate ? (\n <button\n type=\"button\"\n className=\"lax-tool-body__expand\"\n onClick={onExpand}\n >\n +{lines.length - maxPreviewLines} diff lines (点击展开)\n </button>\n ) : null}\n </div>\n );\n}\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","/**\n * MarkdownRendererContext — 富 Markdown 注入(与 ToolDisplayRegistry 解耦,避免循环依赖)\n */\nimport { createContext, useContext, type ReactNode } from 'react';\n\nexport interface MarkdownRendererProps {\n content: string;\n className?: string;\n}\n\nexport type MarkdownRenderer = (props: MarkdownRendererProps) => ReactNode;\n\nexport const MarkdownRendererContext = createContext<MarkdownRenderer | undefined>(\n undefined,\n);\n\nexport function useMarkdownRenderer(): MarkdownRenderer | undefined {\n return useContext(MarkdownRendererContext);\n}\n"],"mappings":"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","names":["minutes","blocks","footer","jsx","jsx","jsxs","jsx","jsxs","CodeBlock","PureTextRenderer","MarkdownRenderer","needsTruncate","visible","remaining","contentHash"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
truncatePreview
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DP7V33X7.js";
|
|
4
4
|
import {
|
|
5
5
|
Agent,
|
|
6
6
|
AskUserQuestion,
|
|
@@ -21,13 +21,13 @@ import {
|
|
|
21
21
|
formatWriteTitle,
|
|
22
22
|
numField,
|
|
23
23
|
strField
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-ZR37OKV6.js";
|
|
25
25
|
import {
|
|
26
26
|
TruncatedContent,
|
|
27
27
|
displayPath,
|
|
28
28
|
formatBashTitle,
|
|
29
29
|
formatPatternTitle
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-4RIOBLGB.js";
|
|
31
31
|
|
|
32
32
|
// src/view/tools/ask_user_question/formatAskUserQuestionTitle.ts
|
|
33
33
|
function firstQuestion(display, input) {
|
|
@@ -383,4 +383,4 @@ export {
|
|
|
383
383
|
useInteractionBus,
|
|
384
384
|
ToolCallShell
|
|
385
385
|
};
|
|
386
|
-
//# sourceMappingURL=chunk-
|
|
386
|
+
//# sourceMappingURL=chunk-4TG4TGIL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/view/tools/ask_user_question/formatAskUserQuestionTitle.ts","../src/view/tools/glob/formatGlobTitle.ts","../src/view/tools/grep/formatGrepTitle.ts","../src/view/tools/read/formatReadTitle.ts","../src/view/tools/skill/formatSkillTitle.ts","../src/view/tools/webfetch/formatWebFetchTitle.ts","../src/view/tools/websearch/formatWebSearchTitle.ts","../src/view/tools/formatToolTitle.ts","../src/view/tools/DefaultToolBody.tsx","../src/view/tools/resolveToolBody.ts","../src/core/interaction/InteractionBus.ts","../src/core/context/InteractionContext.tsx","../src/view/tools/ToolPermissionWait.tsx","../src/view/tools/ToolCallShell.tsx"],"sourcesContent":["/**\n * formatAskUserQuestionTitle.ts — AskUserQuestion 工具标题\n *\n * 对齐参考:CLI widgets/tools/ask_user_question/widget.py format_title\n */\nimport { asDisplayRecord, asInputRecord, numField } from '../displayRecord';\nimport { formatAskUserQuestionsPreview } from '../presentation/askUserHelpers';\nimport { truncatePreview } from '../presentation/textHelpers';\n\nfunction firstQuestion(\n display: Record<string, unknown> | null,\n input: Record<string, unknown>,\n): { header: string; question: string } {\n const items = display?.questions;\n if (Array.isArray(items) && items.length > 0) {\n const first = items[0];\n if (first != null && typeof first === 'object') {\n const row = first as Record<string, unknown>;\n return {\n header: String(row.header ?? '').trim(),\n question: String(row.question ?? '').trim(),\n };\n }\n }\n\n const questions = input.questions;\n if (Array.isArray(questions) && questions.length > 0) {\n const first = questions[0];\n if (first != null && typeof first === 'object') {\n const row = first as Record<string, unknown>;\n return {\n header: String(row.header ?? '').trim(),\n question: String(row.question ?? '').trim(),\n };\n }\n }\n\n return { header: '', question: '' };\n}\n\nexport function formatAskUserQuestionTitle(\n input: unknown,\n display: unknown,\n _summary?: string | null,\n): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const { header, question } = firstQuestion(d, inp);\n\n if (question) {\n const label = header ? `[${header}] ${question}` : question;\n return truncatePreview(label, 100);\n }\n\n const answered = numField(d ?? {}, 'answered_count');\n if (answered != null) return `Ask user (${answered} answered)`;\n\n return 'Ask user';\n}\n\nexport { formatAskUserQuestionsPreview };\n","/**\n * formatGlobTitle.ts — glob 工具标题\n *\n * 对齐参考:CLI widgets/tools/glob/widget.py format_title\n */\nimport { formatPatternTitle } from '../presentation/searchHelpers';\nimport { asDisplayRecord, asInputRecord, numField, strField } from '../displayRecord';\n\nexport function formatGlobTitle(\n input: unknown,\n display: unknown,\n _summary?: string | null,\n): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const pattern = strField(d ?? {}, 'pattern') || strField(inp, 'pattern');\n\n if (!pattern) return 'Search';\n\n const path = strField(inp, 'path') || undefined;\n const suffix = formatPatternTitle(pattern, path);\n const numFiles = numField(d ?? {}, 'num_files');\n const countHint = numFiles != null ? ` · ${numFiles} files` : '';\n\n return `Search(${suffix}${countHint})`;\n}\n","/**\n * formatGrepTitle.ts — grep 工具标题\n *\n * 对齐参考:CLI widgets/tools/grep/widget.py format_title\n */\nimport { formatPatternTitle } from '../presentation/searchHelpers';\nimport { asDisplayRecord, asInputRecord, numField, strField } from '../displayRecord';\n\nexport function formatGrepTitle(\n input: unknown,\n display: unknown,\n _summary?: string | null,\n): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const pattern = strField(d ?? {}, 'pattern') || strField(inp, 'pattern');\n\n if (!pattern) return 'Search';\n\n const path = strField(inp, 'path') || undefined;\n const suffix = formatPatternTitle(pattern, path);\n const numMatches = numField(d ?? {}, 'num_matches');\n const countHint = numMatches != null ? ` · ${numMatches} matches` : '';\n\n return `Search(${suffix}${countHint})`;\n}\n","/**\n * formatReadTitle.ts — Read 工具标题\n *\n * 对齐参考:CLI widgets/tools/read/widget.py format_title\n */\nimport { displayPath } from '../presentation/paths';\nimport { asDisplayRecord, asInputRecord, numField, strField } from '../displayRecord';\n\nconst LINES_RANGE_RE = /lines (\\d+)-(\\d+) of (\\d+)/;\nconst READ_LINES_RE = /Read (\\d+) lines from/;\n\nfunction titleSuffixFromDisplay(display: unknown): string {\n const d = asDisplayRecord(display);\n if (!d) return '';\n\n if (d.type === 'text') {\n const start = numField(d, 'line_start');\n const end = numField(d, 'line_end');\n if (start != null && end != null) {\n return ` · lines ${start}-${end}`;\n }\n }\n\n if (d.type === 'pdf') {\n const ps = numField(d, 'page_start');\n const pe = numField(d, 'page_end');\n if (ps != null && pe != null) {\n return ` · pages ${ps}-${pe}`;\n }\n }\n\n return '';\n}\n\nfunction titleSuffixFromSummary(summary: string, input: unknown): string {\n const matchRange = summary.match(LINES_RANGE_RE);\n if (matchRange) {\n return ` · lines ${matchRange[1]}-${matchRange[2]}`;\n }\n\n const inp = asInputRecord(input);\n const offset = numField(inp, 'offset');\n const limit = numField(inp, 'limit');\n if (offset != null && limit != null) {\n return ` · lines ${offset}-${offset + limit - 1}`;\n }\n\n const matchLines = summary.match(READ_LINES_RE);\n if (matchLines) {\n return ` · ${matchLines[1]} lines`;\n }\n\n return '';\n}\n\nexport function formatReadTitle(input: unknown, display: unknown, summary?: string | null): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const path = displayPath(\n strField(d ?? {}, 'file_path') ||\n strField(inp, 'file_path') ||\n strField(inp, 'path'),\n );\n\n const suffix =\n titleSuffixFromDisplay(display) ||\n (summary ? titleSuffixFromSummary(summary, input) : '');\n\n if (!path) {\n return suffix ? `Read(${suffix.trim()})` : 'Read';\n }\n\n return `Read(${path}${suffix})`;\n}\n","/**\n * formatSkillTitle.ts — skill 工具标题\n *\n * 对齐参考:CLI widgets/tools/skill/widget.py format_title\n */\nimport { asDisplayRecord, asInputRecord, strField } from '../displayRecord';\n\nexport function formatSkillTitle(\n input: unknown,\n display: unknown,\n _summary?: string | null,\n): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const name = strField(d ?? {}, 'skill_name') || strField(inp, 'skill_name');\n if (!name) return 'Skill';\n\n if (d?.source === 'commands_DEPRECATED') {\n return `/${name}`;\n }\n return name;\n}\n","/**\n * formatWebFetchTitle.ts — WebFetch 工具标题\n *\n * 对齐参考:CLI widgets/tools/webfetch/widget.py format_title\n */\nimport { asDisplayRecord, asInputRecord, numField, strField } from '../displayRecord';\nimport { truncatePreview } from '../presentation/textHelpers';\n\nexport function formatWebFetchTitle(\n input: unknown,\n display: unknown,\n _summary?: string | null,\n): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const url = strField(d ?? {}, 'url') || strField(inp, 'url');\n if (!url) return 'Fetch';\n\n const code = numField(d ?? {}, 'http_code');\n const title =\n code != null ? `${url} · HTTP ${code}` : truncatePreview(url, 100);\n return `Fetch(${title})`;\n}\n","/**\n * formatWebSearchTitle.ts — WebSearch 工具标题\n *\n * 对齐参考:CLI widgets/tools/websearch/widget.py format_title\n */\nimport { asDisplayRecord, asInputRecord, numField, strField } from '../displayRecord';\nimport { truncatePreview } from '../presentation/textHelpers';\n\nexport function formatWebSearchTitle(\n input: unknown,\n display: unknown,\n _summary?: string | null,\n): string {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const query = strField(d ?? {}, 'query') || strField(inp, 'query');\n if (!query) return 'Web Search';\n\n let queryPart = `\"${truncatePreview(query, 100)}\"`;\n const hits = numField(d ?? {}, 'total_hits');\n if (hits != null) queryPart = `${queryPart} · ${hits} hits`;\n\n return `Web Search(${queryPart})`;\n}\n","/**\n * formatToolTitle.ts — 工具卡片标题格式化\n */\nimport { formatAgentTitle } from './presentation/agentHelpers';\nimport { formatAskUserQuestionTitle } from './ask_user_question/formatAskUserQuestionTitle';\nimport { formatBashTitle } from './presentation/bashHelpers';\nimport { formatEditTitle } from './edit/formatEditTitle';\nimport { formatGlobTitle } from './glob/formatGlobTitle';\nimport { formatGrepTitle } from './grep/formatGrepTitle';\nimport { formatReadTitle } from './read/formatReadTitle';\nimport { formatSkillTitle } from './skill/formatSkillTitle';\nimport { formatWebFetchTitle } from './webfetch/formatWebFetchTitle';\nimport { formatWebSearchTitle } from './websearch/formatWebSearchTitle';\nimport { formatWriteTitle } from './write/formatWriteTitle';\nimport {\n Agent,\n AskUserQuestion,\n Bash,\n Edit,\n Glob,\n Grep,\n Read,\n Skill,\n WebFetch,\n WebSearch,\n Write,\n} from './toolNames';\n\ntype TitleFormatter = (\n input: unknown,\n display: unknown,\n summary?: string | null,\n meta?: unknown,\n) => string;\n\nconst TITLE_FORMATTERS: Record<string, TitleFormatter> = {\n [Read]: formatReadTitle,\n [Grep]: formatGrepTitle,\n [Glob]: formatGlobTitle,\n [Edit]: formatEditTitle,\n [Write]: formatWriteTitle,\n [Bash]: formatBashTitle,\n [Agent]: formatAgentTitle,\n [Skill]: formatSkillTitle,\n [WebSearch]: formatWebSearchTitle,\n [WebFetch]: formatWebFetchTitle,\n [AskUserQuestion]: formatAskUserQuestionTitle,\n};\n\nexport function formatToolTitle(\n toolName: string,\n input: unknown,\n display: unknown,\n summary?: string | null,\n meta?: unknown,\n): string {\n const formatter = TITLE_FORMATTERS[toolName];\n if (formatter) {\n return formatter(input, display, summary, meta);\n }\n return toolName;\n}\n","/**\n * DefaultToolBody.tsx — 未注册工具回退 Body\n *\n * 职责:\n * summary + display JSON 预览(≥ V2);markdown/text 走 TruncatedContent。\n *\n * 链路位置:\n * resolveToolBody 最终回退。\n *\n * 当前裁剪范围:\n * 不渲染 blocks 主视图(折叠区保留在 ToolCallCard details)。\n *\n * 对齐参考:\n * CLI widgets/tools/base.py BaseToolWidget · V2 ToolCallCard JSON pre\n */\nimport { ToolResultHints } from './presentation/ToolResultHints';\nimport { TruncatedContent } from './presentation/TruncatedContent';\nimport type { ToolDisplayProps } from './types';\n\nfunction formatDisplayJson(display: unknown): string {\n if (display == null) return '';\n if (typeof display === 'string') return display;\n try {\n return JSON.stringify(display, null, 2);\n } catch {\n return String(display);\n }\n}\n\nfunction extractTextContent(display: unknown): string | null {\n if (display == null) return null;\n if (typeof display === 'string') return display;\n if (typeof display === 'object') {\n const record = display as { content?: unknown; text?: unknown };\n if (typeof record.content === 'string') return record.content;\n if (typeof record.text === 'string') return record.text;\n }\n return null;\n}\n\nexport function DefaultToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n const summary = result?.summary;\n const displayBody = result?.display ?? null;\n const textContent = extractTextContent(displayBody);\n const jsonBody = textContent ?? formatDisplayJson(displayBody);\n\n return (\n <div className=\"lax-tool-body lax-tool-body--default\">\n {summary ? (\n <div className=\"lax-tool-card__summary\">{summary}</div>\n ) : null}\n\n {displayBody != null && displayBody !== '' && jsonBody ? (\n <div className=\"lax-tool-card__display\">\n {textContent != null ? (\n <TruncatedContent\n text={textContent}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n ) : (\n <pre className=\"lax-tool-card__display-body\">{jsonBody}</pre>\n )}\n </div>\n ) : null}\n\n {result?.truncated ? (\n <div className=\"lax-tool-card__truncated\">结果已截断</div>\n ) : null}\n\n {result?.overflow_file ? (\n <div className=\"lax-tool-card__overflow\">\n 完整输出:\n <code>{result.overflow_file}</code>\n </div>\n ) : null}\n\n <ToolResultHints hints={result?.hints} />\n </div>\n );\n}\n","/**\n * resolveToolBody.ts — 工具 Body 路由纯函数\n *\n * 职责:\n * registry → display.type → DefaultToolBody(精确 tool_name 匹配,无 alias)。\n *\n * 链路位置:\n * ToolCallCard render。\n *\n * 当前裁剪范围:\n * T0 display.type 二级路由表为空;T1+ 注册专用 Widget 与 kind router。\n *\n * 对齐参考:\n * CLI widgets/tools/__init__.py resolve_tool_widget\n */\nimport { DefaultToolBody } from './DefaultToolBody';\nimport type { ToolDisplayRegistry } from './registry';\nimport type { ToolBodyComponent } from './types';\n\n/** display.type → Body;T0 空表,T1+ 填充。 */\nconst DISPLAY_KIND_ROUTER = new Map<string, ToolBodyComponent>();\n\nfunction getDisplayType(display: unknown): string | undefined {\n if (display == null || typeof display !== 'object') return undefined;\n const type = (display as { type?: unknown }).type;\n return typeof type === 'string' ? type : undefined;\n}\n\nexport function resolveToolBody(\n toolName: string,\n display: unknown,\n registry: ToolDisplayRegistry,\n): ToolBodyComponent {\n const byName = registry.resolve(toolName);\n if (byName) return byName;\n\n const displayType = getDisplayType(display);\n if (displayType) {\n const byKind = DISPLAY_KIND_ROUTER.get(displayType);\n if (byKind) return byKind;\n }\n\n return DefaultToolBody;\n}\n\n/** 测试 / 扩展用:注册 display.type 路由。 */\nexport function registerDisplayKind(\n displayType: string,\n body: ToolBodyComponent,\n): void {\n DISPLAY_KIND_ROUTER.set(displayType, body);\n}\n\n/** 测试用:清空 display kind 路由。 */\nexport function clearDisplayKindRouter(): void {\n DISPLAY_KIND_ROUTER.clear();\n}\n","/**\n * 职责:人类回写薄层 API;PermissionNode 触发,业务实现 HTTP 回写。\n * 链路位置:AgentSession interactionBus prop → PermissionNode 按钮。\n * 当前裁剪范围:permission resolve;不含 HITL 表单协议。\n */\n\nexport interface PermissionResolvePayload {\n requestId: string;\n allow: boolean;\n message?: string;\n}\n\nexport interface InteractionBus {\n resolvePermission: (payload: PermissionResolvePayload) => void | Promise<void>;\n}\n\nexport interface InteractionBusHandlers {\n onPermissionResolve?: (payload: PermissionResolvePayload) => void | Promise<void>;\n}\n\nconst noopBus: InteractionBus = {\n resolvePermission() {\n if (import.meta.env?.DEV) {\n console.warn('[langchain_agentx_stream_ui] resolvePermission without InteractionBus');\n }\n },\n};\n\nexport function createInteractionBus(handlers: InteractionBusHandlers = {}): InteractionBus {\n return {\n resolvePermission(payload) {\n return handlers.onPermissionResolve?.(payload);\n },\n };\n}\n\nexport function getNoopInteractionBus(): InteractionBus {\n return noopBus;\n}\n","/**\n * 职责:向 PermissionNode 注入 InteractionBus。\n * 链路位置:AgentSession / MultiAgentSession Provider。\n * 当前裁剪范围:单 bus;多会话共用同一 bus(业务按 requestId 路由)。\n */\nimport { createContext, useContext } from 'react';\n\nimport type { InteractionBus } from '../interaction/InteractionBus';\nimport { getNoopInteractionBus } from '../interaction/InteractionBus';\n\nexport const InteractionBusContext = createContext<InteractionBus>(getNoopInteractionBus());\n\nexport function useInteractionBus(): InteractionBus {\n return useContext(InteractionBusContext);\n}\n","/**\n * ToolPermissionWait.tsx — ToolCallShell 内嵌 permission 等待态(T4.6)\n *\n * 对齐参考:CC AssistantToolUseMessage「Waiting for permission…」分支\n */\nimport { useState } from 'react';\n\nimport { useInteractionBus } from '../../core/context/InteractionContext';\nimport type { PermissionNode } from '../../types/nodes';\nimport type { PermissionUiMode } from '../sessionViewOptions';\n\nexport interface ToolPermissionWaitProps {\n permission: PermissionNode;\n mode: PermissionUiMode;\n}\n\nexport function ToolPermissionWait({ permission, mode }: ToolPermissionWaitProps) {\n const bus = useInteractionBus();\n const [resolvedLocally, setResolvedLocally] = useState(false);\n\n if (permission.status !== 'pending' || resolvedLocally) return null;\n\n const showActions = mode === 'inline' || mode === 'both';\n\n const onAllow = () => {\n void bus.resolvePermission({ requestId: permission.requestId, allow: true });\n setResolvedLocally(true);\n };\n\n const onDeny = () => {\n void bus.resolvePermission({ requestId: permission.requestId, allow: false });\n setResolvedLocally(true);\n };\n\n return (\n <div className=\"lax-tool-shell__permission-wait\" role=\"status\">\n <div className=\"lax-tool-shell__permission-wait-text\">\n Waiting for permission…\n </div>\n {permission.message ? (\n <div className=\"lax-tool-shell__permission-wait-detail\">{permission.message}</div>\n ) : null}\n {showActions ? (\n <div className=\"lax-tool-shell__permission-actions\">\n <button type=\"button\" className=\"lax-permission-card__allow\" onClick={onAllow}>\n Allow\n </button>\n <button type=\"button\" className=\"lax-permission-card__deny\" onClick={onDeny}>\n Deny\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * ToolCallShell.tsx — 工具卡片外壳\n *\n * 职责:\n * 状态圆点、标题、progress、error 边框;不含工具语义。\n *\n * 链路位置:\n * ToolCallCard 外层布局。\n *\n * 当前裁剪范围:\n * T4.6 内嵌 permission 等待态;Grouped 紧凑布局 variant。\n *\n * 对齐参考:\n * CLI base.py 状态圆点 · CC AssistantToolUseMessage.tsx 外层 Box\n */\nimport type { ReactNode } from 'react';\n\nimport type { ToolCallNode } from '../../types/nodes';\nimport type { PermissionNode } from '../../types/nodes';\nimport type { PermissionUiMode } from '../sessionViewOptions';\nimport { ToolPermissionWait } from './ToolPermissionWait';\n\nexport interface ToolCallShellProps {\n status: ToolCallNode['status'];\n title: string;\n progress?: ToolCallNode['progress'];\n errorMessage?: string | null;\n layout?: 'default' | 'grouped';\n permissionWait?: PermissionNode;\n permissionUiMode?: PermissionUiMode;\n children?: ReactNode;\n}\n\nexport function ToolCallShell({\n status,\n title,\n progress,\n errorMessage,\n layout = 'default',\n permissionWait,\n permissionUiMode = 'standalone',\n children,\n}: ToolCallShellProps) {\n const bare = !title.trim();\n const waitingForPermission =\n permissionWait &&\n permissionUiMode !== 'standalone' &&\n (status === 'running' || status === 'failed');\n\n return (\n <div\n className={[\n 'lax-tool-card',\n 'lax-tool-shell',\n bare ? 'lax-tool-shell--bare' : '',\n layout === 'grouped' ? 'lax-tool-shell--grouped' : '',\n waitingForPermission ? 'lax-tool-shell--permission-wait' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n data-status={status}\n data-error-kind={\n errorMessage ? 'error' : waitingForPermission ? 'permission' : undefined\n }\n >\n {!bare ? (\n <div className=\"lax-tool-shell__header lax-tool-card__header\">\n <span\n className=\"lax-tool-shell__status-dot lax-tool-card__status-dot\"\n data-status={status}\n aria-hidden\n >\n ●{' '}\n </span>\n <span className=\"lax-tool-shell__title lax-tool-card__name\">{title}</span>\n </div>\n ) : null}\n\n {progress ? (\n <div className=\"lax-tool-shell__progress lax-tool-card__progress\">\n {progress.message ?? `${progress.current}/${progress.total}`}\n </div>\n ) : null}\n\n {waitingForPermission && permissionWait ? (\n <ToolPermissionWait permission={permissionWait} mode={permissionUiMode} />\n ) : null}\n\n {children}\n\n {errorMessage && status === 'failed' ? (\n <div className=\"lax-tool-card__error\" role=\"alert\">\n {errorMessage}\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs"]}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
extractLastToolInfoFromProgress,
|
|
16
16
|
formatExploreSummaryText,
|
|
17
17
|
formatThoughtDurationPrefix
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZR37OKV6.js";
|
|
19
19
|
|
|
20
20
|
// src/types/tree.ts
|
|
21
21
|
function createEmptyTree() {
|
|
@@ -975,6 +975,7 @@ function handleTextEnd(tree, event) {
|
|
|
975
975
|
}
|
|
976
976
|
function handleReasoningStart(tree, event, seq) {
|
|
977
977
|
reactivateSessionIfIdle(tree);
|
|
978
|
+
clearModelRetry(tree);
|
|
978
979
|
const id = `reasoning:${seq}`;
|
|
979
980
|
const roundId = `round-${seq}`;
|
|
980
981
|
const node = {
|
|
@@ -1120,6 +1121,7 @@ function maybeSynthesizeLeakedToolProgress(tree, options, params) {
|
|
|
1120
1121
|
}
|
|
1121
1122
|
function handleToolCall(tree, event, seq, options) {
|
|
1122
1123
|
reactivateSessionIfIdle(tree);
|
|
1124
|
+
clearModelRetry(tree);
|
|
1123
1125
|
const id = toolNodeId(tree, event);
|
|
1124
1126
|
const data = event.data;
|
|
1125
1127
|
const existing = tree.byId[id];
|
|
@@ -5248,35 +5250,25 @@ function GroupedSubline({
|
|
|
5248
5250
|
children: [
|
|
5249
5251
|
/* @__PURE__ */ jsxs8("div", { className: "lax-tool-group__subline", children: [
|
|
5250
5252
|
/* @__PURE__ */ jsx9("span", { className: "lax-tool-group__tree", "aria-hidden": true, children: treeChar }),
|
|
5251
|
-
/* @__PURE__ */
|
|
5252
|
-
|
|
5253
|
-
"
|
|
5254
|
-
|
|
5253
|
+
/* @__PURE__ */ jsxs8("span", { className: "lax-tool-group__subline-flow", children: [
|
|
5254
|
+
/* @__PURE__ */ jsx9("span", { className: "lax-tool-group__subline-title", children: subTitle }),
|
|
5255
|
+
status ? /* @__PURE__ */ jsxs8("span", { className: "lax-tool-group__subline-status", children: [
|
|
5256
|
+
" \xB7 ",
|
|
5257
|
+
status
|
|
5258
|
+
] }) : null,
|
|
5259
|
+
canExpand ? /* @__PURE__ */ jsx9(
|
|
5260
|
+
"button",
|
|
5261
|
+
{
|
|
5262
|
+
type: "button",
|
|
5263
|
+
className: "lax-tool-group__transcript-link",
|
|
5264
|
+
onClick: toggleExpanded,
|
|
5265
|
+
"aria-expanded": expanded,
|
|
5266
|
+
children: expanded ? "Hide transcript" : "Show transcript"
|
|
5267
|
+
}
|
|
5268
|
+
) : null
|
|
5255
5269
|
] })
|
|
5256
5270
|
] }),
|
|
5257
|
-
canExpand &&
|
|
5258
|
-
"button",
|
|
5259
|
-
{
|
|
5260
|
-
type: "button",
|
|
5261
|
-
className: "lax-tool-group__transcript-link",
|
|
5262
|
-
onClick: toggleExpanded,
|
|
5263
|
-
"aria-expanded": false,
|
|
5264
|
-
children: "Show transcript"
|
|
5265
|
-
}
|
|
5266
|
-
) : null,
|
|
5267
|
-
canExpand && expanded ? /* @__PURE__ */ jsxs8("div", { className: "lax-tool-group__transcript-panel", "data-testid": "lax-grouped-transcript", children: [
|
|
5268
|
-
hasTranscriptLane ? /* @__PURE__ */ jsx9(SubagentTranscriptBlock, { entries: transcript, dataSource: "transcript-lane" }) : /* @__PURE__ */ jsx9(AgentProgressLines, { entries: progress, mode: "full" }),
|
|
5269
|
-
/* @__PURE__ */ jsx9(
|
|
5270
|
-
"button",
|
|
5271
|
-
{
|
|
5272
|
-
type: "button",
|
|
5273
|
-
className: "lax-tool-group__transcript-link",
|
|
5274
|
-
onClick: toggleExpanded,
|
|
5275
|
-
"aria-expanded": true,
|
|
5276
|
-
children: "Hide transcript"
|
|
5277
|
-
}
|
|
5278
|
-
)
|
|
5279
|
-
] }) : null
|
|
5271
|
+
canExpand && expanded ? /* @__PURE__ */ jsx9("div", { className: "lax-tool-group__transcript-panel", "data-testid": "lax-grouped-transcript", children: hasTranscriptLane ? /* @__PURE__ */ jsx9(SubagentTranscriptBlock, { entries: transcript, dataSource: "transcript-lane" }) : /* @__PURE__ */ jsx9(AgentProgressLines, { entries: progress, mode: "full" }) }) : null
|
|
5280
5272
|
]
|
|
5281
5273
|
}
|
|
5282
5274
|
);
|
|
@@ -5715,4 +5707,4 @@ export {
|
|
|
5715
5707
|
VirtualTimeline,
|
|
5716
5708
|
SessionTimeline
|
|
5717
5709
|
};
|
|
5718
|
-
//# sourceMappingURL=chunk-
|
|
5710
|
+
//# sourceMappingURL=chunk-DJPNJBFL.js.map
|