langchain_agentx_stream_ui 0.6.4 → 0.6.8

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.
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { b as ToolDisplayProps, T as ToolBodyComponent } from './types-DAkw2VOv.js';
3
- import { T as ToolDisplayRegistry } from './sessionViewOptions-EIBugOkf.js';
2
+ import { b as ToolDisplayProps, T as ToolBodyComponent } from './types-kH4WQSM2.js';
3
+ import { T as ToolDisplayRegistry } from './sessionViewOptions-2Hv9BGeg.js';
4
4
 
5
5
  declare function DefaultToolBody({ result, bodyMode, onBodyModeChange, }: ToolDisplayProps): react_jsx_runtime.JSX.Element;
6
6
 
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { a as ToolBodyMode } from './types-DAkw2VOv.js';
2
+ import { a as ToolBodyMode } from './types-kH4WQSM2.js';
3
3
 
4
4
  declare const MAX_PREVIEW_LINES = 3;
5
5
  interface TruncatedContentProps {
@@ -928,13 +928,14 @@ function AgentToolBody({
928
928
  const transcriptLane = subagentTranscript ?? [];
929
929
  const bodyText = buildAgentBodyText(result?.display, result?.summary ?? "");
930
930
  const transcriptFallback = buildAgentTranscriptText(result?.display, progress);
931
- const showDoneSummary = status !== "running" && bodyText.length > 0;
932
- const doneFilesystemStatus = status !== "running" ? extractLastFilesystemStatusFromProgress(progress) : null;
931
+ const showDoneSummary = status === "done" && bodyText.length > 0;
932
+ const doneFilesystemStatus = status === "done" ? extractLastFilesystemStatusFromProgress(progress) : null;
933
933
  const showTranscriptLane = bodyMode === "full" && transcriptLane.length > 0;
934
934
  const showRunningProgress = status === "running" && progress.length > 0 && !showTranscriptLane;
935
935
  const showTranscriptFallback = bodyMode === "full" && !showTranscriptLane && transcriptFallback.length > 0;
936
936
  if (!showRunningProgress && !showDoneSummary && !doneFilesystemStatus && !showTranscriptLane && !showTranscriptFallback) {
937
- return /* @__PURE__ */ jsx3("div", { className: "lax-tool-body lax-tool-body--agent", children: /* @__PURE__ */ jsx3("div", { className: "lax-tool-body__block", "data-variant": "dim", children: /* @__PURE__ */ jsx3("pre", { className: "lax-tool-body__text", children: "(running)" }) }) });
937
+ const idleLabel = status === "failed" ? "(stopped)" : "(running)";
938
+ return /* @__PURE__ */ jsx3("div", { className: "lax-tool-body lax-tool-body--agent", children: /* @__PURE__ */ jsx3("div", { className: "lax-tool-body__block", "data-variant": "dim", children: /* @__PURE__ */ jsx3("pre", { className: "lax-tool-body__text", children: idleLabel }) }) });
938
939
  }
939
940
  return /* @__PURE__ */ jsxs3("div", { className: "lax-tool-body lax-tool-body--agent", children: [
940
941
  showRunningProgress ? /* @__PURE__ */ jsx3(
@@ -1618,4 +1619,4 @@ export {
1618
1619
  ToolDisplayRegistry,
1619
1620
  createDefaultToolRegistry
1620
1621
  };
1621
- //# sourceMappingURL=chunk-GYFC2DI7.js.map
1622
+ //# sourceMappingURL=chunk-7XSQYG3X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/view/tools/toolNames.ts","../src/core/projection/exploreSummary.ts","../src/view/tools/displayRecord.ts","../src/view/tools/edit/formatEditTitle.ts","../src/view/tools/write/formatWriteTitle.ts","../src/view/tools/presentation/planPaths.ts","../src/view/tools/presentation/agentProgressRenderer.ts","../src/view/tools/presentation/agentHelpers.ts","../src/view/tools/agent/AgentProgressLines.tsx","../src/view/tools/presentation/subagentTranscriptRenderer.ts","../src/view/tools/agent/SubagentTranscriptBlock.tsx","../src/view/tools/agent/AgentToolBody.tsx","../src/view/tools/presentation/askUserHelpers.ts","../src/view/tools/ask_user_question/AskUserQuestionToolBody.tsx","../src/view/tools/bash/BashToolBody.tsx","../src/view/tools/edit/EditToolBody.tsx","../src/view/tools/presentation/toolHints.ts","../src/view/tools/presentation/ToolResultHints.tsx","../src/view/tools/glob/GlobToolBody.tsx","../src/view/tools/grep/GrepToolBody.tsx","../src/view/tools/read/ReadToolBody.tsx","../src/view/tools/skill/SkillToolBody.tsx","../src/view/tools/webfetch/WebFetchToolBody.tsx","../src/view/tools/websearch/WebSearchToolBody.tsx","../src/view/tools/write/WriteToolBody.tsx","../src/view/tools/registry.ts"],"sourcesContent":["/**\r\n * toolNames.ts — CC PascalCase 工具名 SSOT(对齐 SDK registry_names.py)\r\n *\r\n * 职责:Stream UI widget / projection / reducer 消费的工具名字面量唯一来源。\r\n * 链路位置:registry.ts、classify.ts、memoryPaths.ts、reducer.ts。\r\n * 当前裁剪范围:无 legacy alias、无 *Tool 后缀变体、无 REMOVED 双轨表。\r\n */\r\n\r\nexport const Read = 'Read';\r\nexport const Write = 'Write';\r\nexport const Edit = 'Edit';\r\nexport const Glob = 'Glob';\r\nexport const Grep = 'Grep';\r\nexport const Bash = 'Bash';\r\nexport const Skill = 'Skill';\r\nexport const Agent = 'Agent';\r\nexport const AskUserQuestion = 'AskUserQuestion';\r\nexport const WebSearch = 'WebSearch';\r\nexport const WebFetch = 'WebFetch';\r\n\r\nexport const TaskCreate = 'TaskCreate';\r\nexport const TaskUpdate = 'TaskUpdate';\r\nexport const TaskList = 'TaskList';\r\nexport const TaskGet = 'TaskGet';\r\nexport const TaskOutput = 'TaskOutput';\r\nexport const TaskStop = 'TaskStop';\r\n\r\n/** SSE 抑制 + Timeline hidden:SDK Task* 内部工具(仅 CC 注册名) */\r\nexport const SILENT_TASK_TOOL_NAMES: readonly string[] = [\r\n TaskCreate,\r\n TaskGet,\r\n TaskList,\r\n TaskUpdate,\r\n];\r\n\r\n/** reducer 不渲染的内部工具(= SILENT_TASK + TaskOutput/TaskStop) */\r\nexport const INTERNAL_TOOL_NAMES: ReadonlySet<string> = new Set([\r\n ...SILENT_TASK_TOOL_NAMES,\r\n TaskOutput,\r\n TaskStop,\r\n]);\r\n\r\n/** CC 核心文件/Shell 工具名(门禁:src 中禁止 legacy 小写 alias) */\r\nexport const CC_CORE_TOOL_NAMES: readonly string[] = [\r\n Read,\r\n Write,\r\n Edit,\r\n Glob,\r\n Grep,\r\n Bash,\r\n Skill,\r\n Agent,\r\n AskUserQuestion,\r\n WebSearch,\r\n WebFetch,\r\n];\r\n\r\n/** 单测负向样本:legacy 名不得出现在 src(由 TN-006 guard 扫描) */\r\nexport const LEGACY_TOOL_NAME_SAMPLES: readonly string[] = [\r\n 'read',\r\n 'read_file',\r\n 'write',\r\n 'edit',\r\n 'glob',\r\n 'grep',\r\n 'bash',\r\n 'skill',\r\n 'agent',\r\n 'Task',\r\n 'search',\r\n 'list',\r\n 'batch_edit',\r\n];\r\n","/**\n * exploreSummary.ts — collapsed_explore 摘要文案(对齐 CC / CLI)\n *\n * 职责:\n * 生成与 CC CollapsedReadSearchContent / getSearchReadSummaryText 一致的 plain 摘要。\n *\n * 链路位置:\n * ExploreCollapseAccumulator → payload.summaryText。\n *\n * 当前裁剪范围:\n * 仅 plain text;Rich/bold 渲染在 CollapsedExploreNode(Phase 3)。\n */\n\nexport interface ExploreSummaryCounts {\n searchCount: number;\n readCount: number;\n listCount: number;\n bashCount: number;\n memorySearchCount: number;\n memoryReadCount: number;\n memoryWriteCount: number;\n relevantRecallCount: number;\n gitOpBashCount: number;\n mcpCallCount: number;\n}\n\ninterface SummaryPart {\n verb: string;\n count: number | null;\n suffix: string;\n}\n\nfunction memoryReadTotal(counts: ExploreSummaryCounts): number {\n if (counts.memoryReadCount === 0 && counts.relevantRecallCount > 0) {\n return counts.relevantRecallCount;\n }\n return counts.memoryReadCount;\n}\n\nfunction tenseVerb(options: {\n active: boolean;\n isFirst: boolean;\n presentCap: string;\n presentLower: string;\n pastCap: string;\n pastLower: string;\n}): string {\n if (options.active) {\n return options.isFirst ? options.presentCap : options.presentLower;\n }\n return options.isFirst ? options.pastCap : options.pastLower;\n}\n\nfunction exploreSummaryParts(\n counts: ExploreSummaryCounts,\n active: boolean,\n continuingSentence = false,\n): SummaryPart[] {\n const parts: SummaryPart[] = [];\n let isFirst = !continuingSentence;\n\n // Memory operations first (对齐 CC/CLI)\n const memRead = memoryReadTotal(counts);\n if (memRead > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Recalling',\n presentLower: 'recalling',\n pastCap: 'Recalled',\n pastLower: 'recalled',\n }),\n count: memRead,\n suffix: memRead === 1 ? 'memory' : 'memories',\n });\n isFirst = false;\n }\n\n if (counts.memorySearchCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Searching',\n presentLower: 'searching',\n pastCap: 'Searched',\n pastLower: 'searched',\n }),\n count: null,\n suffix: 'memories',\n });\n isFirst = false;\n }\n\n if (counts.memoryWriteCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Writing',\n presentLower: 'writing',\n pastCap: 'Wrote',\n pastLower: 'wrote',\n }),\n count: counts.memoryWriteCount,\n suffix: counts.memoryWriteCount === 1 ? 'memory' : 'memories',\n });\n isFirst = false;\n }\n\n // Non-memory operations\n if (counts.searchCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Searching for',\n presentLower: 'searching for',\n pastCap: 'Searched for',\n pastLower: 'searched for',\n }),\n count: counts.searchCount,\n suffix: counts.searchCount === 1 ? 'pattern' : 'patterns',\n });\n isFirst = false;\n }\n\n if (counts.readCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Reading',\n presentLower: 'reading',\n pastCap: 'Read',\n pastLower: 'read',\n }),\n count: counts.readCount,\n suffix: counts.readCount === 1 ? 'file' : 'files',\n });\n isFirst = false;\n }\n\n if (counts.listCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Listing',\n presentLower: 'listing',\n pastCap: 'Listed',\n pastLower: 'listed',\n }),\n count: counts.listCount,\n suffix: counts.listCount === 1 ? 'directory' : 'directories',\n });\n isFirst = false;\n }\n\n if (counts.bashCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Running',\n presentLower: 'running',\n pastCap: 'Ran',\n pastLower: 'ran',\n }),\n count: counts.bashCount,\n suffix: counts.bashCount === 1 ? 'bash command' : 'bash commands',\n });\n isFirst = false;\n }\n\n if (counts.gitOpBashCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Running',\n presentLower: 'running',\n pastCap: 'Ran',\n pastLower: 'ran',\n }),\n count: counts.gitOpBashCount,\n suffix: counts.gitOpBashCount === 1 ? 'git command' : 'git commands',\n });\n isFirst = false;\n }\n\n if (counts.mcpCallCount > 0) {\n parts.push({\n verb: tenseVerb({\n active,\n isFirst,\n presentCap: 'Querying',\n presentLower: 'querying',\n pastCap: 'Queried',\n pastLower: 'queried',\n }),\n count: counts.mcpCallCount,\n suffix: counts.mcpCallCount === 1 ? 'MCP tool' : 'MCP tools',\n });\n isFirst = false;\n }\n\n return parts;\n}\n\nfunction partPlainText(part: SummaryPart): string {\n if (part.count !== null) {\n return `${part.verb} ${part.count} ${part.suffix}`.trim();\n }\n return `${part.verb} ${part.suffix}`.trim();\n}\n\nexport function formatExploreSummaryText(\n counts: ExploreSummaryCounts,\n options: {\n active: boolean;\n prefix?: string;\n joiner?: string;\n /** Thought 前缀已占用句首时,explore 动词用小写续写 */\n continuingSentence?: boolean;\n } = { active: false },\n): string | null {\n const parts = exploreSummaryParts(\n counts,\n options.active,\n options.continuingSentence ?? false,\n );\n if (parts.length === 0) return null;\n const joiner = options.joiner ?? ', ';\n let text = parts.map(partPlainText).join(joiner);\n if (options.active) {\n text = `${text}…`;\n }\n if (options.prefix) {\n text = options.prefix + text;\n }\n return text;\n}\n\n/** CC 合并行前缀:Thought for 8s, */\nexport function formatThoughtDurationPrefix(seconds: number): string {\n const rounded = Math.max(1, Math.round(seconds));\n return `Thought for ${rounded}s, `;\n}\n\nexport function exploreCountsHasActivity(counts: ExploreSummaryCounts): boolean {\n return (\n counts.searchCount > 0 ||\n counts.readCount > 0 ||\n counts.listCount > 0 ||\n counts.bashCount > 0 ||\n counts.memorySearchCount > 0 ||\n counts.memoryReadCount > 0 ||\n counts.memoryWriteCount > 0 ||\n counts.relevantRecallCount > 0 ||\n counts.gitOpBashCount > 0 ||\n counts.mcpCallCount > 0\n );\n}\n","/**\r\n * displayRecord.ts — 从 input / display 安全取字段\r\n */\r\n\r\nexport function asDisplayRecord(\r\n display: unknown,\r\n): Record<string, unknown> | null {\r\n if (display != null && typeof display === 'object' && !Array.isArray(display)) {\r\n return display as Record<string, unknown>;\r\n }\r\n return null;\r\n}\r\n\r\nexport function asInputRecord(input: unknown): Record<string, unknown> {\r\n if (input != null && typeof input === 'object' && !Array.isArray(input)) {\r\n return input as Record<string, unknown>;\r\n }\r\n return {};\r\n}\r\n\r\nexport function strField(record: Record<string, unknown>, key: string): string {\r\n const value = record[key];\r\n return value == null ? '' : String(value).trim();\r\n}\r\n\r\nexport function numField(record: Record<string, unknown>, key: string): number | undefined {\r\n const value = record[key];\r\n if (typeof value === 'number' && Number.isFinite(value)) return value;\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n const n = Number(value);\r\n if (Number.isFinite(n)) return n;\r\n }\r\n return undefined;\r\n}\r\n","/**\r\n * formatEditTitle.ts — edit 工具标题(Update / Create)\r\n *\r\n * 对齐参考:CLI widgets/tools/edit/widget.py format_title\r\n */\r\nimport { asInputRecord, strField } from '../displayRecord';\r\nimport { displayPath } from '../presentation/paths';\r\n\r\nexport function editAction(input: unknown): 'Update' | 'Create' {\r\n const inp = asInputRecord(input);\r\n if (Array.isArray(inp.edits) && inp.edits.length > 0) return 'Update';\r\n if ('old_string' in inp && inp.old_string === '') return 'Create';\r\n return 'Update';\r\n}\r\n\r\nexport function formatEditTitle(\r\n input: unknown,\r\n display: unknown,\r\n _summary?: string | null,\r\n): string {\r\n const inp = asInputRecord(input);\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 path = displayPath(\r\n strField(d ?? {}, 'file_path') || strField(inp, 'file_path'),\r\n );\r\n const action = editAction(inp);\r\n if (!path) return action;\r\n return `${action}(${path})`;\r\n}\r\n","/**\r\n * formatWriteTitle.ts — write 工具标题\r\n *\r\n * 对齐参考:CLI widgets/tools/write/widget.py format_title\r\n */\r\nimport { asDisplayRecord, asInputRecord, strField } from '../displayRecord';\r\nimport { displayPath } from '../presentation/paths';\r\n\r\nexport function formatWriteTitle(\r\n input: unknown,\r\n display: unknown,\r\n _summary?: string | null,\r\n): string {\r\n const inp = asInputRecord(input);\r\n const d = asDisplayRecord(display);\r\n const path = displayPath(\r\n strField(d ?? {}, 'file_path') || strField(inp, 'file_path'),\r\n );\r\n if (!path) return 'Write';\r\n return `Write(${path})`;\r\n}\r\n","/**\n * planPaths.ts — CC plan 文件路径判定(对齐 FileWriteTool/FileEditTool userFacingName)\n *\n * 链路:formatSubagentToolProgressLine Write/Edit → Updated plan\n */\nimport { displayPath } from './paths';\n\nconst PLAN_PATH_MARKERS = ['/.claude/plans/', '.claude/plans/'] as const;\n\nexport function isPlanFilePath(filePath: string): boolean {\n const normalized = displayPath(filePath.trim());\n if (!normalized) return false;\n return PLAN_PATH_MARKERS.some((marker) => normalized.includes(marker));\n}\n","/**\n * agentProgressRenderer.ts — Agent 子工具 progress 行(对齐 CLI progress_renderer.py)\n */\nimport {\n formatExploreSummaryText,\n type ExploreSummaryCounts,\n} from '../../../core/projection/exploreSummary';\nimport type { SubagentProgressEntry } from '../../../types/nodes';\nimport { formatEditTitle } from '../edit/formatEditTitle';\nimport { formatWriteTitle } from '../write/formatWriteTitle';\nimport { isPlanFilePath } from './planPaths';\nimport { truncateCommand } from './bashHelpers';\n\nexport const AGENT_PROGRESS_GUTTER = ' ⎿ ';\n/**\n * 与 GUTTER 同「语义」的挂接行占位(结果 / +N more)。\n * 视觉对齐靠 CSS `--lax-hang-gutter-width` 固定列宽,勿假设 ⎿ ≈ 1 个空格宽。\n */\nexport const AGENT_PROGRESS_INDENT = ' ';\n\nfunction truncatePreview(text: string, maxChars = 80): string {\n const trimmed = text.trim();\n if (trimmed.length <= maxChars) return trimmed;\n return `${trimmed.slice(0, maxChars)}…`;\n}\n\nconst READ_TOOLS = new Set(['Read']);\nconst SEARCH_TOOLS = new Set(['Glob', 'Grep', 'SemanticSearch', 'Search']);\n\nexport interface ProcessedProgressLine {\n text: string;\n toolUseCount: number;\n}\n\nfunction toolInputRecord(input: unknown): Record<string, unknown> {\n if (input != null && typeof input === 'object' && !Array.isArray(input)) {\n return input as Record<string, unknown>;\n }\n return {};\n}\n\n/** 对齐 CLI format_subagent_tool_progress_line:Bash(cmd) / Read(path) / Glob(pattern)。 */\nexport function formatSubagentToolProgressLine(\n toolName: string,\n options: { summary?: string; toolInput?: unknown } = {},\n): string {\n const name = toolName.trim();\n const inp = toolInputRecord(options.toolInput);\n\n if (name === 'Bash') {\n const command = String(inp.command ?? inp.description ?? '').trim();\n if (command) return `Bash(${truncateCommand(command)})`;\n }\n if (name === 'Read') {\n const path = String(inp.path ?? inp.file_path ?? '').trim();\n if (path) return `Read(${truncatePreview(path, 60)})`;\n }\n if (name === 'Glob' || name === 'Grep') {\n const pattern = String(inp.pattern ?? inp.glob_pattern ?? '').trim();\n const path = String(inp.path ?? inp.glob ?? '').trim();\n if (pattern && path) {\n return `${name}(${truncatePreview(pattern, 40)}, ${truncatePreview(path, 40)})`;\n }\n if (pattern) return `${name}(${truncatePreview(pattern, 60)})`;\n if (path) return `${name}(${truncatePreview(path, 60)})`;\n }\n if (name === 'Write') {\n const path = String(inp.file_path ?? inp.path ?? '').trim();\n if (path && isPlanFilePath(path)) return 'Updated plan';\n const title = formatWriteTitle(inp, null);\n if (title !== 'Write') return title;\n }\n if (name === 'Edit') {\n const path = String(inp.file_path ?? inp.path ?? '').trim();\n if (path && isPlanFilePath(path)) return 'Updated plan';\n const title = formatEditTitle(inp, null);\n if (title !== 'Edit') return title;\n }\n\n const summary = (options.summary ?? '').trim();\n const callingLower = `calling ${name.toLowerCase()}`;\n if (summary && summary.toLowerCase() !== callingLower) {\n return summary;\n }\n return name;\n}\n\nexport function formatSubagentProgressLine(entry: SubagentProgressEntry): string {\n return formatSubagentToolProgressLine(entry.toolName, {\n summary: entry.summary,\n toolInput: entry.toolInput,\n });\n}\n\nfunction isSubagentProgressEntry(value: unknown): value is SubagentProgressEntry {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) return false;\n const row = value as SubagentProgressEntry;\n return typeof row.toolName === 'string' && row.toolName.length > 0;\n}\n\nfunction readProgressField<T>(\n row: Record<string, unknown>,\n camel: string,\n snake: string,\n): T | undefined {\n const camelValue = row[camel];\n if (camelValue !== undefined && camelValue !== null) return camelValue as T;\n const snakeValue = row[snake];\n if (snakeValue !== undefined && snakeValue !== null) return snakeValue as T;\n return undefined;\n}\n\n/** grouped_tool_use payload 内 subagent_progress → SubagentProgressEntry[] */\nexport function coerceSubagentProgressEntries(raw: unknown): SubagentProgressEntry[] {\n if (!Array.isArray(raw)) return [];\n const entries: SubagentProgressEntry[] = [];\n for (const item of raw) {\n if (item == null || typeof item !== 'object' || Array.isArray(item)) continue;\n const row = item as Record<string, unknown>;\n const toolName = readProgressField<string>(row, 'toolName', 'tool_name');\n const agentId = readProgressField<string>(row, 'agentId', 'agent_id');\n if (!toolName || !agentId) continue;\n const stepRaw = readProgressField<number>(row, 'step', 'step') ?? 0;\n const statusRaw = readProgressField<string>(row, 'status', 'status') ?? 'completed';\n const status: SubagentProgressEntry['status'] =\n statusRaw === 'running'\n ? 'running'\n : statusRaw === 'error' || statusRaw === 'failed'\n ? 'error'\n : 'completed';\n entries.push({\n agentId,\n subagentType: readProgressField<string>(row, 'subagentType', 'subagent_type'),\n step: stepRaw,\n toolName,\n summary: readProgressField<string>(row, 'summary', 'summary') ?? toolName,\n status,\n toolInput: readProgressField<unknown>(row, 'toolInput', 'tool_input'),\n childToolCallId: readProgressField<string>(row, 'childToolCallId', 'child_tool_call_id'),\n });\n }\n return entries.sort((a, b) => a.step - b.step || a.toolName.localeCompare(b.toolName));\n}\n\n/** GroupedToolCallRow pending 态:Write(path) → Write: path(对齐 CC extractLastToolInfo 冒号格式)。 */\nexport function formatGroupedProgressStatus(entry: SubagentProgressEntry): string {\n const paren = formatSubagentProgressLine(entry);\n const m = /^(Write|Update|Create)\\((.+)\\)$/.exec(paren);\n if (m) return `${m[1]}: ${m[2]}`;\n return paren;\n}\n\n/** 对齐 CLI extractLastToolInfoFromProgressEntries:分组子行 pending 态展示。 */\nexport function extractLastToolInfoFromProgress(\n progress: unknown,\n): string | null {\n if (!Array.isArray(progress) || progress.length === 0) return null;\n for (let index = progress.length - 1; index >= 0; index -= 1) {\n const entry = progress[index];\n if (!isSubagentProgressEntry(entry)) continue;\n const line = formatGroupedProgressStatus(entry);\n if (line) return line;\n }\n return null;\n}\n\nconst FILESYSTEM_PROGRESS_TOOLS = new Set(['Write', 'Edit']);\n\n/** P2:done 态保留最后一行 Write/Edit/Plan filesystem status(冒号格式)。 */\nexport function extractLastFilesystemStatusFromProgress(\n progress: unknown,\n): string | null {\n if (!Array.isArray(progress) || progress.length === 0) return null;\n for (let index = progress.length - 1; index >= 0; index -= 1) {\n const entry = progress[index];\n if (!isSubagentProgressEntry(entry)) continue;\n if (!FILESYSTEM_PROGRESS_TOOLS.has(entry.toolName)) continue;\n const line = formatGroupedProgressStatus(entry);\n if (line === 'Write' || line === 'Edit' || line === 'Update' || line === 'Create') {\n continue;\n }\n return line;\n }\n return null;\n}\n\nfunction emptyExploreCounts(): ExploreSummaryCounts {\n return {\n searchCount: 0,\n readCount: 0,\n listCount: 0,\n bashCount: 0,\n memorySearchCount: 0,\n memoryReadCount: 0,\n memoryWriteCount: 0,\n relevantRecallCount: 0,\n gitOpBashCount: 0,\n mcpCallCount: 0,\n };\n}\n\n/** TodoWrite / Task* 不进子 Agent progress(对齐 CC renderToolUseMessage → null)。 */\nexport function isSilentTaskTool(toolName: string): boolean {\n const name = toolName.trim();\n if (!name) return false;\n if (name === 'TodoWrite') return true;\n return name.startsWith('Task');\n}\n\nfunction isExploreTool(toolName: string): boolean {\n return READ_TOOLS.has(toolName) || SEARCH_TOOLS.has(toolName);\n}\n\nfunction incrementExploreCount(counts: ExploreSummaryCounts, toolName: string): void {\n if (READ_TOOLS.has(toolName)) {\n counts.readCount += 1;\n return;\n }\n if (SEARCH_TOOLS.has(toolName)) {\n counts.searchCount += 1;\n }\n}\n\n/** P1:仅 searchCount + readCount,复用 exploreSummary 时态 SSOT。 */\nexport function buildExploreSummaryLine(\n counts: Pick<ExploreSummaryCounts, 'searchCount' | 'readCount'>,\n options: { active: boolean },\n): string {\n return (\n formatExploreSummaryText(\n { ...emptyExploreCounts(), ...counts },\n { active: options.active },\n ) ?? ''\n );\n}\n\n/** D34 §4.3:尾部连续 explore 块跨 Read/Glob/Grep 合并;Write/Edit/Bash 打断。 */\nfunction processProgressEntries(\n entries: SubagentProgressEntry[],\n isRunning: boolean,\n): ProcessedProgressLine[] {\n const lines: ProcessedProgressLine[] = [];\n let i = 0;\n\n while (i < entries.length) {\n const entry = entries[i]!;\n if (isSilentTaskTool(entry.toolName)) {\n i += 1;\n continue;\n }\n\n if (isExploreTool(entry.toolName)) {\n let j = i;\n const counts = emptyExploreCounts();\n while (j < entries.length && isExploreTool(entries[j]!.toolName)) {\n incrementExploreCount(counts, entries[j]!.toolName);\n j += 1;\n }\n const blockLen = j - i;\n if (blockLen >= 2) {\n lines.push({\n text: buildExploreSummaryLine(counts, { active: isRunning }),\n toolUseCount: blockLen,\n });\n } else {\n lines.push({\n text: formatSubagentProgressLine(entries[i]!),\n toolUseCount: 1,\n });\n }\n i = j;\n continue;\n }\n\n lines.push({\n text: formatSubagentProgressLine(entry),\n toolUseCount: 1,\n });\n i += 1;\n }\n\n return lines;\n}\n\nexport function processAgentProgressLines(\n entries: SubagentProgressEntry[],\n options: { isRunning: boolean; maxVisible: number },\n): { visible: ProcessedProgressLine[]; hiddenToolUseCount: number } {\n const processed = processProgressEntries(entries, options.isRunning);\n if (options.maxVisible >= processed.length) {\n return { visible: processed, hiddenToolUseCount: 0 };\n }\n const visible = processed.slice(-options.maxVisible);\n const hidden = processed.slice(0, processed.length - options.maxVisible);\n const hiddenToolUseCount = hidden.reduce((sum, line) => sum + line.toolUseCount, 0);\n return { visible, hiddenToolUseCount };\n}\n","/**\r\n * agentHelpers.ts — Agent 标题与完成摘要\r\n *\r\n * 对齐参考:CLI helpers.format_agent_title · parse_agent_done_summary\r\n */\r\nimport { truncateLines } from './searchHelpers';\r\nimport { formatSubagentToolProgressLine } from './agentProgressRenderer';\r\n\r\nconst DONE_LINE_RE = /Done \\((.+?)\\)/i;\r\nconst AGENT_STEPS_RE = /(\\d+)\\s+tool uses?/i;\r\nexport const AGENT_MAX_BODY_LINES = 25;\r\nexport const AGENT_PROGRESS_TAIL_LINES = 3;\r\n\r\nexport function truncatePreview(text: string, maxChars = 80): string {\r\n const trimmed = text.trim();\r\n if (trimmed.length <= maxChars) return trimmed;\r\n return `${trimmed.slice(0, maxChars)}…`;\r\n}\r\n\r\nexport function formatAgentTitle(input: unknown, display: 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 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 const merged = { ...inp };\r\n if (d?.subagent_type) merged.subagent_type = d.subagent_type;\r\n if (d?.description) merged.description = d.description;\r\n\r\n const subagent = String(merged.subagent_type ?? 'general-purpose').trim();\r\n const desc = String(merged.description ?? merged.prompt ?? '').trim();\r\n\r\n let title = desc ? `${subagent}(${truncatePreview(desc)})` : subagent;\r\n\r\n const model = merged.model;\r\n if (model) {\r\n const modelStr = String(model).trim();\r\n if (modelStr) title = `${title} ${modelStr}`;\r\n }\r\n\r\n return title;\r\n}\r\n\r\nexport function parseAgentDoneSummary(output: string): string | null {\r\n const text = output.trim();\r\n if (!text) return null;\r\n\r\n const doneMatch = text.match(DONE_LINE_RE);\r\n if (doneMatch) return `Done (${doneMatch[1].trim()})`;\r\n\r\n const stepsMatch = text.match(AGENT_STEPS_RE);\r\n if (stepsMatch) return `Done (${stepsMatch[1]} tool uses)`;\r\n\r\n const first = text.split('\\n', 1)[0]?.trim() ?? '';\r\n if (first.toLowerCase().startsWith('done')) return first;\r\n\r\n return null;\r\n}\r\n\r\nexport function buildAgentBodyText(display: unknown, summary: string): 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\r\n let done: string | null = null;\r\n if (d?.total_steps != null && d.status === 'completed') {\r\n done = `Done (${d.total_steps} tool uses)`;\r\n } else {\r\n done = parseAgentDoneSummary(summary);\r\n }\r\n\r\n if (done) {\r\n let rest = summary.trim();\r\n if (rest.startsWith(done)) {\r\n rest = rest.slice(done.length).trimStart();\r\n }\r\n const parts = [done];\r\n if (rest) {\r\n const { text: truncated, truncated: was } = truncateLines(\r\n rest,\r\n AGENT_MAX_BODY_LINES,\r\n );\r\n parts.push(was ? `${truncated}\\n… 超过 ${AGENT_MAX_BODY_LINES} 行,已截断` : truncated);\r\n }\r\n return parts.join('\\n');\r\n }\r\n\r\n const text = summary.trim();\r\n if (!text) return '(done)';\r\n\r\n const { text: truncated, truncated: was } = truncateLines(text, AGENT_MAX_BODY_LINES);\r\n return was ? `${truncated}\\n… 超过 ${AGENT_MAX_BODY_LINES} 行,已截断` : truncated;\r\n}\r\n\r\nexport function formatSubagentProgressLine(entry: {\r\n toolName: string;\r\n summary: string;\r\n status: string;\r\n toolInput?: unknown;\r\n}): string {\r\n return formatSubagentToolProgressLine(entry.toolName, {\r\n summary: entry.summary,\r\n toolInput: entry.toolInput,\r\n });\r\n}\r\n\r\n/** 完成后展开 transcript:优先 display.tool_calls,否则用 reducer 积累的 progress。 */\r\nexport function buildAgentTranscriptText(\r\n display: unknown,\r\n subagentProgress?: { toolName: string; summary: string; status: 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 toolCalls = d?.tool_calls;\r\n if (Array.isArray(toolCalls) && toolCalls.length > 0) {\r\n return toolCalls\r\n .map((row) => {\r\n const item = row as Record<string, unknown>;\r\n const name = String(item.tool_name ?? 'tool');\r\n const summary = String(item.summary ?? '').trim();\r\n return summary ? `${name}: ${summary}` : name;\r\n })\r\n .join('\\n');\r\n }\r\n if (subagentProgress?.length) {\r\n return subagentProgress.map(formatSubagentProgressLine).join('\\n');\r\n }\r\n return '';\r\n}\r\n","/**\n * AgentProgressLines.tsx — Agent 子工具 progress 折叠行\n *\n * 对齐 CLI AgentProgressLineRenderer · CC AgentTool/UI.tsx renderToolUseProgressMessage\n * 挂接缩进:调用行 GUTTER;+N more 为挂接行用 INDENT(无第二层 ⎿)\n */\nimport {\n AGENT_PROGRESS_GUTTER,\n AGENT_PROGRESS_INDENT,\n processAgentProgressLines,\n} from '../presentation/agentProgressRenderer';\nimport { AGENT_PROGRESS_TAIL_LINES } from '../presentation/agentHelpers';\nimport type { SubagentProgressEntry } from '../../../types/nodes';\nimport type { ToolBodyMode } from '../types';\n\nexport interface AgentProgressLinesProps {\n entries: SubagentProgressEntry[];\n mode: ToolBodyMode;\n maxVisible?: number;\n onExpand?: () => void;\n}\n\nexport function AgentProgressLines({\n entries,\n mode,\n maxVisible = AGENT_PROGRESS_TAIL_LINES,\n onExpand,\n}: AgentProgressLinesProps) {\n if (entries.length === 0) return null;\n\n const isRunning = entries.some((e) => e.status === 'running');\n const limit = mode === 'full' ? entries.length : maxVisible;\n const { visible, hiddenToolUseCount } = processAgentProgressLines(entries, {\n isRunning,\n maxVisible: limit,\n });\n\n return (\n <div className=\"lax-agent-progress\" data-testid=\"lax-agent-progress\">\n {visible.map((line, index) => (\n <div\n key={`${index}:${line.text}`}\n className=\"lax-agent-progress__line\"\n >\n <span className=\"lax-agent-progress__gutter\" aria-hidden>\n {AGENT_PROGRESS_GUTTER}\n </span>\n <span className=\"lax-agent-progress__text\">{line.text}</span>\n </div>\n ))}\n {hiddenToolUseCount > 0 && mode !== 'full' ? (\n <div className=\"lax-agent-progress__line lax-agent-progress__line--more\">\n <span className=\"lax-agent-progress__gutter\" aria-hidden>\n {AGENT_PROGRESS_INDENT}\n </span>\n <button\n type=\"button\"\n className=\"lax-agent-progress__more\"\n onClick={onExpand}\n >\n +{hiddenToolUseCount} more tool {hiddenToolUseCount === 1 ? 'use' : 'uses'}\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * subagentTranscriptRenderer.ts — transcript lane 行渲染(方案 B)\n *\n * 调用行:Read(path) / Write(path) …\n * 结果行:condensed 摘要(Read N lines / File created / Error:…),\n * 嵌套缩进、不再套第二层 ⎿(对齐 CC MessageResponse 嵌套规则)\n */\nimport type { SubagentTranscriptEntry } from '../../../types/nodes';\nimport { displayPath } from './paths';\nimport { truncatePreview } from './agentHelpers';\nimport { formatSubagentToolProgressLine } from './agentProgressRenderer';\nimport { isPlanFilePath } from './planPaths';\n\nexport type TranscriptLineKind = 'call' | 'result';\n\nexport interface TranscriptRenderLine {\n kind: TranscriptLineKind;\n text: string;\n variant?: 'error' | 'dim' | 'default';\n}\n\nfunction toolCallsFromAssistant(message: Record<string, unknown>): Record<string, unknown>[] {\n const raw = message.tool_calls;\n if (!Array.isArray(raw)) return [];\n return raw.filter(\n (item): item is Record<string, unknown> =>\n item != null && typeof item === 'object' && !Array.isArray(item),\n );\n}\n\nfunction toolInputFromCall(call: Record<string, unknown>): Record<string, unknown> | null {\n const args = call.args;\n if (args != null && typeof args === 'object' && !Array.isArray(args)) {\n return args as Record<string, unknown>;\n }\n const input = call.input;\n if (input != null && typeof input === 'object' && !Array.isArray(input)) {\n return input as Record<string, unknown>;\n }\n return null;\n}\n\n/** 绝对路径 → 父目录/文件名(过长才截)。 */\nexport function shortenTranscriptPath(filePath: string, max = 52): string {\n const normalized = displayPath(filePath);\n if (!normalized) return '';\n if (normalized.length <= max) return normalized;\n const parts = normalized.split('/').filter(Boolean);\n if (parts.length >= 2) {\n const tail = `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;\n if (tail.length + 2 <= max) return `…/${tail}`;\n }\n return truncatePreview(normalized, max);\n}\n\nfunction withShortenedPaths(\n toolName: string,\n toolInput: Record<string, unknown>,\n): Record<string, unknown> {\n const next = { ...toolInput };\n if (toolName === 'Read' || toolName === 'Glob' || toolName === 'Grep') {\n if (typeof next.path === 'string' && next.path.trim()) {\n next.path = shortenTranscriptPath(next.path.trim());\n }\n if (typeof next.file_path === 'string' && next.file_path.trim()) {\n next.file_path = shortenTranscriptPath(next.file_path.trim());\n }\n }\n if (toolName === 'Write' || toolName === 'Edit') {\n const raw = String(next.file_path ?? next.path ?? '').trim();\n if (raw && !isPlanFilePath(raw)) {\n const short = shortenTranscriptPath(raw);\n if ('file_path' in next) next.file_path = short;\n else next.path = short;\n }\n }\n return next;\n}\n\nfunction formatAssistantToolLine(\n toolName: string,\n step: number | undefined,\n toolInput: Record<string, unknown> | null,\n): string {\n const name = toolName.trim() || 'Tool';\n if (name === 'Bash' && toolInput) {\n const cmd = String(toolInput.command ?? toolInput.cmd ?? '').trim();\n if (cmd) return formatSubagentToolProgressLine('Bash', { toolInput: { command: cmd } });\n }\n if (['Read', 'Write', 'Edit', 'Glob', 'Grep'].includes(name) && toolInput) {\n return formatSubagentToolProgressLine(name, {\n toolInput: withShortenedPaths(name, toolInput),\n });\n }\n if (typeof step === 'number') return `${name} step ${step}`;\n return name;\n}\n\nconst READ_LINES_FROM_RE = /Read\\s+(\\d+)\\s+lines\\s+from/i;\nconst READ_LINES_RE = /Read\\s+(\\d+)\\s+lines\\b/i;\nconst WROTE_LINES_RE = /Wrote\\s+(\\d+)\\s+lines/i;\nconst REPLACED_RE = /Replaced\\s+(\\d+)\\s+occurrence/i;\nconst NUMBERED_DUMP_RE = /^\\s*\\d+\\t/m;\n\nfunction firstMeaningfulLine(text: string): string {\n for (const line of text.split('\\n')) {\n const t = line.trim();\n if (t) return t;\n }\n return '';\n}\n\nfunction countNonEmptyLines(text: string): number {\n return text.split('\\n').filter((line) => line.trim().length > 0).length;\n}\n\n/** 将 tool_result 原文压成一行摘要;错误保留短 Error: 行。 */\nexport function condenseTranscriptToolResult(\n content: string,\n toolName?: string,\n): { text: string; variant: 'error' | 'dim' | 'default' } {\n const trimmed = content.trim();\n if (!trimmed) {\n return { text: `${(toolName ?? 'tool').trim() || 'tool'} result`, variant: 'default' };\n }\n\n const first = firstMeaningfulLine(trimmed);\n\n if (/^Error\\b/i.test(first) || /^error\\b/i.test(first)) {\n return { text: truncatePreview(first, 120), variant: 'error' };\n }\n\n if (/File unchanged/i.test(trimmed)) {\n return { text: 'File unchanged', variant: 'dim' };\n }\n\n if (/File created successfully/i.test(trimmed) || /^File created\\b/i.test(first)) {\n return { text: 'File created', variant: 'dim' };\n }\n\n const replaced = trimmed.match(REPLACED_RE);\n if (replaced) {\n const n = replaced[1] ?? '1';\n return {\n text: n === '1' ? 'Updated 1 occurrence' : `Updated ${n} occurrences`,\n variant: 'dim',\n };\n }\n\n const wrote = trimmed.match(WROTE_LINES_RE);\n if (wrote) {\n return { text: `Wrote ${wrote[1]} lines`, variant: 'dim' };\n }\n\n const readFrom = trimmed.match(READ_LINES_FROM_RE);\n if (readFrom) {\n return { text: `Read ${readFrom[1]} lines`, variant: 'dim' };\n }\n const readLines = trimmed.match(READ_LINES_RE);\n if (readLines && (NUMBERED_DUMP_RE.test(trimmed) || trimmed.includes('\\n'))) {\n return { text: `Read ${readLines[1]} lines`, variant: 'dim' };\n }\n\n const name = (toolName ?? '').trim();\n const multiLine = trimmed.includes('\\n') || trimmed.length > 160;\n if (multiLine) {\n if (name === 'Read' || NUMBERED_DUMP_RE.test(trimmed) || /^#\\s/m.test(trimmed)) {\n const n = countNonEmptyLines(\n trimmed.replace(READ_LINES_FROM_RE, '').replace(/^\\([^\\)]*\\)\\s*/m, ''),\n );\n const dumpLines = trimmed.split('\\n').filter((line) => NUMBERED_DUMP_RE.test(line)).length;\n const lineCount = dumpLines > 0 ? dumpLines : Math.max(n, 1);\n return { text: `Read ${lineCount} lines`, variant: 'dim' };\n }\n if (name === 'Write') {\n return { text: 'File created', variant: 'dim' };\n }\n if (name === 'Edit') {\n return { text: 'Updated', variant: 'dim' };\n }\n return { text: truncatePreview(first, 120), variant: 'dim' };\n }\n\n return { text: truncatePreview(first, 120), variant: 'default' };\n}\n\nfunction renderUserToolResult(message: Record<string, unknown>): TranscriptRenderLine {\n const toolName = String(message.name ?? message.tool_name ?? '').trim() || undefined;\n const content = message.content;\n\n if (typeof content === 'string') {\n const condensed = condenseTranscriptToolResult(content, toolName);\n return { kind: 'result', text: condensed.text, variant: condensed.variant };\n }\n\n if (content != null && typeof content !== 'string') {\n try {\n const condensed = condenseTranscriptToolResult(JSON.stringify(content), toolName);\n return { kind: 'result', text: condensed.text, variant: condensed.variant };\n } catch {\n const condensed = condenseTranscriptToolResult(String(content), toolName);\n return { kind: 'result', text: condensed.text, variant: condensed.variant };\n }\n }\n\n return {\n kind: 'result',\n text: `${toolName ?? 'tool'} result`,\n variant: 'default',\n };\n}\n\n/** 将单条 transcript lane entry 渲染为一行或多行(assistant tool_calls 可展开为多行)。 */\nexport function renderTranscriptEntryLines(\n entry: SubagentTranscriptEntry,\n): TranscriptRenderLine[] {\n const lines: TranscriptRenderLine[] = [];\n const { messageKind, message, step, toolName } = entry;\n\n if (messageKind === 'assistant') {\n const toolCalls = toolCallsFromAssistant(message);\n if (toolCalls.length > 0) {\n for (const call of toolCalls) {\n const callName = String(call.name ?? toolName ?? 'Tool').trim();\n lines.push({\n kind: 'call',\n text: formatAssistantToolLine(callName, step, toolInputFromCall(call)),\n });\n }\n return lines;\n }\n const text = String(message.content ?? '').trim();\n if (text) {\n lines.push({ kind: 'call', text: truncatePreview(text, 240) });\n }\n return lines;\n }\n\n if (messageKind === 'user') {\n lines.push(renderUserToolResult(message));\n }\n return lines;\n}\n\n/**\n * 将 transcript lane 展平为可见行。\n *\n * 多 tool_calls 批到达时,按 FIFO 交错 call↔result,使简述挂在对应调用下\n *(hanging indent 规格,见 quality-check/references/agent-progress-hanging-indent.md)。\n */\nexport function renderTranscriptLaneLines(\n entries: SubagentTranscriptEntry[],\n): TranscriptRenderLine[] {\n const pendingCalls: TranscriptRenderLine[] = [];\n const lines: TranscriptRenderLine[] = [];\n\n const flushPendingCalls = () => {\n while (pendingCalls.length > 0) {\n const call = pendingCalls.shift();\n if (call && call.text.length > 0) lines.push(call);\n }\n };\n\n for (const entry of entries) {\n if (entry.messageKind === 'assistant') {\n const toolCalls = toolCallsFromAssistant(entry.message);\n if (toolCalls.length > 0) {\n for (const call of toolCalls) {\n const callName = String(call.name ?? entry.toolName ?? 'Tool').trim();\n const text = formatAssistantToolLine(\n callName,\n entry.step,\n toolInputFromCall(call),\n );\n if (text.length > 0) {\n pendingCalls.push({ kind: 'call', text });\n }\n }\n continue;\n }\n // 无 tool_calls 的叙述:先吐出未配对调用,再跟正文\n flushPendingCalls();\n const text = String(entry.message.content ?? '').trim();\n if (text) {\n lines.push({ kind: 'call', text: truncatePreview(text, 240) });\n }\n continue;\n }\n\n if (entry.messageKind === 'user') {\n const result = renderUserToolResult(entry.message);\n if (result.text.length === 0) continue;\n const paired = pendingCalls.shift();\n if (paired && paired.text.length > 0) {\n lines.push(paired);\n }\n lines.push(result);\n }\n }\n\n flushPendingCalls();\n return lines;\n}\n","/**\n * SubagentTranscriptBlock.tsx — transcript lane 展开块(方案 B)\n *\n * 对齐 CLI render_transcript_lane_text · CC VerboseAgentTranscript:\n * call 行带 ⎿,result 行仅缩进(不再套第二层 ⎿)。\n */\nimport type { SubagentTranscriptEntry } from '../../../types/nodes';\nimport {\n AGENT_PROGRESS_GUTTER,\n AGENT_PROGRESS_INDENT,\n} from '../presentation/agentProgressRenderer';\nimport { renderTranscriptLaneLines } from '../presentation/subagentTranscriptRenderer';\n\nexport interface SubagentTranscriptBlockProps {\n entries: SubagentTranscriptEntry[];\n /** transcript-lane | progress-fallback | trace-fallback */\n dataSource?: string;\n}\n\nfunction gutterForKind(kind: 'call' | 'result'): string {\n return kind === 'call' ? AGENT_PROGRESS_GUTTER : AGENT_PROGRESS_INDENT;\n}\n\nexport function SubagentTranscriptBlock({\n entries,\n dataSource = 'transcript-lane',\n}: SubagentTranscriptBlockProps) {\n if (entries.length === 0) return null;\n\n const rendered = renderTranscriptLaneLines(entries);\n if (rendered.length === 0) return null;\n\n return (\n <div\n className=\"lax-agent-progress lax-agent-progress--transcript\"\n data-testid=\"lax-subagent-transcript-lane\"\n data-source={dataSource}\n >\n {rendered.map((line, index) => (\n <div\n key={`${index}:${line.kind}:${line.text}`}\n className=\"lax-agent-progress__line\"\n data-kind={line.kind}\n data-variant={line.variant ?? 'default'}\n >\n <span className=\"lax-agent-progress__gutter\" aria-hidden>\n {gutterForKind(line.kind)}\n </span>\n <span className=\"lax-agent-progress__text\">{line.text}</span>\n </div>\n ))}\n </div>\n );\n}\n","/**\n * AgentToolBody.tsx — Agent / Task 子代理正文\n *\n * 对齐参考:CLI widgets/tools/agent/widget.py · CC AgentTool/UI.tsx\n */\nimport {\n buildAgentBodyText,\n buildAgentTranscriptText,\n} from '../presentation/agentHelpers';\nimport {\n AGENT_PROGRESS_GUTTER,\n extractLastFilesystemStatusFromProgress,\n} from '../presentation/agentProgressRenderer';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\nimport { AgentProgressLines } from './AgentProgressLines';\nimport { SubagentTranscriptBlock } from './SubagentTranscriptBlock';\n\nfunction TranscriptFallbackLines({ text }: { text: string }) {\n const lines = text.split('\\n').map((line) => line.trimEnd()).filter((line) => line.length > 0);\n if (lines.length === 0) return null;\n return (\n <div\n className=\"lax-agent-progress lax-agent-progress--transcript\"\n data-source=\"trace-fallback\"\n data-testid=\"lax-agent-transcript-fallback\"\n >\n <div className=\"lax-agent-progress__label\">Transcript</div>\n {lines.map((line, index) => (\n <div\n key={`${index}:${line}`}\n className=\"lax-agent-progress__line\"\n data-kind=\"call\"\n >\n <span className=\"lax-agent-progress__gutter\" aria-hidden>\n {AGENT_PROGRESS_GUTTER}\n </span>\n <span className=\"lax-agent-progress__text\">{line}</span>\n </div>\n ))}\n </div>\n );\n}\n\nexport function AgentToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n status,\n subagentProgress,\n subagentTranscript,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--agent\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const progress = subagentProgress ?? [];\n const transcriptLane = subagentTranscript ?? [];\n const bodyText = buildAgentBodyText(result?.display, result?.summary ?? '');\n const transcriptFallback = buildAgentTranscriptText(result?.display, progress);\n // CC / D43:仅 completed(done) 渲染 Done teaser;failed/cancel 禁止\n const showDoneSummary = status === 'done' && bodyText.length > 0;\n const doneFilesystemStatus =\n status === 'done' ? extractLastFilesystemStatusFromProgress(progress) : null;\n const showTranscriptLane =\n bodyMode === 'full' && transcriptLane.length > 0;\n const showRunningProgress =\n status === 'running' && progress.length > 0 && !showTranscriptLane;\n const showTranscriptFallback =\n bodyMode === 'full' &&\n !showTranscriptLane &&\n transcriptFallback.length > 0;\n\n if (\n !showRunningProgress &&\n !showDoneSummary &&\n !doneFilesystemStatus &&\n !showTranscriptLane &&\n !showTranscriptFallback\n ) {\n const idleLabel = status === 'failed' ? '(stopped)' : '(running)';\n return (\n <div className=\"lax-tool-body lax-tool-body--agent\">\n <div className=\"lax-tool-body__block\" data-variant=\"dim\">\n <pre className=\"lax-tool-body__text\">{idleLabel}</pre>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"lax-tool-body lax-tool-body--agent\">\n {showRunningProgress ? (\n <AgentProgressLines\n entries={progress}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n ) : null}\n {showDoneSummary ? (\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n maxLines={12}\n onExpand={() => onBodyModeChange?.('full')}\n />\n ) : null}\n {showDoneSummary && doneFilesystemStatus ? (\n <div\n className=\"lax-agent-progress lax-agent-progress--done-status\"\n data-testid=\"lax-agent-done-filesystem-status\"\n >\n <div className=\"lax-agent-progress__line\">\n <span className=\"lax-agent-progress__gutter\" aria-hidden>\n {AGENT_PROGRESS_GUTTER}\n </span>\n <span className=\"lax-agent-progress__text\">{doneFilesystemStatus}</span>\n </div>\n </div>\n ) : null}\n {showTranscriptLane ? (\n <SubagentTranscriptBlock entries={transcriptLane} dataSource=\"transcript-lane\" />\n ) : null}\n {showTranscriptFallback ? (\n <TranscriptFallbackLines text={transcriptFallback} />\n ) : null}\n </div>\n );\n}\n","/**\r\n * askUserHelpers.ts — AskUserQuestion 正文与预览\r\n *\r\n * 对齐参考:CLI widgets/tools/helpers.py format_ask_user_*\r\n */\r\nexport function formatAskUserDisplayBody(display: Record<string, unknown>): string {\r\n const items = display.questions;\r\n if (!Array.isArray(items) || items.length === 0) return '';\r\n\r\n const lines: string[] = [];\r\n for (const item of items) {\r\n if (item == null || typeof item !== 'object') continue;\r\n const row = item as Record<string, unknown>;\r\n const header = String(row.header ?? '').trim();\r\n const question = String(row.question ?? '').trim();\r\n const answer = String(row.answer ?? '').trim();\r\n const prefix = header ? `[${header}] ` : '';\r\n lines.push(`${prefix}${question}`);\r\n if (answer) lines.push(` → ${answer}`);\r\n const selected = row.selected_options;\r\n if (Array.isArray(selected) && selected.length > 0) {\r\n for (const label of selected) {\r\n lines.push(` · ${String(label)}`);\r\n }\r\n }\r\n }\r\n return lines.length > 0 ? lines.join('\\n') : '';\r\n}\r\n\r\nexport function formatAskUserQuestionsPreview(input: Record<string, unknown>): string {\r\n const questions = input.questions;\r\n if (!Array.isArray(questions) || questions.length === 0) {\r\n return '(waiting for answers)';\r\n }\r\n\r\n const lines: string[] = [];\r\n questions.forEach((raw, idx) => {\r\n if (raw == null || typeof raw !== 'object') return;\r\n const q = raw as Record<string, unknown>;\r\n const header = String(q.header ?? '').trim();\r\n const qtext = String(q.question ?? '').trim();\r\n const prefix = header ? `[${header}] ` : '';\r\n lines.push(`${idx + 1}. ${prefix}${qtext}`);\r\n const options = q.options;\r\n if (Array.isArray(options)) {\r\n for (const opt of options) {\r\n if (opt != null && typeof opt === 'object') {\r\n const label = String((opt as Record<string, unknown>).label ?? '').trim();\r\n if (label) lines.push(` · ${label}`);\r\n }\r\n }\r\n }\r\n });\r\n return lines.length > 0 ? lines.join('\\n') : '(waiting for answers)';\r\n}\r\n","/**\n * AskUserQuestionToolBody.tsx — AskUserQuestion 工具正文\n *\n * 对齐参考:CLI widgets/tools/ask_user_question/widget.py\n */\nimport { asDisplayRecord, asInputRecord } from '../displayRecord';\nimport {\n formatAskUserDisplayBody,\n formatAskUserQuestionsPreview,\n} from '../presentation/askUserHelpers';\nimport { truncateLines } from '../presentation/searchHelpers';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nconst MAX_DISPLAY_LINES = 25;\nconst MAX_DISPLAY_CHARS = 1200;\n\nfunction buildAskUserBody(\n input: unknown,\n display: unknown,\n summary: string,\n): string {\n const d = asDisplayRecord(display);\n if (d) {\n const displayBody = formatAskUserDisplayBody(d);\n if (displayBody) {\n if (displayBody.length > MAX_DISPLAY_CHARS) {\n const { text, truncated } = truncateLines(displayBody, MAX_DISPLAY_LINES);\n return truncated ? `${text}\\n… 已截断` : text;\n }\n return displayBody;\n }\n }\n\n const text = summary.trim();\n if (text) return `Answered: ${text}`;\n\n return formatAskUserQuestionsPreview(asInputRecord(input));\n}\n\nexport function AskUserQuestionToolBody({\n input,\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--ask-user\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const bodyText = buildAskUserBody(input, result?.display, result?.summary ?? '');\n\n return (\n <div className=\"lax-tool-body lax-tool-body--ask-user\">\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n maxLines={12}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n}\n","/**\r\n * BashToolBody.tsx — bash 工具多块 stdout/stderr 正文\r\n *\r\n * 对齐参考:CLI widgets/tools/bash/widget.py · CC BashTool/UI.tsx\r\n */\r\nimport { BodyBlockList } from '../presentation/BodyBlockList';\r\nimport { buildBashBodyBlocks } from '../presentation/bashHelpers';\r\nimport type { ToolDisplayProps } from '../types';\r\n\r\nexport function BashToolBody({\r\n result,\r\n bodyMode,\r\n onBodyModeChange,\r\n}: ToolDisplayProps) {\r\n const isError = result?.status === 'failed' || Boolean(result?.error);\r\n const summary = result?.summary ?? '';\r\n const { blocks, truncated, remainingLines } = buildBashBodyBlocks(\r\n result?.display,\r\n summary,\r\n result?.meta,\r\n bodyMode,\r\n isError,\r\n );\r\n\r\n return (\r\n <div className=\"lax-tool-body lax-tool-body--bash\">\r\n <BodyBlockList blocks={blocks} />\r\n {truncated && bodyMode === 'preview' ? (\r\n <button\r\n type=\"button\"\r\n className=\"lax-tool-body__expand\"\r\n onClick={() => onBodyModeChange?.('full')}\r\n >\r\n +{remainingLines} lines (点击展开)\r\n </button>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","/**\n * EditToolBody.tsx — edit 工具正文(unified diff)\n *\n * 对齐参考:CLI widgets/tools/edit/widget.py · CC FileEditToolDiff.tsx\n */\nimport { resolveEditDiffText } from '../presentation/diffHelpers';\nimport { DiffView } from '../presentation/DiffView';\nimport type { ToolDisplayProps } from '../types';\n\nexport function EditToolBody({\n input,\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--edit\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const diff = resolveEditDiffText(\n result?.display,\n input,\n result?.summary ?? '',\n );\n\n return (\n <div className=\"lax-tool-body lax-tool-body--edit\">\n <DiffView\n diff={diff}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n}\n","/**\n * toolHints.ts — SDK ToolResultEnvelope.hints 解析\n *\n * SDK 形态:null | string | { message: string }[] | string[]\n */\n\nexport function parseToolResultHints(hints: unknown): string[] {\n if (hints == null) return [];\n if (typeof hints === 'string') {\n const trimmed = hints.trim();\n return trimmed ? [trimmed] : [];\n }\n if (!Array.isArray(hints)) return [];\n\n const messages: string[] = [];\n for (const item of hints) {\n if (typeof item === 'string') {\n const trimmed = item.trim();\n if (trimmed) messages.push(trimmed);\n continue;\n }\n if (item && typeof item === 'object') {\n const message = (item as { message?: unknown }).message;\n if (typeof message === 'string') {\n const trimmed = message.trim();\n if (trimmed) messages.push(trimmed);\n }\n }\n }\n return messages;\n}\n","/**\n * ToolResultHints.tsx — artifact hints 展示(SDK present() 层 B 语义)\n */\nimport { parseToolResultHints } from './toolHints';\n\nexport interface ToolResultHintsProps {\n hints: unknown;\n}\n\nexport function ToolResultHints({ hints }: ToolResultHintsProps) {\n const messages = parseToolResultHints(hints);\n if (messages.length === 0) return null;\n\n return (\n <div className=\"lax-tool-body__hints\" data-testid=\"lax-tool-result-hints\">\n {messages.map((message) => (\n <div\n key={message}\n className=\"lax-tool-body__block lax-tool-body__block--hint\"\n data-variant=\"dim\"\n >\n <p className=\"lax-tool-body__hint-text\">{message}</p>\n </div>\n ))}\n </div>\n );\n}\n","/**\n * GlobToolBody.tsx — glob 工具正文\n *\n * 对齐参考:CLI widgets/tools/glob/widget.py · helpers.format_search_result_body\n */\nimport { asDisplayRecord } from '../displayRecord';\nimport { formatSearchResultBody } from '../presentation/searchHelpers';\nimport { ToolResultHints } from '../presentation/ToolResultHints';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nfunction buildGlobBodyText(result: ToolDisplayProps['result']): string {\n const d = asDisplayRecord(result?.display);\n\n if (d?.type === 'file_list') {\n const files = Array.isArray(d.files) ? d.files.map((f) => String(f)) : [];\n const numFiles =\n typeof d.num_files === 'number' ? d.num_files : files.length;\n const summary =\n numFiles > 0 ? `Found ${numFiles} files` : 'No files found';\n if (files.length > 0) {\n return formatSearchResultBody(`${summary}\\n${files.join('\\n')}`);\n }\n return summary;\n }\n\n if (Array.isArray(d?.files)) {\n const files = d.files.map((f) => String(f));\n const summary = `Found ${files.length} files`;\n return formatSearchResultBody(`${summary}\\n${files.join('\\n')}`);\n }\n\n const summary = result?.summary?.trim() ?? '';\n if (summary) return formatSearchResultBody(summary);\n\n return '(No output)';\n}\n\nexport function GlobToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--glob\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const bodyText = buildGlobBodyText(result);\n\n return (\n <div className=\"lax-tool-body lax-tool-body--glob\">\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n <ToolResultHints hints={result?.hints} />\n </div>\n );\n}\n","/**\n * GrepToolBody.tsx — grep 工具正文\n *\n * 对齐参考:CLI widgets/tools/grep/widget.py · helpers.format_search_result_body\n */\nimport { asDisplayRecord } from '../displayRecord';\nimport { formatSearchResultBody } from '../presentation/searchHelpers';\nimport { ToolResultHints } from '../presentation/ToolResultHints';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nfunction buildGrepBodyText(result: ToolDisplayProps['result']): string {\n const d = asDisplayRecord(result?.display);\n\n if (d?.type === 'search_results') {\n const matches = Array.isArray(d.matches)\n ? d.matches.map((m) => String(m))\n : [];\n const numMatches =\n typeof d.num_matches === 'number' ? d.num_matches : matches.length;\n const summary =\n numMatches > 0\n ? `Found ${numMatches} matches`\n : 'No matches found';\n if (matches.length > 0) {\n return formatSearchResultBody(`${summary}\\n${matches.join('\\n')}`);\n }\n return summary;\n }\n\n if (Array.isArray(d?.matches)) {\n const matches = d.matches.map((m) => String(m));\n const summary = `Found ${matches.length} matches`;\n return formatSearchResultBody(`${summary}\\n${matches.join('\\n')}`);\n }\n\n const summary = result?.summary?.trim() ?? '';\n if (summary) return formatSearchResultBody(summary);\n\n return '(No output)';\n}\n\nexport function GrepToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--grep\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const bodyText = buildGrepBodyText(result);\n\n return (\n <div className=\"lax-tool-body lax-tool-body--grep\">\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n <ToolResultHints hints={result?.hints} />\n </div>\n );\n}\n","/**\n * ReadToolBody.tsx — Read 工具正文\n *\n * 对齐参考:CLI widgets/tools/read/widget.py format_body · CC FileReadTool/UI.tsx\n */\nimport { asDisplayRecord, numField, strField } from '../displayRecord';\nimport { BodyBlockList } from '../presentation/BodyBlockList';\nimport { MarkdownBlock } from '../presentation/MarkdownBlock';\nimport { MAX_PREVIEW_LINES } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nconst LINES_RANGE_RE = /lines (\\d+)-(\\d+) of (\\d+)/i;\nconst READ_LINES_RE = /Read (\\d+) lines from/i;\nconst EMPTY_RE = /\\(empty file\\)/i;\nconst NOTEBOOK_RE = /Read notebook.*?(\\d+) cells/i;\nconst IMAGE_RE = /Read image/i;\nconst PDF_RE = /Read PDF/i;\n\nfunction formatReadBodySummary(display: unknown, summary: string): string {\n const d = asDisplayRecord(display);\n\n if (d?.type === 'text') {\n const start = numField(d, 'line_start');\n const end = numField(d, 'line_end');\n const total = numField(d, 'total_lines');\n if (start != null && end != null && total != null) {\n return `Read lines ${start}–${end} of ${total}`;\n }\n const numLines = numField(d, 'num_lines');\n if (numLines != null) {\n return `Read ${numLines} lines`;\n }\n }\n\n if (d?.type === 'image') {\n const w = strField(d, 'width');\n const h = strField(d, 'height');\n if (w && h) return `Read image (${w}×${h})`;\n return 'Read image';\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 `Read PDF pages ${ps}–${pe}`;\n }\n return 'Read PDF';\n }\n\n const text = summary.trim();\n if (!text) return '(done)';\n\n if (EMPTY_RE.test(text)) return 'Empty file';\n const notebook = text.match(NOTEBOOK_RE);\n if (notebook) return `Read ${notebook[1]} cells`;\n if (IMAGE_RE.test(text)) return text.split('\\n', 1)[0]?.trim() || 'Read image';\n if (PDF_RE.test(text)) return text.split('\\n', 1)[0]?.trim() || 'Read PDF';\n\n const range = text.match(LINES_RANGE_RE);\n if (range) {\n return `Read lines ${range[1]}–${range[2]} of ${range[3]}`;\n }\n const readLines = text.match(READ_LINES_RE);\n if (readLines) return `Read ${readLines[1]} lines`;\n\n if (text.length > 500) {\n const lineCount = text.split('\\n').length;\n return `Read complete (${lineCount} lines in result)`;\n }\n\n return text.slice(0, 200) || '(done)';\n}\n\nfunction extractReadContent(display: unknown): string | null {\n const d = asDisplayRecord(display);\n if (!d) return null;\n if (d.type === 'markdown' || d.type === 'text') {\n const content = strField(d, 'content');\n if (content) return content;\n }\n return null;\n}\n\nexport function ReadToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n const display = result?.display ?? null;\n const summary = result?.summary ?? '';\n const bodyLine = formatReadBodySummary(display, summary);\n const content = extractReadContent(display);\n const d = asDisplayRecord(display);\n const isMarkdown = d?.type === 'markdown';\n\n // 构建文本 blocks(对齐 BashToolBody)\n const buildTextBlocks = () => {\n if (!content) return [];\n const lines = content.split('\\n');\n const isPreview = bodyMode === 'preview' && lines.length > MAX_PREVIEW_LINES;\n const text = isPreview ? lines.slice(0, MAX_PREVIEW_LINES).join('\\n') : content;\n return [{ text, variant: 'normal' as const }];\n };\n\n const textBlocks = buildTextBlocks();\n const hasMore = content && bodyMode === 'preview' && content.split('\\n').length > MAX_PREVIEW_LINES;\n\n return (\n <div className=\"lax-tool-body lax-tool-body--read\">\n <div className=\"lax-tool-body__summary\">{bodyLine}</div>\n {content ? (\n isMarkdown ? (\n <MarkdownBlock\n text={content}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n ) : (\n <>\n <BodyBlockList blocks={textBlocks} />\n {hasMore ? (\n <button\n type=\"button\"\n className=\"lax-tool-body__expand\"\n onClick={() => onBodyModeChange?.('full')}\n >\n +{content.split('\\n').length - MAX_PREVIEW_LINES} lines (点击展开)\n </button>\n ) : null}\n </>\n )\n ) : null}\n {result?.truncated ? (\n <div className=\"lax-tool-card__truncated\">结果已截断</div>\n ) : null}\n {result?.overflow_file ? (\n <div className=\"lax-tool-card__overflow\">\n 完整输出:\n <code>{result.overflow_file}</code>\n </div>\n ) : null}\n </div>\n );\n}\n","/**\n * SkillToolBody.tsx — skill 工具正文\n *\n * 对齐参考:CLI widgets/tools/skill/widget.py · CC SkillTool/UI.tsx\n */\nimport { truncateLines } from '../presentation/searchHelpers';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nconst MAX_BODY_LINES = 20;\n\nexport function SkillToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--skill\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const text = result?.summary?.trim() ?? '';\n if (!text) {\n return (\n <div className=\"lax-tool-body lax-tool-body--skill\">\n <div className=\"lax-tool-body__block\" data-variant=\"dim\">\n <pre className=\"lax-tool-body__text\">(done)</pre>\n </div>\n </div>\n );\n }\n\n const { text: truncated, truncated: was } = truncateLines(text, MAX_BODY_LINES);\n const bodyText = was ? `${truncated}\\n… 已截断` : truncated;\n\n return (\n <div className=\"lax-tool-body lax-tool-body--skill\">\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n maxLines={12}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n}\n","/**\n * WebFetchToolBody.tsx — WebFetch 工具正文\n *\n * 对齐参考:CLI widgets/tools/webfetch/widget.py · CC WebFetchTool/UI.tsx\n */\nimport { asDisplayRecord } from '../displayRecord';\nimport { truncateLines } from '../presentation/searchHelpers';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nconst RECEIVED_RE = /Received\\s+.+/i;\nconst MAX_BODY_LINES = 15;\n\nfunction buildWebFetchBody(result: ToolDisplayProps['result']): string {\n const d = asDisplayRecord(result?.display);\n if (d?.content_length != null) {\n const parts = [`Received ${d.content_length} bytes`];\n if (d.duration_ms != null) parts.push(`in ${d.duration_ms}ms`);\n if (d.from_cache) parts.push('(cached)');\n return parts.join(' ');\n }\n\n const text = result?.summary?.trim() ?? '';\n if (!text) return '(done)';\n\n const match = text.match(RECEIVED_RE);\n if (match) {\n const line = match[0].split('\\n', 1)[0] ?? match[0];\n return text.length <= 400 ? text : `${line}\\n…`;\n }\n\n const { text: truncated, truncated: was } = truncateLines(text, MAX_BODY_LINES);\n return was ? `${truncated}\\n… 已截断` : truncated;\n}\n\nexport function WebFetchToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--webfetch\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const bodyText = buildWebFetchBody(result);\n\n return (\n <div className=\"lax-tool-body lax-tool-body--webfetch\">\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n maxLines={12}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n}\n","/**\n * WebSearchToolBody.tsx — WebSearch 工具正文\n *\n * 对齐参考:CLI widgets/tools/websearch/widget.py · CC WebSearchTool/UI.tsx\n */\nimport { asDisplayRecord, strField } from '../displayRecord';\nimport { truncateLines } from '../presentation/searchHelpers';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport type { ToolDisplayProps } from '../types';\n\nconst MAX_BODY_LINES = 15;\n\nfunction buildWebSearchBody(result: ToolDisplayProps['result']): string {\n const d = asDisplayRecord(result?.display);\n if (d?.total_hits != null) {\n const engine = strField(d, 'search_engine') || 'search';\n return `Web search (${engine}): ${d.total_hits} results`;\n }\n\n const text = result?.summary?.trim() ?? '';\n if (!text) return '(done)';\n\n const first = text.split('\\n', 1)[0]?.trim() ?? '';\n if (/^(web search|did |found )/i.test(first)) {\n return text.length < 300 ? text : `${first}\\n…`;\n }\n\n const { text: truncated, truncated: was } = truncateLines(text, MAX_BODY_LINES);\n return was ? `${truncated}\\n… 已截断` : truncated;\n}\n\nexport function WebSearchToolBody({\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--websearch\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const bodyText = buildWebSearchBody(result);\n\n return (\n <div className=\"lax-tool-body lax-tool-body--websearch\">\n <TruncatedContent\n text={bodyText}\n mode={bodyMode}\n maxLines={12}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n}\n","/**\n * WriteToolBody.tsx — write 工具正文(diff 或新建预览)\n *\n * 对齐参考:CLI widgets/tools/write/widget.py · CC FileWriteTool/UI.tsx\n */\nimport { asDisplayRecord, asInputRecord, strField } from '../displayRecord';\nimport {\n countLines,\n formatDiffFromStrings,\n WRITE_PREVIEW_LINES,\n} from '../presentation/diffHelpers';\nimport { DiffView } from '../presentation/DiffView';\nimport { TruncatedContent } from '../presentation/TruncatedContent';\nimport { displayPath } from '../presentation/paths';\nimport type { ToolDisplayProps } from '../types';\n\nfunction buildWriteBodyText(\n input: unknown,\n display: unknown,\n summary: string,\n): { kind: 'diff' | 'preview' | 'text'; text: string } {\n const d = asDisplayRecord(display);\n const inp = asInputRecord(input);\n const content = strField(inp, 'content');\n const path = displayPath(\n strField(d ?? {}, 'file_path') || strField(inp, 'file_path'),\n );\n const fileType = strField(d ?? {}, 'type');\n\n const original = d?.original_file;\n if (fileType === 'update' && original != null && content) {\n return {\n kind: 'diff',\n text: formatDiffFromStrings(String(original), content),\n };\n }\n\n const diffText = strField(d ?? {}, 'diff');\n if (diffText) {\n return { kind: 'diff', text: diffText };\n }\n\n const numLines =\n typeof d?.num_lines === 'number'\n ? d.num_lines\n : countLines(content);\n\n if (numLines === 0 && !content.trim()) {\n const trimmed = summary.trim();\n return { kind: 'text', text: trimmed || '(No content)' };\n }\n\n const lines = content.split('\\n');\n const preview = lines.slice(0, WRITE_PREVIEW_LINES).join('\\n');\n const remaining = numLines - WRITE_PREVIEW_LINES;\n const header = `Wrote ${numLines} lines to ${path || 'file'}`;\n const body =\n remaining > 0 ? `${header}\\n${preview}\\n… +${remaining} lines` : `${header}\\n${preview}`;\n\n return { kind: 'preview', text: body };\n}\n\nexport function WriteToolBody({\n input,\n result,\n bodyMode,\n onBodyModeChange,\n}: ToolDisplayProps) {\n if (result?.error) {\n return (\n <div className=\"lax-tool-body lax-tool-body--write\">\n <div className=\"lax-tool-body__block\" data-variant=\"error\">\n <pre className=\"lax-tool-body__text\">{result.error.message}</pre>\n </div>\n </div>\n );\n }\n\n const body = buildWriteBodyText(\n input,\n result?.display,\n result?.summary ?? '',\n );\n\n if (body.kind === 'diff') {\n return (\n <div className=\"lax-tool-body lax-tool-body--write\">\n <DiffView\n diff={body.text}\n mode={bodyMode}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n }\n\n return (\n <div className=\"lax-tool-body lax-tool-body--write\">\n <TruncatedContent\n text={body.text}\n mode={bodyMode}\n maxLines={WRITE_PREVIEW_LINES + 1}\n onExpand={() => onBodyModeChange?.('full')}\n />\n </div>\n );\n}\n","/**\r\n * registry.ts — 工具展示注册表\r\n */\r\nimport { AgentToolBody } from './agent/AgentToolBody';\r\nimport { AskUserQuestionToolBody } from './ask_user_question/AskUserQuestionToolBody';\r\nimport { BashToolBody } from './bash/BashToolBody';\r\nimport { EditToolBody } from './edit/EditToolBody';\r\nimport { GlobToolBody } from './glob/GlobToolBody';\r\nimport { GrepToolBody } from './grep/GrepToolBody';\r\nimport { ReadToolBody } from './read/ReadToolBody';\r\nimport { SkillToolBody } from './skill/SkillToolBody';\r\nimport { WebFetchToolBody } from './webfetch/WebFetchToolBody';\r\nimport { WebSearchToolBody } from './websearch/WebSearchToolBody';\r\nimport { WriteToolBody } from './write/WriteToolBody';\r\nimport {\r\n Agent,\r\n AskUserQuestion,\r\n Bash,\r\n Edit,\r\n Glob,\r\n Grep,\r\n Read,\r\n Skill,\r\n WebFetch,\r\n WebSearch,\r\n Write,\r\n} from './toolNames';\r\nimport type { ToolBodyComponent } from './types';\r\n\r\nexport class ToolDisplayRegistry {\r\n private readonly map = new Map<string, ToolBodyComponent>();\r\n\r\n register(toolName: string, body: ToolBodyComponent): this {\r\n this.map.set(toolName, body);\r\n return this;\r\n }\r\n\r\n resolve(toolName: string): ToolBodyComponent | undefined {\r\n return this.map.get(toolName);\r\n }\r\n\r\n static default(): ToolDisplayRegistry {\r\n return createDefaultToolRegistry();\r\n }\r\n}\r\n\r\n/** 默认 registry:CC TOOL_NAME 单键,与 SDK registry_names.py 对齐。 */\r\nexport function createDefaultToolRegistry(): ToolDisplayRegistry {\r\n return new ToolDisplayRegistry()\r\n .register(Read, ReadToolBody)\r\n .register(Grep, GrepToolBody)\r\n .register(Glob, GlobToolBody)\r\n .register(Edit, EditToolBody)\r\n .register(Write, WriteToolBody)\r\n .register(Bash, BashToolBody)\r\n .register(Agent, AgentToolBody)\r\n .register(Skill, SkillToolBody)\r\n .register(AskUserQuestion, AskUserQuestionToolBody)\r\n .register(WebSearch, WebSearchToolBody)\r\n .register(WebFetch, WebFetchToolBody);\r\n}\r\n"],"mappings":"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","names":["truncatePreview","truncated","was","formatSubagentProgressLine","truncatePreview","text","truncatePreview","jsx","jsxs","jsx","jsxs","jsx","text","jsx","jsxs","jsx","jsx","jsx","jsxs","summary","jsx","jsxs","summary","jsx","jsxs","READ_LINES_RE","jsx","jsx","MAX_BODY_LINES","jsx","MAX_BODY_LINES","jsx"]}
@@ -21,7 +21,7 @@ import {
21
21
  formatWriteTitle,
22
22
  numField,
23
23
  strField
24
- } from "./chunk-GYFC2DI7.js";
24
+ } from "./chunk-7XSQYG3X.js";
25
25
  import {
26
26
  TruncatedContent,
27
27
  displayPath,
@@ -383,4 +383,4 @@ export {
383
383
  useInteractionBus,
384
384
  ToolCallShell
385
385
  };
386
- //# sourceMappingURL=chunk-5XELRP3S.js.map
386
+ //# sourceMappingURL=chunk-B2NG5KGH.js.map
@@ -15,7 +15,7 @@ import {
15
15
  extractLastToolInfoFromProgress,
16
16
  formatExploreSummaryText,
17
17
  formatThoughtDurationPrefix
18
- } from "./chunk-GYFC2DI7.js";
18
+ } from "./chunk-7XSQYG3X.js";
19
19
 
20
20
  // src/types/tree.ts
21
21
  function createEmptyTree() {
@@ -85,6 +85,8 @@ var DEFAULT_EVENT_TIERS = {
85
85
  "task-progress": "debug",
86
86
  "task-notification-enqueued": "debug",
87
87
  "task-notification-consumed": "debug",
88
+ /** 与 subagent-end 同级 collapsed(不可当可丢 debug) */
89
+ "task-notification": "collapsed",
88
90
  "task-terminated": "debug",
89
91
  "task-list-snapshot": "state",
90
92
  error: "main",
@@ -113,7 +115,7 @@ function resolveToolParentId(event, ctx, eventIndex) {
113
115
  return toolNodeIdFromEvent(event, eventIndex);
114
116
  }
115
117
  function isSubagentFoldEvent(event) {
116
- if (event.event_type === "subagent-start" || event.event_type === "subagent-end" || event.event_type === "subagent-tool-call" || event.event_type === "subagent-tool-result" || event.event_type === "subagent-transcript-message" || event.event_type === "subagent-model-step") {
118
+ if (event.event_type === "subagent-start" || event.event_type === "subagent-end" || event.event_type === "subagent-tool-call" || event.event_type === "subagent-tool-result" || event.event_type === "subagent-transcript-message" || event.event_type === "subagent-model-step" || event.event_type === "task-notification") {
117
119
  return true;
118
120
  }
119
121
  if (event.event_type === "tool-progress") {
@@ -124,7 +126,12 @@ function isSubagentFoldEvent(event) {
124
126
  }
125
127
  function resolveAgentToolParentId(event) {
126
128
  const data = event.data;
127
- if (data.tool_call_id) return `tool:${data.tool_call_id}`;
129
+ if (typeof data.tool_call_id === "string" && data.tool_call_id) {
130
+ return `tool:${data.tool_call_id}`;
131
+ }
132
+ if (typeof data.tool_use_id === "string" && data.tool_use_id) {
133
+ return `tool:${data.tool_use_id}`;
134
+ }
128
135
  return void 0;
129
136
  }
130
137
  function classifyEvent(event, ctx, overrides, eventIndex = 0) {
@@ -525,6 +532,150 @@ function formatModelRetryCategoryLabel(category) {
525
532
  }
526
533
  }
527
534
 
535
+ // src/core/finishCancel.ts
536
+ var DEFAULT_DISPLAY_INTERRUPT_TEXT = "[Request interrupted by user]";
537
+ var USER_CANCEL_TERMINAL_REASONS = /* @__PURE__ */ new Set([
538
+ "aborted_streaming",
539
+ "aborted_tools"
540
+ ]);
541
+ function isUserCancelledFinish(data) {
542
+ if (data.error_kind === "hook_stopped") return false;
543
+ if (data.error_kind === "user_cancelled") return true;
544
+ const reason = typeof data.terminal_reason === "string" ? data.terminal_reason : "";
545
+ if (USER_CANCEL_TERMINAL_REASONS.has(reason)) return true;
546
+ return false;
547
+ }
548
+ function isHookStoppedFinish(data) {
549
+ return data.error_kind === "hook_stopped";
550
+ }
551
+ function classifyFinishErrorPresentation(data) {
552
+ if (isHookStoppedFinish(data)) return "hook_stopped";
553
+ if (isUserCancelledFinish(data)) return "interrupt";
554
+ return "error";
555
+ }
556
+ function resolveInterruptDisplayText(data) {
557
+ if (typeof data.display_interrupt_text === "string" && data.display_interrupt_text.trim()) {
558
+ return data.display_interrupt_text.trim();
559
+ }
560
+ return DEFAULT_DISPLAY_INTERRUPT_TEXT;
561
+ }
562
+ function resolveHookStoppedMessage(data) {
563
+ if (Array.isArray(data.errors) && data.errors.length > 0) {
564
+ return data.errors.map(String).join("\n");
565
+ }
566
+ return "Stopped by hook";
567
+ }
568
+
569
+ // src/core/taskNotification.ts
570
+ function trimStr(value) {
571
+ return typeof value === "string" ? value.trim() : "";
572
+ }
573
+ function markTaskNotificationClosed(tree, taskId) {
574
+ tree.meta.taskNotificationClosedIds = {
575
+ ...tree.meta.taskNotificationClosedIds ?? {},
576
+ [taskId]: true
577
+ };
578
+ }
579
+ function isTaskNotificationClosed(tree, taskId) {
580
+ return tree.meta.taskNotificationClosedIds?.[taskId] === true;
581
+ }
582
+ function findTaskNotificationTarget(tree, data) {
583
+ const toolUseId = trimStr(data.tool_use_id);
584
+ const agentId = trimStr(data.agent_id);
585
+ const taskId = trimStr(data.task_id);
586
+ if (toolUseId) {
587
+ const byTool = findAgentToolCallNodeByCallId(tree, toolUseId);
588
+ if (byTool) {
589
+ return { nodeId: byTool.id, agentId: agentId || taskId || null };
590
+ }
591
+ }
592
+ const sessionKey = agentId || taskId;
593
+ if (sessionKey) {
594
+ for (const node of Object.values(tree.byId)) {
595
+ if (node?.kind !== "tool_call" || node.toolName !== "Agent") continue;
596
+ if (node.subagentSessions?.[sessionKey]) {
597
+ return { nodeId: node.id, agentId: sessionKey };
598
+ }
599
+ }
600
+ }
601
+ if (taskId) {
602
+ const byTaskAsCall = findAgentToolCallNodeByCallId(tree, taskId);
603
+ if (byTaskAsCall) {
604
+ return { nodeId: byTaskAsCall.id, agentId: agentId || null };
605
+ }
606
+ }
607
+ return null;
608
+ }
609
+ function finalizeRunningProgressForAgent(tool, agentId, terminal) {
610
+ const progress = tool.subagentProgress;
611
+ if (!progress?.length || !agentId) return progress;
612
+ return progress.map(
613
+ (entry) => entry.agentId === agentId && entry.status === "running" ? { ...entry, status: terminal } : entry
614
+ );
615
+ }
616
+ function hasRunningSession(sessions) {
617
+ return Object.values(sessions).some((marker) => marker.status === "running");
618
+ }
619
+ function applyTaskNotification(tree, data, endedAt) {
620
+ const taskId = trimStr(data.task_id);
621
+ if (!taskId) return false;
622
+ if (isTaskNotificationClosed(tree, taskId)) return false;
623
+ const status = data.status;
624
+ if (status !== "stopped" && status !== "completed" && status !== "failed") {
625
+ return false;
626
+ }
627
+ const target = findTaskNotificationTarget(tree, data);
628
+ if (!target) return false;
629
+ const tool = tree.byId[target.nodeId];
630
+ if (!tool || tool.kind !== "tool_call") return false;
631
+ const agentKey = target.agentId;
632
+ let nextSessions = tool.subagentSessions ?? {};
633
+ let sessionChanged = false;
634
+ if (agentKey) {
635
+ const existing = nextSessions[agentKey];
636
+ if (!existing || existing.status === "running") {
637
+ nextSessions = upsertSubagentSession(nextSessions, {
638
+ agentId: agentKey,
639
+ subagentType: existing?.subagentType,
640
+ status: "done",
641
+ startedAt: existing?.startedAt ?? endedAt,
642
+ endedAt
643
+ });
644
+ sessionChanged = true;
645
+ }
646
+ }
647
+ const progressTerminal = status === "completed" ? "completed" : "error";
648
+ const hasRunningProgress = !!agentKey && !!tool.subagentProgress?.some(
649
+ (entry) => entry.agentId === agentKey && entry.status === "running"
650
+ );
651
+ const nextProgress = hasRunningProgress ? finalizeRunningProgressForAgent(tool, agentKey, progressTerminal) : tool.subagentProgress;
652
+ const progressChanged = nextProgress !== tool.subagentProgress;
653
+ let nextToolStatus = tool.status;
654
+ let nextEndedAt = tool.endedAt;
655
+ let toolStatusChanged = false;
656
+ if (tool.status === "running") {
657
+ const shouldCloseParent = !agentKey || !hasRunningSession(nextSessions);
658
+ if (shouldCloseParent) {
659
+ nextToolStatus = status === "completed" ? "done" : "failed";
660
+ nextEndedAt = endedAt;
661
+ toolStatusChanged = true;
662
+ }
663
+ }
664
+ if (!sessionChanged && !progressChanged && !toolStatusChanged) {
665
+ markTaskNotificationClosed(tree, taskId);
666
+ return false;
667
+ }
668
+ tree.byId[target.nodeId] = {
669
+ ...tool,
670
+ status: nextToolStatus,
671
+ endedAt: nextEndedAt,
672
+ subagentSessions: nextSessions,
673
+ subagentProgress: nextProgress
674
+ };
675
+ markTaskNotificationClosed(tree, taskId);
676
+ return true;
677
+ }
678
+
528
679
  // src/core/reducer.ts
529
680
  function isInternalTool(toolName) {
530
681
  return INTERNAL_TOOL_NAMES.has(toolName);
@@ -722,17 +873,34 @@ function resolveFinishErrorMessage(data) {
722
873
  return "Agent finished with an error";
723
874
  }
724
875
  function appendFinishErrorNode(tree, event, data, seq) {
725
- const { message, type } = resolveErrorEventFields({
726
- message: resolveFinishErrorMessage(data),
727
- type: typeof data.error_kind === "string" && data.error_kind || typeof data.terminal_reason === "string" && data.terminal_reason || void 0
728
- });
876
+ const presentation = classifyFinishErrorPresentation(data);
877
+ let message;
878
+ let type;
879
+ let variant = "error";
880
+ if (presentation === "interrupt") {
881
+ message = resolveInterruptDisplayText(data);
882
+ type = typeof data.error_kind === "string" && data.error_kind || typeof data.terminal_reason === "string" && data.terminal_reason || "user_cancelled";
883
+ variant = "interrupt";
884
+ } else if (presentation === "hook_stopped") {
885
+ message = resolveHookStoppedMessage(data);
886
+ type = "hook_stopped";
887
+ variant = "hook_stopped";
888
+ } else {
889
+ const resolved = resolveErrorEventFields({
890
+ message: resolveFinishErrorMessage(data),
891
+ type: typeof data.error_kind === "string" && data.error_kind || typeof data.terminal_reason === "string" && data.terminal_reason || void 0
892
+ });
893
+ message = resolved.message;
894
+ type = resolved.type;
895
+ }
729
896
  const id = `finish-error:${seq}`;
730
897
  const node = {
731
898
  kind: "error",
732
899
  id,
733
900
  message,
734
901
  errorType: type,
735
- startedAt: eventTimeToMs(event.timestamp)
902
+ startedAt: eventTimeToMs(event.timestamp),
903
+ variant
736
904
  };
737
905
  tree.byId[id] = node;
738
906
  appendMainStageChild(tree, id, event, seq);
@@ -1266,6 +1434,13 @@ function handleToolProgress(tree, event, parentNodeId, _seq) {
1266
1434
  }
1267
1435
  });
1268
1436
  }
1437
+ function handleTaskNotification(tree, event) {
1438
+ applyTaskNotification(
1439
+ tree,
1440
+ event.data,
1441
+ eventTimeToMs(event.timestamp)
1442
+ );
1443
+ }
1269
1444
  function handleSubagentBoundaryStart(tree, event, parentNodeId, options) {
1270
1445
  const data = event.data;
1271
1446
  let parentId = parentNodeId;
@@ -1601,6 +1776,9 @@ function applyClassified(tree, classified, eventIndex, options) {
1601
1776
  break;
1602
1777
  case "subagent-model-step":
1603
1778
  break;
1779
+ case "task-notification":
1780
+ handleTaskNotification(tree, event);
1781
+ break;
1604
1782
  case "start-step":
1605
1783
  handleStepStart(tree, event, parentNodeId, seq);
1606
1784
  break;
@@ -1806,6 +1984,9 @@ function resolveWorkflowBanner(state) {
1806
1984
  return { kind: "sync_failed", message: "\u540C\u6B65\u72B6\u6001\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0" };
1807
1985
  }
1808
1986
  const auth = state.authority?.status;
1987
+ if (auth === "canceled") {
1988
+ return { kind: "canceled", message: "\u5DF2\u53D6\u6D88" };
1989
+ }
1809
1990
  if (auth === "error") {
1810
1991
  return { kind: "authority_error", message: "Workflow \u6267\u884C\u5931\u8D25" };
1811
1992
  }
@@ -4093,6 +4274,13 @@ function shouldShowAgentSpinner(state) {
4093
4274
  if (isAuthorityTerminalStatus(auth)) return false;
4094
4275
  return true;
4095
4276
  }
4277
+ function isAgentInputLocked(state) {
4278
+ if (!state.authorityBindingActive) {
4279
+ const status = state.tree.status;
4280
+ return status === "running" || status === "connecting";
4281
+ }
4282
+ return !isAuthorityTerminalStatus(state.authority?.status);
4283
+ }
4096
4284
 
4097
4285
  // src/view/TaskList.tsx
4098
4286
  import { useEffect as useEffect3, useMemo as useMemo4, useRef as useRef2, useState as useState3 } from "react";
@@ -5700,6 +5888,7 @@ export {
5700
5888
  CollapsedExploreNode,
5701
5889
  SystemSummaryNode,
5702
5890
  shouldShowAgentSpinner,
5891
+ isAgentInputLocked,
5703
5892
  TaskList,
5704
5893
  Spinner,
5705
5894
  formatTaskFooterLabel,
@@ -5713,4 +5902,4 @@ export {
5713
5902
  VirtualTimeline,
5714
5903
  SessionTimeline
5715
5904
  };
5716
- //# sourceMappingURL=chunk-O5GERXTY.js.map
5905
+ //# sourceMappingURL=chunk-UBYOUDQE.js.map