@blade-hq/agent-kit 0.4.4 → 0.4.6
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/README.md +8 -1
- package/dist/chunk-2UP7MG3J.js +66 -0
- package/dist/chunk-2UP7MG3J.js.map +1 -0
- package/dist/chunk-4VWLTG5L.js +2984 -0
- package/dist/chunk-4VWLTG5L.js.map +1 -0
- package/dist/chunk-7LEKQI47.js +32 -0
- package/dist/chunk-7LEKQI47.js.map +1 -0
- package/dist/chunk-DQCXSPHP.js +33 -0
- package/dist/chunk-DQCXSPHP.js.map +1 -0
- package/dist/chunk-I3FFV63W.js +30 -0
- package/dist/chunk-I3FFV63W.js.map +1 -0
- package/dist/chunk-J3XVFPOV.js +58 -0
- package/dist/chunk-J3XVFPOV.js.map +1 -0
- package/dist/chunk-JCJFFJ42.js +39 -0
- package/dist/chunk-JCJFFJ42.js.map +1 -0
- package/dist/chunk-LIL4FIZP.js +7992 -0
- package/dist/chunk-LIL4FIZP.js.map +1 -0
- package/dist/chunk-OKQWPNE3.js +1077 -0
- package/dist/chunk-OKQWPNE3.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-TC5BBLWO.js +29 -0
- package/dist/chunk-TC5BBLWO.js.map +1 -0
- package/dist/chunk-VD4CKRMT.js +127 -0
- package/dist/chunk-VD4CKRMT.js.map +1 -0
- package/dist/chunk-X6MEYCU7.js +1401 -0
- package/dist/chunk-X6MEYCU7.js.map +1 -0
- package/dist/client/index.d.ts +529 -40
- package/dist/client/index.js +24 -1033
- package/dist/client/index.js.map +1 -1
- package/dist/react/api/licenses.js +11 -1470
- package/dist/react/api/licenses.js.map +1 -1
- package/dist/react/api/vibe-coding.js +25 -1481
- package/dist/react/api/vibe-coding.js.map +1 -1
- package/dist/react/cards/register.js +45 -138
- package/dist/react/cards/register.js.map +1 -1
- package/dist/react/components/chat/index.js +28 -11366
- package/dist/react/components/chat/index.js.map +1 -1
- package/dist/react/components/plan/index.js +135 -3054
- package/dist/react/components/plan/index.js.map +1 -1
- package/dist/react/components/session/index.js +21 -1499
- package/dist/react/components/session/index.js.map +1 -1
- package/dist/react/components/workspace/index.js +116 -1715
- package/dist/react/components/workspace/index.js.map +1 -1
- package/dist/react/devtools/bridge-devtools/index.js +8 -51
- package/dist/react/devtools/bridge-devtools/index.js.map +1 -1
- package/dist/react/index.d.ts +74 -2
- package/dist/react/index.js +656 -13958
- package/dist/react/index.js.map +1 -1
- package/dist/style.css +2 -0
- package/package.json +5 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/react/components/chat/ChatView.tsx","../../../../src/react/hooks/use-chat.ts","../../../../src/react/sockets/socket-state.ts","../../../../src/react/lib/chat.ts","../../../../src/client/resources/models.ts","../../../../src/client/socket.ts","../../../../src/react/stores/answer-callback-store.ts","../../../../src/react/stores/client-aware.ts","../../../../src/react/stores/auth-store.ts","../../../../src/react/api/auth.ts","../../../../src/react/stores/session-store.ts","../../../../src/react/api/sessions.ts","../../../../src/react/stores/chat-store.ts","../../../../src/react/components/chat/display-utils.ts","../../../../src/react/stores/ui-store.ts","../../../../src/react/stores/task-store.ts","../../../../src/react/stores/background-store.ts","../../../../src/react/stores/card-state-store.ts","../../../../src/react/stores/connection-store.ts","../../../../src/react/stores/gis-store.ts","../../../../src/react/stores/runtime-features-store.ts","../../../../src/react/stores/runtime-store.ts","../../../../src/react/stores/ui-bridge-store.ts","../../../../src/react/bootstrap.ts","../../../../src/react/api/client.ts","../../../../src/react/api/skills.ts","../../../../src/react/devtools/bridge-devtools/tap.ts","../../../../src/react/schemas/partner-skill.ts","../../../../src/react/lib/resource-bridge.ts","../../../../src/react/lib/tool-preview.ts","../../../../src/react/lib/ui-meta.ts","../../../../src/react/components/chat/ChatInput.tsx","../../../../src/react/asr/use-tiptap-voice-input.ts","../../../../src/react/asr/use-voice-input.ts","../../../../src/react/asr/voice-input-support.ts","../../../../src/react/asr/VoiceWaveform.tsx","../../../../src/react/components/model/ModelSelector.tsx","../../../../src/react/hooks/use-model-preferences.ts","../../../../src/react/api/models.ts","../../../../src/react/api/user-preferences.ts","../../../../src/react/hooks/use-input-history.ts","../../../../src/react/lib/attachment-upload.ts","../../../../src/react/schemas/skill.ts","../../../../src/react/components/chat/FileCompletionMenu.tsx","../../../../src/react/components/chat/SkillCompletionMenu.tsx","../../../../src/react/components/chat/FileSizeLimitDialog.tsx","../../../../src/react/components/chat/SkillStatusBar.tsx","../../../../src/react/hooks/use-background-tasks.ts","../../../../src/react/hooks/use-context-stats.ts","../../../../src/react/hooks/use-skill-stats.ts","../../../../src/react/hooks/use-token-pressure.ts","../../../../src/react/lib/utils.ts","../../../../src/react/components/chat/ProgressCircle.tsx","../../../../src/react/components/chat/extensions/file-mention.ts","../../../../src/react/components/chat/extensions/skill-mention.ts","../../../../src/react/components/chat/ConnectionBanner.tsx","../../../../src/react/components/chat/MessageList.tsx","../../../../../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js","../../../../../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/StickToBottom.js","../../../../src/react/components/plan/PlanSummaryCard.tsx","../../../../src/react/components/chat/AskUserQuestionBlock.tsx","../../../../src/react/components/markdown/MarkdownContent.tsx","../../../../src/react/components/card/CardCodeBlock.tsx","../../../../src/react/lib/card-registry.ts","../../../../src/react/lib/code-highlight.ts","../../../../src/react/components/card/CardRenderer.tsx","../../../../src/react/components/card/CardContext.tsx","../../../../src/react/components/card/CardStates.tsx","../../../../src/react/components/plan/parse-plan-tree.ts","../../../../src/react/components/plan/parse-plan-messages.ts","../../../../src/react/components/plan/extract-plan-messages.ts","../../../../src/react/components/chat/AssistantTurnBlock.tsx","../../../../src/react/routes.ts","../../../../src/react/components/ai-elements/reasoning.tsx","../../../../src/react/components/ui/collapsible.tsx","../../../../src/react/components/ai-elements/shimmer.tsx","../../../../src/react/components/chat/AgentLoopBlock.tsx","../../../../src/react/components/chat/ResourceIframe.tsx","../../../../src/react/components/chat/ToolCallBlock.tsx","../../../../src/react/lib/session-file-preview.ts","../../../../src/react/components/chat/tool-renderers/shared.tsx","../../../../src/react/components/chat/tool-renderers/BashRenderer.tsx","../../../../src/react/components/chat/tool-renderers/FileEditRenderer.tsx","../../../../src/react/components/chat/tool-renderers/FileReadRenderer.tsx","../../../../src/react/components/chat/ImageLightbox.tsx","../../../../src/react/components/chat/tool-renderers/SearchRenderer.tsx","../../../../src/react/components/chat/tool-renderers/registry.ts","../../../../src/react/components/chat/UserMessageBubble.tsx","../../../../src/react/lib/preview-dispatch.ts","../../../../src/react/lib/whatif-prompt.ts","../../../../src/react/components/chat/AttachmentPreviewDialog.tsx","../../../../src/react/components/chat/MessageContextPills.tsx","../../../../src/react/components/chat/MessageFileAttachmentList.tsx","../../../../src/react/components/chat/MessageActions.tsx","../../../../src/react/components/chat/TextAttachmentPills.tsx","../../../../src/react/components/chat/WhatIfUserBubble.tsx","../../../../src/react/components/chat/whatif-quote-context.tsx","../../../../src/react/components/chat/CompactionCard.tsx","../../../../src/react/components/chat/RenderErrorBoundary.tsx","../../../../src/react/components/chat/StickyStatusBar.tsx","../../../../src/react/components/chat/TurnNavRail.tsx"],"sourcesContent":["import { Eye } from \"lucide-react\"\nimport { useCallback, type ReactNode } from \"react\"\nimport { useChat } from \"../../hooks/use-chat\"\nimport type { MessageContent } from \"../../schemas/message\"\nimport { useSessionStore } from \"../../stores/session-store\"\nimport { ChatInput } from \"./ChatInput\"\nimport { ConnectionBanner } from \"./ConnectionBanner\"\nimport { MessageList } from \"./MessageList\"\n\ninterface ChatViewProps {\n sessionId: string\n renderAttachments?: () => ReactNode\n onBeforeSend?: (content: MessageContent) => MessageContent\n onCommand?: (commandId: string) => void | Promise<void>\n canShareSession?: boolean\n onResyncSkills?: () => void\n isResyncingSkills?: boolean\n}\n\nexport function ChatView({\n sessionId,\n renderAttachments,\n onBeforeSend,\n onCommand,\n canShareSession = false,\n onResyncSkills,\n isResyncingSkills = false,\n}: ChatViewProps) {\n const {\n messages,\n isStreaming,\n send,\n stop,\n } = useChat(sessionId)\n const session = useSessionStore((s) => s.sessions.find((ss) => ss.id === sessionId))\n const mode = useSessionStore((s) => s.modes[sessionId] ?? \"executing\")\n const toggleMode = useCallback(\n () => useSessionStore.getState().togglePlanningMode(sessionId),\n [sessionId],\n )\n const sessionStatus = session?.status\n const isViewer = session?.viewer_role === \"viewer\"\n const onConfirmPlan = useCallback(\n (action: \"execute\" | \"revise\", text?: string) => {\n if (action === \"execute\") {\n send(\"计划已确认,开始执行\", \"executing\")\n } else if (text) {\n send(text, \"planning\")\n }\n },\n [send],\n )\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col overflow-hidden\">\n {isViewer && (\n <div className=\"flex items-center justify-center gap-2 border-b border-[hsl(var(--border))] bg-[hsl(var(--card))] py-2 text-xs text-[hsl(var(--muted-foreground))]\">\n <Eye size={14} />\n 你正在查看分享的会话(只读)\n </div>\n )}\n {!isViewer && <ConnectionBanner />}\n <MessageList\n key={sessionId}\n sessionId={sessionId}\n messages={messages}\n onAnswer={\n isViewer\n ? undefined\n : (msg, toolCallId, answerData) =>\n send(msg, mode, { tool_call_id: toolCallId, ...answerData })\n }\n sessionStatus={sessionStatus}\n onConfirmPlan={isViewer ? undefined : onConfirmPlan}\n />\n {!isViewer && (\n <ChatInput\n onSend={(msg, _targetSessionId, model) =>\n send(msg, mode, undefined, { model: model || undefined })\n }\n onStop={stop}\n isStreaming={isStreaming}\n mode={mode}\n onToggleMode={toggleMode}\n renderAttachments={renderAttachments}\n onBeforeSend={onBeforeSend}\n onCommand={onCommand}\n canShareSession={canShareSession}\n onResyncSkills={onResyncSkills}\n isResyncingSkills={isResyncingSkills}\n />\n )}\n </div>\n )\n}\n","import { useCallback, useEffect } from \"react\"\nimport { getSocket } from \"../api/socket\"\nimport type { ChatMessage, MessageContent } from \"../schemas/message\"\nimport { useAnswerCallbackStore } from \"../stores/answer-callback-store\"\nimport { useChatStore } from \"../stores/chat-store\"\nimport { useSessionStore } from \"../stores/session-store\"\n\nconst EMPTY_MESSAGES: ChatMessage[] = []\n\nexport function useChat(sessionId: string) {\n const messages = useChatStore((s) => s.messages[sessionId] ?? EMPTY_MESSAGES)\n const isStreaming = useChatStore((s) => s.isStreaming[sessionId] ?? false)\n const mode = useSessionStore((s) => s.modes[sessionId] ?? \"executing\")\n const setAnswerCallback = useAnswerCallbackStore((s) => s.setAnswerCallback)\n\n const send = useCallback(\n (\n msg: MessageContent,\n mode?: string,\n askuserAnswer?: Record<string, unknown>,\n options?: { model?: string },\n ) => {\n const synthesizedAnswer =\n askuserAnswer ?? buildPendingAskUserAnswer(sessionId, msg)\n getSocket().send(sessionId, msg, mode, synthesizedAnswer, options)\n },\n [sessionId],\n )\n\n const stop = useCallback(() => {\n getSocket().stop(sessionId)\n }, [sessionId])\n\n const answer = useCallback(\n (msg: string, toolCallId: string, answerData: { selections: Record<number, number[]>; custom: Record<number, string> }) => {\n send(msg, mode, { tool_call_id: toolCallId, ...answerData })\n },\n [mode, send],\n )\n\n useEffect(() => {\n setAnswerCallback(sessionId, answer)\n return () => setAnswerCallback(sessionId, undefined)\n }, [answer, sessionId, setAnswerCallback])\n\n return { messages, isStreaming, send, stop }\n}\n\nexport function buildPendingAskUserAnswer(\n sessionId: string,\n message: MessageContent,\n): Record<string, unknown> | undefined {\n const session = useSessionStore.getState().sessions.find((item) => item.id === sessionId)\n if (session?.status !== \"waiting_for_input\") {\n return undefined\n }\n const text = extractMessageText(message)\n if (!text) {\n return undefined\n }\n const turns = useChatStore.getState().turns[sessionId] ?? []\n for (let turnIndex = turns.length - 1; turnIndex >= 0; turnIndex -= 1) {\n const turn = turns[turnIndex]\n if (turn.loop_id === \"root\" || turn.role !== \"assistant\") continue\n for (let toolIndex = turn.tool_calls.length - 1; toolIndex >= 0; toolIndex -= 1) {\n const toolCall = turn.tool_calls[toolIndex]\n if (toolCall.status !== \"awaiting_answer\") continue\n if (!toolCall.tool_name.includes(\"AskUserQuestion\")) continue\n return {\n tool_call_id: toolCall.id,\n selections: {},\n custom: { \"0\": text },\n }\n }\n }\n return undefined\n}\n\nfunction extractMessageText(message: MessageContent): string {\n if (typeof message === \"string\") {\n return message.trim()\n }\n return message\n .filter((part) => part.type === \"text\")\n .map((part) => part.text.trim())\n .filter(Boolean)\n .join(\"\\n\")\n .trim()\n}\n","import type { AgentSocket } from \"./event-bridge\"\n\nexport let agentSocket: AgentSocket | null = null\n\nexport function setAgentSocket(nextSocket: AgentSocket | null): void {\n agentSocket = nextSocket\n}\n\nexport function getSocket(): AgentSocket {\n if (!agentSocket) throw new Error(\"Socket not initialized. Call bootstrapBladeClient() first.\")\n return agentSocket\n}\n","import type {\n ChatMessage,\n FileContentPart,\n ImageUrlContentPart,\n MessageContent,\n MessageContentPart,\n} from \"../schemas/message\"\n\nconst SYSTEM_REMINDER_PATTERN = /^<system-reminder>\\s*[\\s\\S]*?\\s*<\\/system-reminder>$/i\nconst LEGACY_FORK_CONTEXT_MARKERS = [\n \"父智能体在派生你之前已经完成了一些操作。\",\n \"可通过 `read_file` 读取。\",\n \"# 你的任务\",\n]\n\nexport function normalizeMessageContent(content: unknown): MessageContent {\n if (typeof content === \"string\") return content\n if (Array.isArray(content)) return content as MessageContentPart[]\n return String(content ?? \"\")\n}\n\nexport function getTextContent(content: MessageContent): string {\n if (typeof content === \"string\") return content\n return content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n}\n\nexport function isSystemReminderText(text: string): boolean {\n return SYSTEM_REMINDER_PATTERN.test(text.trim())\n}\n\nexport function isLegacyForkContextText(text: string): boolean {\n const normalized = text.trim()\n return LEGACY_FORK_CONTEXT_MARKERS.every((marker) => normalized.includes(marker))\n}\n\nexport function isHiddenInternalMessage(message: Pick<ChatMessage, \"role\" | \"content\">): boolean {\n if (message.role !== \"user\") return false\n const text = getTextContent(normalizeMessageContent(message.content))\n return isSystemReminderText(text) || isLegacyForkContextText(text)\n}\n\nexport function buildMessageContent(\n text: string,\n attachments: Array<{\n kind: \"file\"\n name: string\n uploadedPath?: string\n textContent?: string | null\n mimeType?: string\n }>,\n): MessageContent {\n if (attachments.length === 0) return text\n const textSegments: string[] = []\n\n if (text.trim()) {\n textSegments.push(text)\n }\n\n for (const attachment of attachments) {\n let fileText: string\n if (attachment.uploadedPath) {\n const displayName = attachment.uploadedPath.split(\"/\").pop() || attachment.name\n fileText = `[附件: ${displayName}] 已上传到工作区路径: ${attachment.uploadedPath}`\n } else if (attachment.textContent) {\n const MAX_TEXT_CHARS = 100_000\n const content =\n attachment.textContent.length > MAX_TEXT_CHARS\n ? `${attachment.textContent.slice(0, MAX_TEXT_CHARS)}\\n\\n[内容已截断,原始共 ${attachment.textContent.length} 字符]`\n : attachment.textContent\n fileText = `[附件: ${attachment.name}]\\n${content}`\n } else {\n fileText = `[附件: ${attachment.name}]`\n }\n textSegments.push(fileText)\n }\n\n return textSegments.join(\"\\n\\n\")\n}\n\nexport function contentPreview(content: MessageContent, maxLen = 80): string {\n const text = getTextContent(content).trim()\n return text.length > maxLen ? `${text.slice(0, maxLen)}…` : text\n}\n\n/**\n * Transform a skill mention into a natural language skill invocation.\n * Strips the `<skill>name</skill>` tag from the raw input and prepends the instruction.\n */\nexport function transformSlashCommand(skillName: string, rawInput: string): string {\n const prompt = rawInput.replace(`<skill>${skillName}</skill>`, \"\").trim()\n return prompt\n ? `请使用 ${skillName} skill 完成任务\\n${prompt}`\n : `请使用 ${skillName} skill 完成任务`\n}\n\nconst ATTACHMENT_TAG_RE = /\\[附件:\\s*([^\\]]+)\\](?:[ \\t]*已上传到工作区路径:[ \\t]*([^\\r\\n]+))?/g\n// 来自 addContext 的 context 在发送时序列化为独立 text part:`[上下文: LABEL]\\nCONTENT`\n// 整块 part 匹配而非行内替换,避免破坏正文中可能出现的\"[上下文:\"字样\nconst CONTEXT_PART_RE = /^\\[上下文:\\s*([^\\]]+)\\]\\n([\\s\\S]*)$/\n\nexport interface ParsedTextAttachment {\n name: string\n uploadedPath?: string\n}\n\nexport interface ParsedTextContext {\n label: string\n content: string\n}\n\n/**\n * Extract `[附件: name]` and `[上下文: label]` tags from text parts and return\n * the cleaned text plus the collected attachment / context metadata. 每个 text\n * part 独立匹配,以避免跨 part 拼接打乱正则。\n */\nexport function extractTextAttachments(content: MessageContent): {\n cleanText: string\n attachments: ParsedTextAttachment[]\n contexts: ParsedTextContext[]\n} {\n if (typeof content === \"string\") {\n const attachments: ParsedTextAttachment[] = []\n const contexts: ParsedTextContext[] = []\n const ctxMatch = CONTEXT_PART_RE.exec(content)\n let working = content\n if (ctxMatch) {\n contexts.push({ label: ctxMatch[1].trim(), content: ctxMatch[2].trim() })\n working = \"\"\n }\n for (const match of working.matchAll(ATTACHMENT_TAG_RE)) {\n attachments.push({\n name: match[1].trim(),\n uploadedPath: match[2]?.trim() || undefined,\n })\n }\n return {\n cleanText: working.replace(ATTACHMENT_TAG_RE, \"\").trim(),\n attachments,\n contexts,\n }\n }\n\n const attachments: ParsedTextAttachment[] = []\n const contexts: ParsedTextContext[] = []\n const cleanParts: string[] = []\n\n for (const part of content) {\n if (part.type !== \"text\") continue\n\n const ctxMatch = CONTEXT_PART_RE.exec(part.text)\n if (ctxMatch) {\n contexts.push({ label: ctxMatch[1].trim(), content: ctxMatch[2].trim() })\n continue\n }\n\n let hasAttachment = false\n for (const match of part.text.matchAll(ATTACHMENT_TAG_RE)) {\n attachments.push({\n name: match[1].trim(),\n uploadedPath: match[2]?.trim() || undefined,\n })\n hasAttachment = true\n }\n if (hasAttachment) {\n const remaining = part.text.replace(ATTACHMENT_TAG_RE, \"\").trim()\n if (remaining) cleanParts.push(remaining)\n } else {\n cleanParts.push(part.text)\n }\n }\n\n return { cleanText: cleanParts.join(\"\\n\").trim(), attachments, contexts }\n}\n\nexport function getImageParts(content: MessageContent): ImageUrlContentPart[] {\n if (typeof content === \"string\") return []\n return content.filter((part): part is ImageUrlContentPart => part.type === \"image_url\")\n}\n\nexport function getFileParts(content: MessageContent): FileContentPart[] {\n if (typeof content === \"string\") return []\n return content.filter((part): part is FileContentPart => part.type === \"file\")\n}\n\ninterface MessageGroup {\n root: ChatMessage | null\n childLoops: { loopName: string; messages: ChatMessage[] }[]\n}\n\nexport function groupMessagesByLoop(messages: ChatMessage[]): MessageGroup[] {\n const groups: MessageGroup[] = []\n let currentGroup: MessageGroup | null = null\n\n for (const msg of messages) {\n const loop = msg.loop_name ?? \"root\"\n\n if (loop === \"root\") {\n currentGroup = { root: msg, childLoops: [] }\n groups.push(currentGroup)\n } else {\n if (!currentGroup) {\n currentGroup = { root: null, childLoops: [] }\n groups.push(currentGroup)\n }\n const existingLoop = currentGroup.childLoops.find((l) => l.loopName === loop)\n if (existingLoop) {\n existingLoop.messages.push(msg)\n } else {\n currentGroup.childLoops.push({ loopName: loop, messages: [msg] })\n }\n }\n }\n\n return groups\n}\n","import { type } from \"arktype\"\nimport type { BladeClient } from \"../blade-client\"\n\nexport const ModelOption = type({\n id: \"string\",\n label: \"string\",\n})\nexport type ModelOption = typeof ModelOption.infer\n\nexport const ModelsConfig = type({\n default: \"string\",\n models: ModelOption.array(),\n})\n\nexport type ModelsConfig = typeof ModelsConfig.infer\n\nexport class ModelsResource {\n constructor(private client: BladeClient) {}\n\n async getModelsConfig(init?: RequestInit): Promise<ModelsConfig> {\n const data = await this.client.jsonFromInit<unknown>(\"/api/config/models\", init)\n return ModelsConfig.assert(data)\n }\n}\n","import { io, type Socket } from \"socket.io-client\"\nimport { buildSocketAuth, type AuthOptions } from \"./auth\"\nimport type { ClientToServerEvents, ServerToClientEvents } from \"./types/socket-events\"\n\nexport type TypedSocket = Socket<ServerToClientEvents, ClientToServerEvents>\n\nexport interface CreateSocketOptions extends AuthOptions {\n baseUrl: string\n path?: string\n}\n\nexport function createSocket(options: CreateSocketOptions): TypedSocket {\n const auth = buildSocketAuth(options)\n return io(options.baseUrl, {\n path: options.path ?? \"/socket.io\",\n withCredentials: true,\n auth: typeof options.token === \"function\" ? (cb) => cb(buildSocketAuth(options) ?? {}) : auth,\n autoConnect: false,\n })\n}\n","import { create } from \"zustand\"\nimport type { AskUserAnswerData } from \"../components/chat/AskUserQuestionBlock\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nexport type AnswerCallback = (\n answer: string,\n toolCallId: string,\n answerData: AskUserAnswerData,\n) => void\n\ninterface AnswerCallbackState extends ClientAwareState {\n callbacks: Record<string, AnswerCallback | undefined>\n setAnswerCallback: (sessionId: string, callback?: AnswerCallback) => void\n}\n\nexport const useAnswerCallbackStore = create<AnswerCallbackState>()((set) => ({\n ...createClientActions(set),\n callbacks: {},\n setAnswerCallback: (sessionId, callback) => {\n set((state) => ({\n callbacks: {\n ...state.callbacks,\n [sessionId]: callback,\n },\n }))\n },\n}))\n","import type { StoreApi } from \"zustand\"\nimport type { BladeClient } from \"../../client\"\n\nexport interface ClientAwareState {\n _client: BladeClient | null\n setClient: (client: BladeClient) => void\n}\n\nexport function createClientActions<T extends ClientAwareState>(\n set: StoreApi<T>[\"setState\"],\n): ClientAwareState {\n return {\n _client: null,\n setClient: (client) => set({ _client: client } as Partial<T>),\n }\n}\n","import { create } from \"zustand\"\nimport { createJSONStorage, persist } from \"zustand/middleware\"\nimport * as authApi from \"../api/auth\"\nimport { agentSocket } from \"../sockets/socket-state\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\nimport { useSessionStore } from \"./session-store\"\n\ninterface User {\n id: string\n username: string\n display_name?: string | null\n avatar_url: string | null\n is_admin?: boolean\n}\n\ninterface AuthState extends ClientAwareState {\n token: string | null\n socketAuthToken: string | null\n user: User | null\n loading: boolean\n error: string | null\n\n logout: () => void\n checkAuth: () => Promise<void>\n hydrateFromCookie: () => Promise<void>\n}\n\ntype PersistedAuthState = Pick<AuthState, \"token\" | \"user\">\n\nconst noopStorage = {\n getItem: () => null,\n setItem: () => {},\n removeItem: () => {},\n}\n\nfunction shouldClearPersistedAuthState(value: string): boolean {\n try {\n const parsed = JSON.parse(value) as {\n state?: PersistedAuthState | null\n }\n return parsed.state?.token == null && parsed.state?.user == null\n } catch {\n return false\n }\n}\n\nconst authStorage = createJSONStorage<PersistedAuthState>(() => {\n if (typeof localStorage === \"undefined\") {\n return noopStorage\n }\n\n return {\n getItem: (name) => localStorage.getItem(name),\n setItem: (name, value) => {\n if (shouldClearPersistedAuthState(value)) {\n localStorage.removeItem(name)\n return\n }\n\n localStorage.setItem(name, value)\n },\n removeItem: (name) => localStorage.removeItem(name),\n }\n})\n\nfunction finishAuth(set: (partial: Partial<AuthState>) => void, payload: { token: string; user: User }) {\n set({\n token: payload.token,\n socketAuthToken: null,\n user: payload.user,\n loading: false,\n error: null,\n })\n agentSocket?.reconnect()\n useSessionStore\n .getState()\n .fetchSessions()\n .catch(() => {})\n}\n\nfunction finishCookieHydration(\n set: (partial: Partial<AuthState>) => void,\n payload: { token: string; user: User },\n) {\n set({\n token: null,\n socketAuthToken: payload.token,\n user: payload.user,\n loading: false,\n error: null,\n })\n agentSocket?.reconnect()\n useSessionStore\n .getState()\n .fetchSessions()\n .catch(() => {})\n}\n\nfunction toUser(info: authApi.UserInfo): User {\n return {\n id: info.id,\n username: info.username,\n display_name: info.display_name,\n avatar_url: info.avatar_url,\n is_admin: info.is_admin,\n }\n}\n\nexport const useAuthStore = create<AuthState>()(\n persist(\n (set, get) => ({\n ...createClientActions(set),\n token: null,\n socketAuthToken: null,\n user: null,\n loading: false,\n error: null,\n\n logout: () => {\n void authApi.logout().catch(() => {})\n set({ token: null, socketAuthToken: null, user: null, error: null })\n agentSocket?.disconnect()\n useSessionStore.getState().reset()\n },\n\n checkAuth: async () => {\n const token = get().token\n if (!token) return\n try {\n const auth = await authApi.getMe()\n finishAuth(set, { token: auth.token, user: toUser(auth) })\n } catch {\n set({ token: null, socketAuthToken: null, user: null, error: null })\n useSessionStore.getState().reset()\n }\n },\n\n hydrateFromCookie: async () => {\n set({ loading: true, error: null })\n const previousToken = get().token\n\n if (previousToken) {\n try {\n const auth = await authApi.getMe()\n finishAuth(set, { token: auth.token, user: toUser(auth) })\n return\n } catch {\n set({ token: null, socketAuthToken: null, user: null, error: null })\n useSessionStore.getState().reset()\n }\n }\n\n try {\n const auth = await authApi.getMe()\n finishCookieHydration(set, { token: auth.token, user: toUser(auth) })\n } catch {\n set({\n token: null,\n socketAuthToken: null,\n user: null,\n loading: false,\n error: null,\n })\n useSessionStore.getState().reset()\n }\n },\n }),\n {\n name: \"agent-auth\",\n storage: authStorage,\n partialize: (state) => {\n if (state.socketAuthToken) {\n return { token: null, user: null }\n }\n return { token: state.token, user: state.user }\n },\n },\n ),\n)\n","import type { AuthResource } from \"../../client/resources/auth\"\nimport { getClient } from \"./client\"\nexport type * from \"../../client/resources/auth\"\n\nconst r = (): AuthResource => getClient().auth\nexport const getProviders = (...args: Parameters<AuthResource[\"getProviders\"]>) => r().getProviders(...args)\nexport const getMe = (...args: Parameters<AuthResource[\"getMe\"]>) => r().getMe(...args)\nexport const logout = (...args: Parameters<AuthResource[\"logout\"]>) => r().logout(...args)\n","import { create } from \"zustand\"\nimport * as sessionsApi from \"../api/sessions\"\nimport type { AskUserAnswerData } from \"../components/chat/AskUserQuestionBlock\"\nimport type { ContentBlock, TurnProjection } from \"../schemas/projection\"\nimport type { ModeId, SessionInfo, SessionStatus } from \"../schemas/session\"\nimport { setChatStoreSessionAccessor, useChatStore } from \"./chat-store\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\nimport { useTaskStore } from \"./task-store\"\n\nexport type SessionMode = ModeId\nconst DEFAULT_SESSION_MODE: SessionMode = \"executing\"\n\ntype QueryClientLike = {\n invalidateQueries: (options: { queryKey: readonly unknown[] }) => Promise<unknown>\n}\n\ninterface SessionState extends ClientAwareState {\n sessions: SessionInfo[]\n activeSessionId: string | null\n loading: boolean\n modes: Record<string, SessionMode>\n rewindDrafts: Record<string, string>\n /** Session IDs that were just created and haven't had their first history load yet */\n _freshSessions: Set<string>\n\n fetchSessions: () => Promise<void>\n createSession: (intent?: string) => Promise<string>\n registerCreatedSession: (session: SessionInfo, mode?: SessionMode) => void\n upsertSession: (session: SessionInfo) => void\n isFreshSession: (sessionId: string) => boolean\n setActiveSession: (id: string) => void\n clearActiveSession: () => void\n deleteSession: (id: string) => Promise<void>\n updateSessionStatus: (sessionId: string, status: SessionStatus) => void\n updateSessionIntent: (sessionId: string, intent: string) => void\n /**\n * ship-attack v2:通用增量更新 session 字段。用于 session:updated 等事件\n * 广播\"后端刚改了 session 元数据(intent / bound_skill_id / ...)\"时,\n * 前端原地 patch sessions 缓存,而不需要重新拉整个列表。\n */\n patchSession: (sessionId: string, patch: Partial<SessionInfo>) => void\n pinSession: (sessionId: string, pinned: boolean) => Promise<void>\n setRewindDraft: (sessionId: string, text: string | null) => void\n setMode: (sessionId: string, mode: SessionMode) => void\n togglePlanningMode: (sessionId: string) => void\n toggleSharing: (sessionId: string) => Promise<void>\n reset: () => void\n}\n\n// agentSocket will be set after socket init -- see socket.ts\nlet onSessionChange: ((sessionId: string | null) => void) | null = null\nexport function setOnSessionChange(fn: (sessionId: string | null) => void) {\n onSessionChange = fn\n}\n\n/** 侧栏等使用 React Query 拉取会话列表时,与 zustand patch 同步失效。 */\nexport function invalidateHomeSidebarSessions() {\n const queryClient = (globalThis as { __agentQueryClient?: QueryClientLike }).__agentQueryClient\n if (!queryClient) return\n void queryClient.invalidateQueries({ queryKey: [\"sessions\", \"home-sidebar\"] })\n}\n\nfunction isSessionAccessRevoked(error: unknown) {\n if (error instanceof Error) {\n const msg = error.message\n return msg.includes(\"API 403\") || msg.includes(\"API 404\")\n }\n return false\n}\n\nfunction removeSessionArtifacts(sessionId: string) {\n useChatStore.getState().clearMessages(sessionId)\n useTaskStore.getState().setTasks(sessionId, [])\n}\n\nfunction pruneSessionState(state: SessionState, sessionId: string) {\n const nextFresh = new Set(state._freshSessions)\n nextFresh.delete(sessionId)\n const { [sessionId]: _mode, ...modes } = state.modes\n const { [sessionId]: _rewindDraft, ...rewindDrafts } = state.rewindDrafts\n\n return {\n sessions: state.sessions.filter((session) => session.id !== sessionId),\n activeSessionId: state.activeSessionId === sessionId ? null : state.activeSessionId,\n modes,\n rewindDrafts,\n _freshSessions: nextFresh,\n }\n}\n\nfunction navigateAwayFromSession(sessionId: string) {\n if (typeof window === \"undefined\") return\n if (window.location.pathname !== `/chat/${sessionId}`) return\n window.history.replaceState(window.history.state, \"\", \"/chat\")\n window.dispatchEvent(new PopStateEvent(\"popstate\"))\n}\n\nfunction handleUnreadableSession(\n set: (\n partial:\n | Partial<SessionState>\n | ((state: SessionState) => Partial<SessionState> | SessionState),\n ) => void,\n get: () => SessionState,\n sessionId: string,\n) {\n const wasActive = get().activeSessionId === sessionId\n removeSessionArtifacts(sessionId)\n set((state) => pruneSessionState(state, sessionId))\n if (wasActive) {\n onSessionChange?.(null)\n navigateAwayFromSession(sessionId)\n }\n invalidateHomeSidebarSessions()\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction extractModeFromBlocks(blocks: ContentBlock[]): SessionMode | null {\n const modeBlock = blocks.find((block) => block.type === \"mode_change\")\n if (\n modeBlock &&\n isPlainRecord(modeBlock.content) &&\n (modeBlock.content.to === \"planning\" || modeBlock.content.to === \"executing\")\n ) {\n return modeBlock.content.to\n }\n if (blocks.some((block) => block.type === \"planning_enter\")) return \"planning\"\n if (blocks.some((block) => block.type === \"planning_exit\")) return \"executing\"\n return null\n}\n\nfunction toSelectionMap(value: unknown): Record<number, number[]> {\n if (!isPlainRecord(value)) return {}\n const entries = Object.entries(value)\n .map(([questionKey, optionIndexes]) => {\n if (!Array.isArray(optionIndexes)) return null\n const parsedIndexes = optionIndexes\n .map((item) => (typeof item === \"number\" ? item : Number(item)))\n .filter((item) => Number.isInteger(item))\n return [Number(questionKey), parsedIndexes] as const\n })\n .filter((entry): entry is readonly [number, number[]] => entry !== null)\n return Object.fromEntries(entries) as Record<number, number[]>\n}\n\nfunction toCustomMap(value: unknown): Record<number, string> {\n if (!isPlainRecord(value)) return {}\n const entries = Object.entries(value)\n .filter(([, text]) => typeof text === \"string\")\n .map(([questionKey, text]) => [Number(questionKey), text] as const)\n return Object.fromEntries(entries) as Record<number, string>\n}\n\nfunction extractAskAnswers(turns: TurnProjection[]): Record<string, AskUserAnswerData> {\n const answers: Record<string, AskUserAnswerData> = {}\n\n for (const turn of turns) {\n for (const block of turn.blocks) {\n if (block.type !== \"ask_user_answer\" || typeof block.tool_call_id !== \"string\") continue\n answers[block.tool_call_id] = {\n selections: toSelectionMap(isPlainRecord(block.content) ? block.content.selections : undefined),\n custom: toCustomMap(isPlainRecord(block.content) ? block.content.custom : undefined),\n }\n }\n }\n\n return answers\n}\n\nfunction registerCreatedSessionState(\n set: (\n partial:\n | Partial<SessionState>\n | ((state: SessionState) => Partial<SessionState> | SessionState),\n ) => void,\n session: SessionInfo,\n mode: SessionMode = DEFAULT_SESSION_MODE,\n) {\n useChatStore.getState().setTurns(session.id, [])\n useTaskStore.getState().setTasks(session.id, [])\n set((state) => ({\n sessions: [session, ...state.sessions.filter((item) => item.id !== session.id)],\n modes: { ...state.modes, [session.id]: state.modes[session.id] ?? mode },\n _freshSessions: new Set(state._freshSessions).add(session.id),\n }))\n}\n\nasync function revalidateViewerSessions(existingSessions: SessionInfo[]): Promise<SessionInfo[]> {\n const viewerSessions = existingSessions.filter((session) => session.viewer_role === \"viewer\")\n if (viewerSessions.length === 0) {\n return []\n }\n const refreshed = await Promise.all(\n viewerSessions.map(async (session) => {\n try {\n return await sessionsApi.getSession(session.id)\n } catch (error) {\n if (isSessionAccessRevoked(error)) {\n return null\n }\n return session\n }\n }),\n )\n return refreshed.filter((session): session is SessionInfo => session !== null)\n}\n\nexport const useSessionStore = create<SessionState>()((set, get) => ({\n ...createClientActions(set),\n sessions: [],\n activeSessionId: null,\n loading: false,\n modes: {},\n rewindDrafts: {},\n _freshSessions: new Set(),\n\n fetchSessions: async () => {\n set({ loading: true })\n try {\n const currentState = get()\n const [sessions, viewerSessions] = await Promise.all([\n sessionsApi.listSessions(),\n revalidateViewerSessions(currentState.sessions),\n ])\n const knownSessionIds = new Set(sessions.map((session) => session.id))\n const mergedSessions = [\n ...sessions,\n ...viewerSessions.filter((session) => !knownSessionIds.has(session.id)),\n ]\n const removedSessionIds = currentState.sessions\n .filter(\n (session) =>\n session.viewer_role === \"viewer\" &&\n !mergedSessions.some((candidate) => candidate.id === session.id),\n )\n .map((session) => session.id)\n const activeSessionId = currentState.activeSessionId\n\n for (const sessionId of removedSessionIds) {\n removeSessionArtifacts(sessionId)\n }\n\n let nextState: Partial<SessionState> = {\n sessions: mergedSessions,\n activeSessionId: currentState.activeSessionId,\n loading: false,\n modes: currentState.modes,\n rewindDrafts: currentState.rewindDrafts,\n _freshSessions: currentState._freshSessions,\n }\n for (const sessionId of removedSessionIds) {\n nextState = {\n ...nextState,\n ...pruneSessionState(\n {\n ...currentState,\n sessions: nextState.sessions ?? currentState.sessions,\n activeSessionId: nextState.activeSessionId ?? currentState.activeSessionId,\n loading: nextState.loading ?? currentState.loading,\n modes: nextState.modes ?? currentState.modes,\n rewindDrafts: nextState.rewindDrafts ?? currentState.rewindDrafts,\n _freshSessions: nextState._freshSessions ?? currentState._freshSessions,\n },\n sessionId,\n ),\n }\n }\n set(nextState)\n\n if (activeSessionId && removedSessionIds.includes(activeSessionId)) {\n onSessionChange?.(null)\n navigateAwayFromSession(activeSessionId)\n }\n\n invalidateHomeSidebarSessions()\n } catch (error) {\n set({ loading: false })\n throw error\n }\n },\n\n createSession: async (intent) => {\n const { session_id } = await sessionsApi.createSession(intent)\n const now = new Date().toISOString()\n get().registerCreatedSession({\n id: session_id,\n intent: intent ?? \"\",\n status: \"created\" as const,\n created_at: now,\n updated_at: now,\n })\n get().setActiveSession(session_id)\n invalidateHomeSidebarSessions()\n get()\n .fetchSessions()\n .catch(() => {})\n return session_id\n },\n\n registerCreatedSession: (session, mode = DEFAULT_SESSION_MODE) => {\n registerCreatedSessionState(set, session, mode)\n },\n\n upsertSession: (session) => {\n set((state) => ({\n sessions: state.sessions.some((item) => item.id === session.id)\n ? state.sessions.map((item) => (item.id === session.id ? { ...item, ...session } : item))\n : [session, ...state.sessions],\n }))\n },\n\n isFreshSession: (sessionId) => get()._freshSessions.has(sessionId),\n\n setActiveSession: (id) => {\n set({ activeSessionId: id })\n onSessionChange?.(id)\n // 切换 session 时后端可能已经走完了一轮对话但前端没订阅,sessions 列表里的\n // status 还停留在旧值(running/waiting_for_input 混乱)。异步拉一次 detail\n // 合回 sessions 数组,保证 AskUser 卡片的 answered 判定正确。\n sessionsApi\n .getSession(id)\n .then((detail) => {\n set((state) => ({\n sessions: state.sessions.some((s) => s.id === id)\n ? state.sessions.map((s) =>\n s.id === id\n ? { ...s, status: detail.status, updated_at: detail.updated_at }\n : s,\n )\n : [detail, ...state.sessions],\n }))\n })\n .catch(() => {})\n const tasksPromise = sessionsApi.getSessionTasks(id).catch(() => null)\n Promise.all([sessionsApi.getSessionTurns(id), tasksPromise])\n .then(([turns, tasks]) => {\n if (tasks) useTaskStore.getState().setTasks(id, tasks)\n useChatStore.getState().setAskAnswers(id, extractAskAnswers(turns))\n let inferredMode: SessionMode = DEFAULT_SESSION_MODE\n for (const turn of turns) {\n const nextMode = extractModeFromBlocks(turn.blocks)\n if (nextMode) {\n inferredMode = nextMode\n }\n }\n set((state) => {\n if (state.modes[id] == null) {\n return { modes: { ...state.modes, [id]: inferredMode } }\n }\n return state\n })\n\n // Skip overwriting messages for fresh sessions — the optimistic seed is\n // correct and the history response is empty; overwriting would erase any\n // message that was sent between create and this response arriving.\n const isFresh = get()._freshSessions.has(id)\n if (isFresh) {\n set((state) => {\n const next = new Set(state._freshSessions)\n next.delete(id)\n return { _freshSessions: next }\n })\n // Only apply if history is non-empty (e.g. resumed session)\n if (turns.length > 0) {\n useChatStore.getState().setTurns(id, turns)\n }\n } else {\n useChatStore.getState().setTurns(id, turns)\n }\n })\n .catch((error) => {\n if (isSessionAccessRevoked(error)) {\n handleUnreadableSession(set, get, id)\n return\n }\n console.error(\"Failed to load session data\", error)\n })\n },\n\n clearActiveSession: () => {\n set({ activeSessionId: null })\n onSessionChange?.(null)\n },\n\n deleteSession: async (id) => {\n await sessionsApi.deleteSession(id)\n invalidateHomeSidebarSessions()\n const wasActive = get().activeSessionId === id\n await get().fetchSessions()\n if (!wasActive) {\n return\n }\n\n const nextId = get().sessions[0]?.id ?? null\n if (nextId) {\n get().setActiveSession(nextId)\n return\n }\n\n get().clearActiveSession()\n },\n\n updateSessionStatus: (sessionId, status) => {\n set((state) => ({\n sessions: state.sessions.map((s) => (s.id === sessionId ? { ...s, status } : s)),\n }))\n // Only reset streaming on terminal statuses to avoid race conditions\n // where a stale status update from a previous run could cancel streaming\n // for a new in-flight run. The primary streaming reset is via chat:end;\n // this serves as a fallback for missed chat:end events.\n if (status === \"failed\" || status === \"interrupted\") {\n useChatStore.getState().setStreaming(sessionId, false)\n if (status === \"interrupted\") {\n useChatStore.getState().markInterrupted(sessionId)\n } else {\n useChatStore.getState().markFailed(sessionId)\n }\n }\n },\n\n updateSessionIntent: (sessionId, intent) => {\n set((state) => ({\n sessions: state.sessions.map((s) => (s.id === sessionId ? { ...s, intent } : s)),\n }))\n },\n\n patchSession: (sessionId, patch) => {\n set((state) => ({\n sessions: state.sessions.map((s) =>\n s.id === sessionId ? { ...s, ...patch } : s,\n ),\n }))\n },\n\n pinSession: async (sessionId, pinned) => {\n const updated = await sessionsApi.pinSession(sessionId, pinned)\n set((state) => ({\n sessions: state.sessions.map((s) =>\n s.id === sessionId\n ? { ...s, is_pinned: updated.is_pinned, pinned_at: updated.pinned_at }\n : s,\n ),\n }))\n invalidateHomeSidebarSessions()\n },\n\n setRewindDraft: (sessionId, text) => {\n set((state) => {\n if (text == null) {\n const { [sessionId]: _, ...rest } = state.rewindDrafts\n return { rewindDrafts: rest }\n }\n\n return {\n rewindDrafts: {\n ...state.rewindDrafts,\n [sessionId]: text,\n },\n }\n })\n },\n\n setMode: (sessionId, mode) => {\n set((state) => ({ modes: { ...state.modes, [sessionId]: mode } }))\n },\n\n togglePlanningMode: (sessionId) => {\n const current = get().modes[sessionId] ?? DEFAULT_SESSION_MODE\n const next = current === \"executing\" ? \"planning\" : \"executing\"\n set((state) => ({ modes: { ...state.modes, [sessionId]: next } }))\n },\n\n toggleSharing: async (sessionId) => {\n const session = get().sessions.find((s) => s.id === sessionId)\n if (!session) return\n const newShared = !session.shared\n const result = await sessionsApi.updateSharing(sessionId, newShared)\n set((state) => ({\n sessions: state.sessions.map((s) =>\n s.id === sessionId ? { ...s, shared: result.shared } : s,\n ),\n }))\n },\n\n reset: () => {\n set({\n sessions: [],\n activeSessionId: null,\n loading: false,\n modes: {},\n rewindDrafts: {},\n _freshSessions: new Set(),\n })\n invalidateHomeSidebarSessions()\n },\n}))\n\n// Wire up lazy accessor to break circular dependency with chat-store\nsetChatStoreSessionAccessor(() => useSessionStore.getState().activeSessionId)\n","import type { SessionsResource } from \"../../client/resources/sessions\"\nimport { getClient } from \"./client\"\nexport type * from \"../../client/resources/sessions\"\n\nconst r = (): SessionsResource => getClient().sessions\n\nexport const listSessions = (...args: Parameters<SessionsResource[\"listSessions\"]>) => r().listSessions(...args)\nexport const listSessionsPaginated = (...args: Parameters<SessionsResource[\"listSessionsPaginated\"]>) => r().listSessionsPaginated(...args)\nexport const listSessionsWithSkillData = (...args: Parameters<SessionsResource[\"listSessionsWithSkillData\"]>) => r().listSessionsWithSkillData(...args)\nexport const createSession = (...args: Parameters<SessionsResource[\"createSession\"]>) => r().createSession(...args)\nexport const createSessionWithRequest = (...args: Parameters<SessionsResource[\"createSessionWithRequest\"]>) => r().createSessionWithRequest(...args)\nexport const getSession = (...args: Parameters<SessionsResource[\"getSession\"]>) => r().getSession(...args)\nexport const updateSession = (...args: Parameters<SessionsResource[\"updateSession\"]>) => r().updateSession(...args)\nexport const pinSession = (...args: Parameters<SessionsResource[\"pinSession\"]>) => r().pinSession(...args)\nexport const startReplaySession = (...args: Parameters<SessionsResource[\"startReplaySession\"]>) => r().startReplaySession(...args)\nexport const updateReplaySession = (...args: Parameters<SessionsResource[\"updateReplaySession\"]>) => r().updateReplaySession(...args)\nexport const updateSharing = (...args: Parameters<SessionsResource[\"updateSharing\"]>) => r().updateSharing(...args)\nexport const updateSessionMemory = (...args: Parameters<SessionsResource[\"updateSessionMemory\"]>) => r().updateSessionMemory(...args)\nexport const createShare = (...args: Parameters<SessionsResource[\"createShare\"]>) => r().createShare(...args)\nexport const revokeShare = (...args: Parameters<SessionsResource[\"revokeShare\"]>) => r().revokeShare(...args)\nexport const getSharedSession = (...args: Parameters<SessionsResource[\"getSharedSession\"]>) => r().getSharedSession(...args)\nexport const getSessionTasks = (...args: Parameters<SessionsResource[\"getSessionTasks\"]>) => r().getSessionTasks(...args)\nexport const getSessionTurns = (...args: Parameters<SessionsResource[\"getSessionTurns\"]>) => r().getSessionTurns(...args)\nexport const getSessionContextStats = (...args: Parameters<SessionsResource[\"getSessionContextStats\"]>) => r().getSessionContextStats(...args)\nexport const getSessionHistory = (...args: Parameters<SessionsResource[\"getSessionHistory\"]>) => r().getSessionHistory(...args)\nexport const tokenizePrompt = (...args: Parameters<SessionsResource[\"tokenizePrompt\"]>) => r().tokenizePrompt(...args)\nexport const tokenizeMessages = (...args: Parameters<SessionsResource[\"tokenizeMessages\"]>) => r().tokenizeMessages(...args)\nexport const getSessionCheckpoints = (...args: Parameters<SessionsResource[\"getSessionCheckpoints\"]>) => r().getSessionCheckpoints(...args)\nexport const checkoutSession = (...args: Parameters<SessionsResource[\"checkoutSession\"]>) => r().checkoutSession(...args)\nexport const rewindSession = (...args: Parameters<SessionsResource[\"rewindSession\"]>) => r().rewindSession(...args)\nexport const switchBranch = (...args: Parameters<SessionsResource[\"switchBranch\"]>) => r().switchBranch(...args)\nexport const deleteSession = (...args: Parameters<SessionsResource[\"deleteSession\"]>) => r().deleteSession(...args)\nexport const listBackgroundTasks = (...args: Parameters<SessionsResource[\"listBackgroundTasks\"]>) => r().listBackgroundTasks(...args)\nexport const getBackgroundTask = (...args: Parameters<SessionsResource[\"getBackgroundTask\"]>) => r().getBackgroundTask(...args)\nexport const stopBackgroundTask = (...args: Parameters<SessionsResource[\"stopBackgroundTask\"]>) => r().stopBackgroundTask(...args)\nexport const listDir = (...args: Parameters<SessionsResource[\"listDir\"]>) => r().listDir(...args)\nexport const uploadFiles = (...args: Parameters<SessionsResource[\"uploadFiles\"]>) => r().uploadFiles(...args)\nexport const deleteFile = (...args: Parameters<SessionsResource[\"deleteFile\"]>) => r().deleteFile(...args)\nexport const writeFile = (...args: Parameters<SessionsResource[\"writeFile\"]>) => r().writeFile(...args)\nexport const renameFile = (...args: Parameters<SessionsResource[\"renameFile\"]>) => r().renameFile(...args)\nexport const copyFile = (...args: Parameters<SessionsResource[\"copyFile\"]>) => r().copyFile(...args)\nexport const shareFile = (...args: Parameters<SessionsResource[\"shareFile\"]>) => r().shareFile(...args)\nexport const getDownloadDirUrl = (...args: Parameters<SessionsResource[\"getDownloadDirUrl\"]>) => r().getDownloadDirUrl(...args)\nexport const exportSession = (...args: Parameters<SessionsResource[\"exportSession\"]>) => r().exportSession(...args)\nexport const previewImport = (...args: Parameters<SessionsResource[\"previewImport\"]>) => r().previewImport(...args)\nexport const importSession = (...args: Parameters<SessionsResource[\"importSession\"]>) => r().importSession(...args)\n","import { create } from \"zustand\"\nimport type { AskUserAnswerData } from \"../components/chat/AskUserQuestionBlock\"\nimport { formatToolName } from \"../components/chat/display-utils\"\nimport { normalizeMessageContent } from \"../lib/chat\"\nimport type { ChatMessage, CompactionInfo, MessageContent, ToolCallInfo } from \"../schemas/message\"\nimport type { ContentBlock, PatchEnvelope, TurnProjection } from \"../schemas/projection\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\nimport { useUiStore } from \"./ui-store\"\n\nlet _getActiveSessionId: (() => string | null) | null = null\n\nexport function setChatStoreSessionAccessor(fn: () => string | null) {\n _getActiveSessionId = fn\n}\n\nexport interface AgentLoopInfo {\n toolCallId: string\n description: string\n status: \"running\" | \"done\" | \"error\" | \"cancelled\" | \"awaiting_answer\"\n}\n\nexport interface ActiveCompactionState extends CompactionInfo {\n turn_id: string\n status: \"streaming\" | \"completed\" | \"paused\" | \"failed\" | \"interrupted\"\n}\n\ninterface ChatState extends ClientAwareState {\n turns: Record<string, TurnProjection[]>\n messages: Record<string, ChatMessage[]>\n askAnswers: Record<string, Record<string, AskUserAnswerData>>\n isStreaming: Record<string, boolean>\n agentLoops: Record<string, Record<string, AgentLoopInfo>>\n activeCompactions: Record<string, ActiveCompactionState | null>\n\n addUserMessage: (sessionId: string, content: MessageContent) => void\n setTurns: (sessionId: string, turns: TurnProjection[]) => void\n upsertTurn: (sessionId: string, turn: TurnProjection) => void\n applyTurnPatch: (sessionId: string, patch: PatchEnvelope) => void\n addErrorMessage: (sessionId: string, content: string) => void\n markInterrupted: (sessionId: string) => void\n markFailed: (sessionId: string) => void\n setStreaming: (sessionId: string, streaming: boolean) => void\n setAskAnswers: (sessionId: string, answers: Record<string, AskUserAnswerData>) => void\n clearMessages: (sessionId: string) => void\n}\n\nfunction parseAgentDescription(argumentsJson: string): string {\n try {\n return JSON.parse(argumentsJson)?.description ?? \"子智能体\"\n } catch {\n return \"子智能体\"\n }\n}\n\nfunction inferLoopStatusFromMessages(messages: ChatMessage[]): AgentLoopInfo[\"status\"] {\n const toolCalls = messages.flatMap((message) => message.tool_calls ?? [])\n if (messages.some((message) => message.status === \"streaming\")) return \"running\"\n if (toolCalls.some((toolCall) => toolCall.status === \"awaiting_answer\")) return \"awaiting_answer\"\n if (toolCalls.some((toolCall) => toolCall.status === \"error\")) return \"error\"\n if (toolCalls.some((toolCall) => toolCall.status === \"cancelled\")) return \"cancelled\"\n if (toolCalls.some((toolCall) => toolCall.status === \"pending\")) return \"running\"\n return \"done\"\n}\n\nfunction inferLoopStatusFromTurns(turns: TurnProjection[], messages: ChatMessage[]): AgentLoopInfo[\"status\"] {\n const latestAgentNotification = [...turns]\n .reverse()\n .flatMap((turn) => turn.blocks)\n .find((block) => {\n if (block.type !== \"system_notification\" || !isRecord(block.content)) return false\n return block.content.notification_type === \"agent:start\" || block.content.notification_type === \"agent:end\"\n })\n if (\n latestAgentNotification?.type === \"system_notification\" &&\n isRecord(latestAgentNotification.content)\n ) {\n const notificationType = latestAgentNotification.content.notification_type\n const status = latestAgentNotification.content.status\n if (notificationType === \"agent:start\" || status === \"running\") return \"running\"\n if (status === \"error\") return \"error\"\n if (status === \"cancelled\") return \"cancelled\"\n }\n return inferLoopStatusFromMessages(messages)\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction parentForkToolCallIdFromTurn(turn: TurnProjection): string | null {\n if (typeof turn.parent_fork_tool_call_id === \"string\" && turn.parent_fork_tool_call_id.length > 0) {\n return turn.parent_fork_tool_call_id\n }\n for (const block of turn.blocks) {\n if (block.type !== \"system_notification\" || !isRecord(block.content)) continue\n const metadata = block.content.metadata\n if (!isRecord(metadata)) continue\n const parentId = metadata.parent_fork_tool_call_id\n if (typeof parentId === \"string\" && parentId.length > 0) return parentId\n }\n return null\n}\n\nfunction buildMessageContent(turn: TurnProjection): MessageContent {\n const textBlocks = turn.blocks.filter((block) => block.type === \"text\")\n if (textBlocks.length === 0) return \"\"\n if (textBlocks.length === 1) return normalizeMessageContent(textBlocks[0].content)\n return textBlocks\n .map((block) => {\n if (typeof block.content === \"string\") return block.content\n return JSON.stringify(block.content)\n })\n .join(\"\")\n}\n\nfunction buildReasoning(turn: TurnProjection): string | undefined {\n const thinking = turn.blocks\n .filter((block) => block.type === \"thinking\")\n .map((block) => (typeof block.content === \"string\" ? block.content : JSON.stringify(block.content)))\n .filter(Boolean)\n if (thinking.length === 0) return undefined\n return thinking.join(\"\\n\\n\")\n}\n\nfunction isModeChangeContent(value: unknown): value is { from: string; to: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { from?: unknown }).from === \"string\" &&\n typeof (value as { to?: unknown }).to === \"string\"\n )\n}\n\nfunction extractModeFromBlocks(blocks: ContentBlock[]): \"planning\" | \"executing\" | null {\n const modeBlock = blocks.find((block) => block.type === \"mode_change\")\n if (modeBlock && isModeChangeContent(modeBlock.content)) {\n return modeBlock.content.to === \"planning\" || modeBlock.content.to === \"executing\"\n ? modeBlock.content.to\n : null\n }\n if (blocks.some((block) => block.type === \"planning_enter\")) return \"planning\"\n if (blocks.some((block) => block.type === \"planning_exit\")) return \"executing\"\n return null\n}\n\nfunction projectionToMessage(turn: TurnProjection): ChatMessage | null {\n if (turn.kind === \"compaction\" && turn.compaction_id) {\n return {\n role: \"assistant\",\n content: turn.summary_preview ?? \"\",\n kind: \"compaction\",\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n compaction: {\n compaction_id: turn.compaction_id,\n summary_preview: turn.summary_preview,\n summary_full: turn.summary_full,\n archived_count: turn.archived_count,\n archived_files: turn.archived_files,\n archived_tool_calls: turn.archived_tool_calls,\n tokens_before: turn.tokens_before,\n tokens_after: turn.tokens_after,\n saved_ratio: turn.saved_ratio,\n trigger: turn.trigger,\n failure_reason: turn.failure_reason,\n fallback_applied: turn.fallback_applied,\n },\n }\n }\n\n const planningBlock = turn.blocks.find(\n (block) =>\n block.type === \"mode_change\" ||\n block.type === \"planning_enter\" ||\n block.type === \"planning_exit\" ||\n block.type === \"plan_status\",\n )\n if (planningBlock) {\n if (planningBlock.type === \"plan_status\") {\n return {\n role: \"tool\",\n content:\n typeof planningBlock.content === \"string\"\n ? planningBlock.content\n : JSON.stringify(planningBlock.content ?? {}, null, 2),\n kind: \"plan_status\",\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n }\n }\n return {\n role: \"assistant\",\n content:\n planningBlock.type === \"mode_change\"\n ? typeof planningBlock.content === \"string\"\n ? planningBlock.content\n : JSON.stringify(planningBlock.content ?? {})\n : \"\",\n kind: planningBlock.type,\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n }\n }\n\n if (turn.blocks.some((block) => block.type === \"ask_user_answer\")) {\n return null\n }\n\n const content = buildMessageContent(turn)\n const reasoning = buildReasoning(turn)\n const toolCalls: ToolCallInfo[] | undefined =\n turn.tool_calls.length > 0\n ? turn.tool_calls.map((toolCall) => ({\n id: toolCall.id,\n name: toolCall.tool_name,\n display_name: toolCall.display_name,\n arguments: toolCall.arguments,\n result: toolCall.result ?? undefined,\n pending_question_ref: toolCall.pending_question_ref ?? undefined,\n status:\n toolCall.status === \"pending\" ||\n toolCall.status === \"awaiting_answer\" ||\n toolCall.status === \"done\" ||\n toolCall.status === \"error\" ||\n toolCall.status === \"cancelled\"\n ? toolCall.status\n : \"pending\",\n ...(typeof toolCall.duration_ms === \"number\" ? { duration_ms: toolCall.duration_ms } : {}),\n }))\n : undefined\n\n if (turn.role === \"system\" && !content && !toolCalls?.length) {\n return null\n }\n\n return {\n role: turn.role === \"system\" ? \"assistant\" : turn.role,\n content,\n blocks: turn.blocks,\n ...(reasoning ? { reasoning } : {}),\n ...(toolCalls ? { tool_calls: toolCalls } : {}),\n loop_name: turn.loop_id,\n entry_id: turn.turn_id,\n status: turn.status,\n ...(typeof turn.duration_ms === \"number\" ? { duration_ms: turn.duration_ms } : {}),\n ...(turn.started_at ? { timestamp: turn.started_at } : {}),\n ...(turn.memory_refs?.length ? { memory_refs: turn.memory_refs } : {}),\n }\n}\n\nfunction rebuildAgentLoops(turns: TurnProjection[]): Record<string, AgentLoopInfo> {\n const messages = turns.map(projectionToMessage).filter(Boolean) as ChatMessage[]\n const childLoopNames = [...new Set(turns.map((turn) => turn.loop_id).filter((name) => name !== \"root\"))]\n if (childLoopNames.length === 0) return {}\n\n const agentToolCalls = messages\n .filter((message) => message.role === \"assistant\" && (message.loop_name ?? \"root\") === \"root\")\n .flatMap((message) => message.tool_calls ?? [])\n .filter((toolCall) => formatToolName(toolCall.name) === \"Agent\")\n\n const loops: Record<string, AgentLoopInfo> = {}\n const agentToolCallsById = new Map(agentToolCalls.map((toolCall) => [toolCall.id, toolCall]))\n const explicitParentToolCallIds = new Set(\n turns.map(parentForkToolCallIdFromTurn).filter((id): id is string => id !== null),\n )\n const usedToolCallIds = new Set<string>()\n for (const loopName of childLoopNames) {\n const loopMessages = messages.filter((message) => (message.loop_name ?? \"root\") === loopName)\n const loopTurns = turns.filter((turn) => turn.loop_id === loopName)\n const parentToolCallId = loopTurns.map(parentForkToolCallIdFromTurn).find(Boolean)\n const explicitToolCall =\n parentToolCallId && !usedToolCallIds.has(parentToolCallId)\n ? (agentToolCallsById.get(parentToolCallId) ?? null)\n : null\n const fallbackToolCall =\n explicitToolCall === null\n ? agentToolCalls.find(\n (toolCall) => !usedToolCallIds.has(toolCall.id) && !explicitParentToolCallIds.has(toolCall.id),\n )\n : null\n const toolCall = explicitToolCall ?? fallbackToolCall\n if (!toolCall) continue\n usedToolCallIds.add(toolCall.id)\n loops[loopName] = {\n toolCallId: toolCall.id,\n description: parseAgentDescription(toolCall.arguments),\n status: inferLoopStatusFromTurns(loopTurns, loopMessages),\n }\n }\n return loops\n}\n\nfunction applyPlanningSideEffects(sessionId: string, turns: TurnProjection[]) {\n const latestMode = [...turns]\n .reverse()\n .map((turn) => extractModeFromBlocks(turn.blocks))\n .find((mode): mode is \"planning\" | \"executing\" => mode !== null)\n if (latestMode !== \"planning\") return\n if (_getActiveSessionId?.() !== sessionId) return\n const ui = useUiStore.getState()\n ui.setActiveRightTab(\"situation\")\n if (ui.rightPanelCollapsed) {\n ui.toggleRightPanel()\n }\n}\n\nfunction materialize(turns: TurnProjection[]) {\n const messages = turns\n .map(projectionToMessage)\n .filter((message): message is ChatMessage => message !== null)\n const activeCompaction = [...turns]\n .reverse()\n .find(\n (turn): turn is TurnProjection =>\n turn.kind === \"compaction\" && turn.status === \"streaming\" && typeof turn.compaction_id === \"string\",\n )\n return {\n messages,\n agentLoops: rebuildAgentLoops(turns),\n activeCompaction: activeCompaction\n ? {\n turn_id: activeCompaction.turn_id,\n status: activeCompaction.status,\n compaction_id: activeCompaction.compaction_id!,\n summary_preview: activeCompaction.summary_preview,\n summary_full: activeCompaction.summary_full,\n archived_count: activeCompaction.archived_count,\n archived_files: activeCompaction.archived_files,\n archived_tool_calls: activeCompaction.archived_tool_calls,\n tokens_before: activeCompaction.tokens_before,\n tokens_after: activeCompaction.tokens_after,\n saved_ratio: activeCompaction.saved_ratio,\n trigger: activeCompaction.trigger,\n failure_reason: activeCompaction.failure_reason,\n fallback_applied: activeCompaction.fallback_applied,\n }\n : null,\n }\n}\n\nconst ERROR_ANCHOR_PREFIX = \"error-anchor:\"\n\nfunction updateSessionState(state: ChatState, sessionId: string, turns: TurnProjection[]) {\n const orderedTurns = [...turns].sort((left, right) => left.sequence - right.sequence)\n const { messages, agentLoops, activeCompaction } = materialize(orderedTurns)\n applyPlanningSideEffects(sessionId, orderedTurns)\n // addErrorMessage 注入的 role===\"error\" 不在 turns 里,默认会被 materialize 抹掉。\n // 给每条 error 打上 turn_id 锚点(见 addErrorMessage),只保留锚点命中当前最后一个 turn 的 error:\n // - upsertTurn/applyTurnPatch 推进同一 turn:锚点仍命中 → 错误气泡保留\n // - 用户发新消息(addUserMessage 追加 user turn):最后一个 turn 变化 → 旧错误自动丢弃\n // - session rewind 到更早 checkpoint:锚点的 turn 已不在列表 → 旧错误自动丢弃\n // - 重连/reload 同一 session:最后一个 turn 仍是那个 failed turn → 错误气泡保留\n const lastTurnId = orderedTurns[orderedTurns.length - 1]?.turn_id ?? null\n const preservedErrors = lastTurnId\n ? (state.messages[sessionId] ?? []).filter(\n (m) =>\n m.role === \"error\" &&\n typeof m.entry_id === \"string\" &&\n m.entry_id.startsWith(`${ERROR_ANCHOR_PREFIX}${lastTurnId}:`),\n )\n : []\n const mergedMessages = preservedErrors.length > 0 ? [...messages, ...preservedErrors] : messages\n return {\n turns: { ...state.turns, [sessionId]: orderedTurns },\n messages: { ...state.messages, [sessionId]: mergedMessages },\n agentLoops: { ...state.agentLoops, [sessionId]: agentLoops },\n activeCompactions: { ...state.activeCompactions, [sessionId]: activeCompaction },\n }\n}\n\nexport const useChatStore = create<ChatState>()((set) => ({\n ...createClientActions(set),\n turns: {},\n messages: {},\n askAnswers: {},\n isStreaming: {},\n agentLoops: {},\n activeCompactions: {},\n\n addUserMessage: (sessionId, content) => {\n set((state) => {\n const existing = state.turns[sessionId] ?? []\n const turnId = `local-user-${Date.now()}`\n const optimisticTurn: TurnProjection = {\n id: turnId,\n sequence: Math.max(0, ...existing.map((turn) => turn.sequence)) + 1,\n turn_id: turnId,\n loop_id: \"root\",\n role: \"user\",\n status: \"completed\",\n blocks: [{ type: \"text\", content }],\n tool_calls: [],\n model: null,\n usage: null,\n duration_ms: 0,\n }\n return updateSessionState(state, sessionId, [...existing, optimisticTurn])\n })\n },\n\n setTurns: (sessionId, turns) => {\n set((state) => updateSessionState(state, sessionId, [...turns]))\n },\n\n upsertTurn: (sessionId, turn) => {\n set((state) => {\n const existing = [...(state.turns[sessionId] ?? [])]\n const index = existing.findIndex((item) => item.turn_id === turn.turn_id)\n if (index >= 0) {\n existing[index] = turn\n } else {\n existing.push(turn)\n }\n return {\n ...updateSessionState(state, sessionId, existing),\n }\n })\n },\n\n applyTurnPatch: (sessionId, patch) => {\n set((state) => {\n const turn = patch.data.turn\n if (!turn) return state\n\n const existing = [...(state.turns[sessionId] ?? [])]\n const index = existing.findIndex((item) => item.turn_id === turn.turn_id)\n const lastSequence = index >= 0 ? existing[index].sequence : null\n if (lastSequence !== null && patch.sequence <= lastSequence) {\n return state\n }\n\n const nextTurn = {\n ...turn,\n sequence: patch.sequence,\n }\n if (index >= 0) {\n existing[index] = nextTurn\n } else {\n existing.push(nextTurn)\n }\n return {\n ...updateSessionState(state, sessionId, existing),\n }\n })\n },\n\n addErrorMessage: (sessionId, content) => {\n set((state) => {\n const turns = state.turns[sessionId] ?? []\n const anchorTurnId = turns[turns.length - 1]?.turn_id ?? null\n // 用 entry_id 携带 turn_id 锚点,updateSessionState 据此决定错误气泡去留\n const entry_id = anchorTurnId\n ? `${ERROR_ANCHOR_PREFIX}${anchorTurnId}:${Date.now()}`\n : undefined\n return {\n messages: {\n ...state.messages,\n [sessionId]: [\n ...(state.messages[sessionId] ?? []),\n { role: \"error\", content, loop_name: \"root\", entry_id },\n ],\n },\n }\n })\n },\n\n markInterrupted: (sessionId) => {\n set((state) => {\n const turns = (state.turns[sessionId] ?? []).map((turn) => {\n if (turn.status !== \"streaming\") return turn\n return {\n ...turn,\n status: \"interrupted\" as const,\n tool_calls: turn.tool_calls.map((toolCall) =>\n toolCall.status === \"pending\" || toolCall.status === \"awaiting_answer\"\n ? { ...toolCall, status: \"cancelled\" as const }\n : toolCall,\n ),\n }\n })\n return {\n ...updateSessionState(state, sessionId, turns),\n }\n })\n },\n\n markFailed: (sessionId) => {\n set((state) => {\n const turns = (state.turns[sessionId] ?? []).map((turn) => {\n if (turn.status !== \"streaming\") return turn\n return {\n ...turn,\n status: \"failed\" as const,\n tool_calls: turn.tool_calls.map((toolCall) =>\n toolCall.status === \"pending\" || toolCall.status === \"awaiting_answer\"\n ? { ...toolCall, status: \"error\" as const }\n : toolCall,\n ),\n }\n })\n return {\n ...updateSessionState(state, sessionId, turns),\n }\n })\n },\n\n setStreaming: (sessionId, streaming) => {\n set((state) => ({\n isStreaming: { ...state.isStreaming, [sessionId]: streaming },\n }))\n },\n\n setAskAnswers: (sessionId, answers) => {\n set((state) => ({\n askAnswers: {\n ...state.askAnswers,\n [sessionId]: answers,\n },\n }))\n },\n\n clearMessages: (sessionId) => {\n set((state) => {\n const { [sessionId]: _turns, ...restTurns } = state.turns\n const { [sessionId]: _messages, ...restMessages } = state.messages\n const { [sessionId]: _answers, ...restAnswers } = state.askAnswers\n const { [sessionId]: _loops, ...restLoops } = state.agentLoops\n const { [sessionId]: _compaction, ...restCompactions } = state.activeCompactions\n return {\n turns: restTurns,\n messages: restMessages,\n askAnswers: restAnswers,\n agentLoops: restLoops,\n activeCompactions: restCompactions,\n }\n })\n },\n}))\n","import type { ChatMessage, ToolCallInfo } from \"../../schemas/message\"\n\nconst TOOL_NAME_ALIASES: Record<string, string> = {\n agent: \"Agent\",\n ask_user_question: \"AskUserQuestion\",\n bash: \"Bash\",\n bg_bash: \"BgBash\",\n edit: \"Edit\",\n exit_plan_mode: \"ExitPlanMode\",\n file_edit: \"Edit\",\n file_read: \"Read\",\n file_write: \"Write\",\n finish_task: \"FinishTask\",\n get_skill_content: \"GetSkillContent\",\n glob: \"Glob\",\n grep: \"Grep\",\n list_skill_tools: \"ListSkillTools\",\n load_skill_tools: \"LoadSkillTools\",\n ls: \"Ls\",\n read: \"Read\",\n run_skill_tool: \"RunSkillTool\",\n search_skills: \"SearchSkills\",\n web_fetch: \"WebFetch\",\n web_search: \"WebSearch\",\n write: \"Write\",\n}\n\n/** System tool Chinese display labels */\nconst TOOL_DISPLAY_LABELS: Record<string, string> = {\n Bash: \"执行命令\",\n BgBash: \"后台执行命令\",\n Read: \"读取文件\",\n Write: \"写入文件\",\n Edit: \"编辑文件\",\n Ls: \"列出目录\",\n Glob: \"匹配文件\",\n Grep: \"搜索文本\",\n WebSearch: \"搜索网页\",\n WebFetch: \"整理网页内容\",\n Agent: \"派生子智能体\",\n AskUserQuestion: \"向用户提问\",\n SearchSkills: \"搜索技能\",\n GetSkillContent: \"读取技能\",\n ListSkillTools: \"查看工具列表\",\n LoadSkillTools: \"加载技能\",\n RunSkillTool: \"执行技能工具\",\n FinishTask: \"任务完成\",\n ExitPlanMode: \"提交计划\",\n ListSessions: \"列出历史会话\",\n GetSessionHistory: \"读取会话历史\",\n}\n\n/** Summary format: \"动词 + N + 量词\" style, e.g. \"读取 4 个技能\" */\nconst TOOL_SUMMARY_TEMPLATES: Record<string, (n: number) => string> = {\n Bash: (n) => `执行 ${n} 条命令`,\n BgBash: (n) => `启动 ${n} 个后台任务`,\n Read: (n) => `读取 ${n} 个文件`,\n Write: (n) => `写入 ${n} 个文件`,\n Edit: (n) => `编辑 ${n} 个文件`,\n Ls: (n) => `查看 ${n} 个目录`,\n Glob: (n) => `匹配 ${n} 组文件`,\n Grep: (n) => `搜索 ${n} 次文本`,\n WebSearch: (n) => `搜索 ${n} 次网页`,\n WebFetch: (n) => `整理 ${n} 次网页`,\n SearchSkills: (n) => `搜索 ${n} 次技能`,\n GetSkillContent: (n) => `读取 ${n} 个技能`,\n ListSkillTools: (n) => `查看 ${n} 个工具列表`,\n RunSkillTool: (n) => `执行 ${n} 个技能工具`,\n Agent: (n) => `调用 ${n} 个子智能体`,\n}\n\nconst OUTPUT_TOOL_ICONS: Record<string, string> = {\n Write: \"📄\",\n Edit: \"📝\",\n}\n\nconst PRIORITY_FILE_KEYS = [\n \"file_path\",\n \"output_file\",\n \"output_path\",\n \"path\",\n \"filepath\",\n \"target_file\",\n \"destination\",\n \"filename\",\n]\n\nconst FILE_PATH_PATTERN =\n /(?:^|[\\s\"'`::])([^\\s\"'`,;:)\\]},。;、]+?\\.[a-z0-9]{1,8})(?=$|[\\s\"'`,.;:)\\]},。;、])/i\n\nexport type ToolTone = \"emerald\" | \"blue\" | \"amber\" | \"red\"\n\nexport interface ToolSummaryTag {\n key: string\n label: string\n tone: \"emerald\" | \"blue\"\n}\n\nconst INDIVIDUAL_SUMMARY_TOOL_NAMES = new Set([\"RunSkillTool\", \"Bash\", \"BgBash\"])\n\nfunction safeParseJson(value: string | null | undefined): unknown {\n if (!value) return null\n try {\n return JSON.parse(value)\n } catch {\n return null\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction getStringArgValue(args: Record<string, unknown> | null, key: string): string {\n const value = args?.[key]\n return typeof value === \"string\" ? value.trim() : \"\"\n}\n\n/** Generic spec labels that should NOT be treated as per-call display names. */\nconst GENERIC_DISPLAY_NAMES = new Set(Object.values(TOOL_DISPLAY_LABELS))\n\nfunction getRunSkillDisplayName(\n toolCall: ToolCallInfo,\n args: Record<string, unknown> | null,\n): string {\n // Prefer per-call display name from arguments over the spec-level generic label.\n const argDisplayName = getStringArgValue(args, \"display_name\")\n if (argDisplayName) return argDisplayName\n\n // Only use toolCall.display_name if it's not a generic spec label\n const displayName = toolCall.display_name?.trim() ?? \"\"\n if (displayName && (displayName === \"写入文件\" || !GENERIC_DISPLAY_NAMES.has(displayName))) {\n return displayName\n }\n\n const argToolName = getStringArgValue(args, \"tool_name\")\n if (argToolName) return argToolName\n\n return \"\"\n}\n\nfunction getCommandDescription(args: Record<string, unknown> | null): string {\n return getStringArgValue(args, \"description\")\n}\n\nfunction findFileLikeValue(value: unknown, depth = 0, allowPlainString = false): string | null {\n if (depth > 3) return null\n if (typeof value === \"string\") {\n const trimmed = value.trim()\n if (!trimmed) return null\n if (allowPlainString || trimmed.includes(\"/\") || /\\.[a-z0-9]{1,8}$/i.test(trimmed)) {\n return trimmed\n }\n return null\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n const found = findFileLikeValue(item, depth + 1, allowPlainString)\n if (found) return found\n }\n return null\n }\n if (isPlainObject(value)) {\n for (const key of PRIORITY_FILE_KEYS) {\n const direct = findFileLikeValue(value[key], depth + 1, true)\n if (direct) return direct\n }\n for (const nested of Object.values(value)) {\n const found = findFileLikeValue(nested, depth + 1, allowPlainString)\n if (found) return found\n }\n }\n return null\n}\n\nfunction extractFilePathFromText(text: string): string | null {\n return text.match(FILE_PATH_PATTERN)?.[1] ?? null\n}\n\nfunction extractFilePathFromResult(result: unknown): string | null {\n if (typeof result === \"string\") {\n const parsed = safeParseJson(result)\n if (parsed != null && parsed !== result) {\n const found = extractFilePathFromResult(parsed)\n if (found) return found\n }\n return extractFilePathFromText(result)\n }\n if (Array.isArray(result)) {\n for (const item of result) {\n const found = extractFilePathFromResult(item)\n if (found) return found\n }\n return null\n }\n if (isPlainObject(result)) {\n for (const key of PRIORITY_FILE_KEYS) {\n const direct = findFileLikeValue(result[key], 0, true)\n if (direct) return direct\n }\n for (const nested of Object.values(result)) {\n const found = extractFilePathFromResult(nested)\n if (found) return found\n }\n }\n return null\n}\n\nfunction isWriteLikeRunSkillTool(label: string, args: Record<string, unknown> | null): boolean {\n const normalizedLabel = label.trim()\n if (normalizedLabel === \"写入文件\" || /write/i.test(normalizedLabel)) return true\n\n const toolName = getStringArgValue(args, \"tool_name\")\n if (/write/i.test(toolName)) return true\n\n return false\n}\n\nfunction formatFileName(filePath: string): string {\n return filePath.split(\"/\").pop() ?? filePath\n}\n\nfunction isInternalStatusFile(filePath: string): boolean {\n const fileName = formatFileName(filePath).toLowerCase()\n return fileName === \"phase.json\"\n}\n\nexport function formatToolName(name: string): string {\n const trimmed = name.trim()\n if (!trimmed) return name\n\n const stripped =\n trimmed.split(\":\").pop()?.split(\"/\").pop()?.split(\".\").pop()?.trim() || trimmed\n const normalized = stripped\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toLowerCase()\n\n return TOOL_NAME_ALIASES[normalized] ?? stripped\n}\n\n/**\n * Returns a context-aware Chinese display label for a tool call.\n * Uses tool arguments to provide specific context (e.g., skill name, file path).\n */\nexport function getToolDisplayLabel(toolCall: ToolCallInfo): string {\n const normalized = formatToolName(toolCall.name)\n const args = safeParseJson(toolCall.arguments) as Record<string, unknown> | null\n const displayName = toolCall.display_name?.trim() ?? \"\"\n const baseLabel = displayName || TOOL_DISPLAY_LABELS[normalized] || normalized\n const metaDisplayName = getStringArgValue(args, \"_meta_display_name\")\n if (metaDisplayName) {\n return metaDisplayName\n }\n\n switch (normalized) {\n case \"RunSkillTool\": {\n const runSkillDisplayName = getRunSkillDisplayName(toolCall, args)\n if (runSkillDisplayName) {\n const filePath = extractToolFilePath(toolCall)\n if (filePath && isWriteLikeRunSkillTool(runSkillDisplayName, args)) {\n return `${runSkillDisplayName}「${formatFileName(filePath)}」`\n }\n return runSkillDisplayName\n }\n return \"执行技能工具\"\n }\n case \"Bash\": {\n const description = getCommandDescription(args)\n return description ? `执行命令行操作:${description}` : \"执行命令行操作\"\n }\n case \"BgBash\": {\n const description = getCommandDescription(args)\n return description ? `后台执行:${description}` : \"后台执行命令\"\n }\n case \"Ls\": {\n const path = args && typeof args.path === \"string\" ? args.path : \"\"\n return path ? `${baseLabel}「${path}」` : baseLabel\n }\n case \"Glob\": {\n const pattern = args && typeof args.pattern === \"string\" ? args.pattern : \"\"\n return pattern ? `${baseLabel}「${pattern}」` : baseLabel\n }\n case \"Grep\": {\n const pattern = args && typeof args.pattern === \"string\" ? args.pattern : \"\"\n return pattern ? `${baseLabel}「${pattern}」` : baseLabel\n }\n case \"WebSearch\":\n case \"WebFetch\": {\n const query = args && typeof args.query === \"string\" ? args.query : \"\"\n return query ? `${baseLabel}「${query}」` : baseLabel\n }\n case \"GetSkillContent\": {\n const skillName =\n args && typeof args.skill_id === \"string\"\n ? args.skill_id\n : args && typeof args.skill_name === \"string\"\n ? args.skill_name\n : \"\"\n return skillName ? `${baseLabel}「${skillName}」` : baseLabel\n }\n case \"SearchSkills\": {\n const query = args && typeof args.query === \"string\" ? args.query : \"\"\n return query ? `${baseLabel}「${query}」` : baseLabel\n }\n case \"ListSkillTools\": {\n const skillId = args && typeof args.skill_id === \"string\" ? args.skill_id : \"\"\n return skillId ? `${baseLabel}「${skillId}」` : baseLabel\n }\n case \"LoadSkillTools\":\n return \"加载技能\"\n case \"FinishTask\": {\n const title = args && typeof args.title === \"string\" ? args.title : \"\"\n return title ? `${baseLabel}:${title}` : baseLabel\n }\n default:\n return baseLabel\n }\n}\n\nexport function getToolTone(status?: ToolCallInfo[\"status\"]): ToolTone {\n if (status === \"error\" || status === \"cancelled\") return \"red\"\n if (status === \"awaiting_answer\") return \"amber\"\n if (status === \"pending\") return \"blue\"\n return \"emerald\"\n}\n\nexport function getToolStatusLabel(status?: ToolCallInfo[\"status\"]): string {\n if (status === \"pending\") return \"运行中\"\n if (status === \"awaiting_answer\") return \"等待回答\"\n if (status === \"error\") return \"错误\"\n if (status === \"cancelled\") return \"已取消\"\n return \"完成\"\n}\n\nexport function getAggregateToolTone(toolCalls: ToolCallInfo[]): ToolTone {\n if (\n toolCalls.some((toolCall) => toolCall.status === \"error\" || toolCall.status === \"cancelled\")\n ) {\n return \"red\"\n }\n if (toolCalls.some((toolCall) => toolCall.status === \"awaiting_answer\")) {\n return \"amber\"\n }\n if (toolCalls.some((toolCall) => toolCall.status === \"pending\")) {\n return \"blue\"\n }\n return \"emerald\"\n}\n\nexport function extractToolFilePath(toolCall: ToolCallInfo): string | null {\n const formattedName = formatToolName(toolCall.name)\n const argsValue = safeParseJson(toolCall.arguments)\n let filePath: string | null = null\n\n if (formattedName === \"Read\" || formattedName === \"Write\" || formattedName === \"Edit\") {\n filePath = findFileLikeValue(argsValue)\n } else if (formattedName === \"RunSkillTool\") {\n filePath = findFileLikeValue(argsValue) ?? extractFilePathFromResult(toolCall.result)\n }\n\n if (!filePath || isInternalStatusFile(filePath)) return null\n return filePath\n}\n\nexport function getToolOutputTag(toolCall: ToolCallInfo): ToolSummaryTag | null {\n const toolName = formatToolName(toolCall.name)\n const filePath = extractToolFilePath(toolCall)\n const icon = OUTPUT_TOOL_ICONS[toolName]\n\n if (!icon || !filePath) return null\n\n return {\n key: `${toolCall.id}-${filePath}`,\n label: `${icon} ${filePath.split(\"/\").pop() ?? filePath}`,\n tone: \"blue\",\n }\n}\n\nexport function isSuccessfulToolCall(toolCall: ToolCallInfo): boolean {\n if (toolCall.status === \"error\" || toolCall.status === \"cancelled\") return false\n if (toolCall.status === \"awaiting_answer\") return false\n if (toolCall.status === \"pending\") return false\n return toolCall.status === \"done\" || toolCall.result != null || toolCall.status == null\n}\n\nexport function countSuccessfulToolCalls(toolCalls: ToolCallInfo[]): number {\n return toolCalls.filter(isSuccessfulToolCall).length\n}\n\nexport function countPendingToolCalls(toolCalls: ToolCallInfo[]): number {\n return toolCalls.filter(\n (toolCall) => toolCall.status === \"pending\" || toolCall.status === \"awaiting_answer\",\n ).length\n}\n\nexport function formatToolCallCount(count: number): string {\n return `已执行 ${count} 次工具调用`\n}\n\nexport function summarizeToolCalls(toolCalls: ToolCallInfo[]): ToolSummaryTag[] {\n const outputTagMap = new Map<string, ToolSummaryTag>()\n const counts = new Map<string, number>()\n const individualTags: ToolSummaryTag[] = []\n\n for (const toolCall of toolCalls.filter(isSuccessfulToolCall)) {\n const normalized = formatToolName(toolCall.name)\n const args = safeParseJson(toolCall.arguments) as Record<string, unknown> | null\n\n if (normalized === \"Agent\" || normalized === \"FinishTask\") continue\n\n if (INDIVIDUAL_SUMMARY_TOOL_NAMES.has(normalized)) {\n if (normalized === \"RunSkillTool\") {\n const runSkillDisplayName = getRunSkillDisplayName(toolCall, args)\n const filePath = extractToolFilePath(toolCall)\n if (filePath && isWriteLikeRunSkillTool(runSkillDisplayName, args)) {\n individualTags.push({\n key: `${individualTags.length}-${toolCall.id}`,\n label: `📄 ${formatFileName(filePath)}`,\n tone: \"blue\",\n })\n continue\n }\n individualTags.push({\n key: `${individualTags.length}-${toolCall.id}`,\n label: runSkillDisplayName || \"执行技能工具\",\n tone: \"emerald\",\n })\n continue\n }\n\n if (normalized === \"Bash\") {\n individualTags.push({\n key: `${individualTags.length}-${toolCall.id}`,\n label: getCommandDescription(args) || \"执行命令行操作\",\n tone: \"emerald\",\n })\n continue\n }\n\n if (normalized === \"BgBash\") {\n individualTags.push({\n key: `${individualTags.length}-${toolCall.id}`,\n label: getCommandDescription(args) || \"后台执行命令\",\n tone: \"emerald\",\n })\n continue\n }\n }\n\n const outputTag = getToolOutputTag(toolCall)\n if (outputTag) {\n const fileLabel = outputTag.label.replace(/^[^\\s]+\\s+/, \"\")\n const existing = outputTagMap.get(fileLabel)\n if (existing?.label.startsWith(\"📄\")) {\n continue\n }\n outputTagMap.set(fileLabel, {\n ...outputTag,\n key: fileLabel,\n label:\n normalized === \"Write\" ||\n existing?.label.startsWith(\"📝\")\n ? `📄 ${fileLabel}`\n : outputTag.label,\n })\n continue\n }\n\n counts.set(normalized, (counts.get(normalized) ?? 0) + 1)\n }\n\n const aggregatedCountTags: ToolSummaryTag[] = []\n for (const [normalized, count] of counts.entries()) {\n const template = TOOL_SUMMARY_TEMPLATES[normalized]\n const label = template ? template(count) : `${TOOL_DISPLAY_LABELS[normalized] ?? normalized} ×${count}`\n aggregatedCountTags.push({\n key: `${normalized}-${count}`,\n label,\n tone: \"emerald\",\n })\n }\n\n const outputTags = [...outputTagMap.values()].sort((left, right) =>\n left.label.localeCompare(right.label),\n )\n const sortedCountTags = aggregatedCountTags.sort((left, right) =>\n left.label.localeCompare(right.label),\n )\n const merged = [...individualTags, ...outputTags, ...sortedCountTags]\n\n if (merged.length <= 5) return merged\n\n return [\n ...merged.slice(0, 5),\n {\n key: `overflow-${merged.length - 5}`,\n label: `+${merged.length - 5} 更多`,\n tone: \"emerald\",\n },\n ]\n}\n\nfunction getMessageText(message: ChatMessage): string {\n if (typeof message.content === \"string\") return message.content\n return message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n}\n\nexport function hasNaturalLanguageText(message: ChatMessage): boolean {\n return getMessageText(message).trim().length > 0\n}\n\nexport function findAnchorMessageIndex(messages: ChatMessage[]): number {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (hasNaturalLanguageText(messages[index])) {\n return index\n }\n }\n return Math.max(messages.length - 1, 0)\n}\n\nexport function getCollapsedTurnSegments(messages: ChatMessage[]): {\n anchorIndex: number\n summaryMessages: ChatMessage[]\n visibleMessages: ChatMessage[]\n} {\n if (messages.length === 0) {\n return { anchorIndex: 0, summaryMessages: [], visibleMessages: [] }\n }\n\n const anchorIndex = findAnchorMessageIndex(messages)\n return {\n anchorIndex,\n summaryMessages: messages.slice(0, anchorIndex),\n visibleMessages: messages.slice(anchorIndex),\n }\n}\n\nexport function getLatestPendingToolName(toolCalls: ToolCallInfo[]): string | null {\n for (let index = toolCalls.length - 1; index >= 0; index -= 1) {\n if (\n toolCalls[index].status === \"pending\" ||\n toolCalls[index].status === \"awaiting_answer\"\n ) {\n return formatToolName(toolCalls[index].name)\n }\n }\n return null\n}\n\nexport function getFinishTaskTitle(toolCalls: ToolCallInfo[]): string | null {\n for (let index = toolCalls.length - 1; index >= 0; index -= 1) {\n if (formatToolName(toolCalls[index].name) !== \"FinishTask\") continue\n const args = safeParseJson(toolCalls[index].arguments)\n if (!isPlainObject(args)) continue\n const title = typeof args.title === \"string\" ? args.title.trim() : \"\"\n if (title) return title\n }\n return null\n}\n\nexport function getTextContentSegments(messages: ChatMessage[]): string[] {\n return messages\n .map((message) => {\n if (typeof message.content === \"string\") return message.content\n return message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n })\n .map((text) => text.trim())\n .filter(Boolean)\n}\n\nexport function getLastTextSegment(messages: ChatMessage[]): string {\n const texts = getTextContentSegments(messages)\n return texts[texts.length - 1] ?? \"\"\n}\n\nexport function countMessageLines(message: ChatMessage): number {\n const text = typeof message.content === \"string\" ? message.content : \"\"\n const reasoningLines = message.reasoning ? message.reasoning.split(\"\\n\").length : 0\n const textLines = text.trim() ? text.trim().split(\"\\n\").length : 0\n const toolLines = message.tool_calls?.length ?? 0\n return reasoningLines + textLines + toolLines\n}\n","import { create } from \"zustand\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\ntype ThemeValue = \"light\" | \"dark\" | \"system\"\n\nconst isBrowser = typeof window !== \"undefined\" && typeof document !== \"undefined\"\n\nexport function resolveEffectiveTheme(theme: ThemeValue): \"light\" | \"dark\" {\n if (theme !== \"system\") return theme\n return isBrowser && window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\"\n}\n\nfunction applyTheme(theme: ThemeValue) {\n if (!isBrowser) return\n const effective = resolveEffectiveTheme(theme)\n document.documentElement.setAttribute(\"data-theme\", effective)\n}\n\n// Initialize theme from localStorage before store creation\nconst storedTheme = isBrowser\n ? (localStorage.getItem(\"blade-theme\") as ThemeValue | null) ?? \"light\"\n : \"light\"\napplyTheme(storedTheme)\n\n// Listen for system preference changes\nif (isBrowser) {\n window.matchMedia(\"(prefers-color-scheme: dark)\").addEventListener(\"change\", () => {\n const current = useUiStore?.getState?.()?.theme\n if (current === \"system\") applyTheme(\"system\")\n })\n}\n\nexport interface PreviewTarget {\n type:\n | \"file\"\n | \"markdown\"\n | \"image\"\n | \"url\"\n | \"html\"\n | \"resource-html\"\n | \"resource-uri\"\n | \"diff\"\n | \"pdf\"\n | \"docx\"\n | \"video\"\n | \"audio\"\n | \"download\"\n | \"card\"\n | \"excel\"\n | \"csv\"\n | \"ppt\"\n content: string\n title?: string\n /** Stable identity key for tab deduplication (e.g. file_path). Falls back to title. */\n key?: string\n /** For diff type: the old content before edit */\n oldContent?: string\n /** Optional bridge session binding for resource iframes. */\n bridgeSessionId?: string\n /** Original source file URL when preview content uses a derived representation (e.g. PPT -> PDF). */\n sourceUrl?: string\n /** Changes when an artifact with the same key is updated in place. */\n revision?: number\n}\n\nexport type ActiveRightTab = \"situation\" | \"preview\" | \"skill-test\" | \"vibe-service\" | \"vibe-preview\"\n\ninterface UpsertArtifactOptions {\n reveal?: boolean\n activate?: boolean\n}\n\ninterface UiState extends ClientAwareState {\n leftPanelSize: number\n rightPanelSize: number\n leftPanelCollapsed: boolean\n rightPanelCollapsed: boolean\n activeRightTab: ActiveRightTab\n /** All open artifact tabs */\n artifacts: PreviewTarget[]\n /** Index of the active tab (-1 if none) */\n activeArtifactIndex: number\n theme: ThemeValue\n\n setLeftPanelSize: (size: number) => void\n setRightPanelSize: (size: number) => void\n setLeftPanelCollapsed: (collapsed: boolean) => void\n setRightPanelCollapsed: (collapsed: boolean) => void\n toggleLeftPanel: () => void\n toggleRightPanel: () => void\n setActiveRightTab: (tab: ActiveRightTab) => void\n /** Add or update an artifact tab (matched by key/title). Opens the panel automatically. */\n pushArtifact: (target: PreviewTarget) => void\n /** Add or update an artifact tab with optional reveal/activate control. */\n upsertArtifact: (target: PreviewTarget, options?: UpsertArtifactOptions) => void\n /** Switch to a tab by index */\n setActiveArtifact: (index: number) => void\n /** Close a tab by index */\n closeArtifact: (index: number) => void\n /** Close a tab by stable key if it exists. */\n removeArtifactByKey: (key: string) => void\n /** Close all tabs and collapse panel */\n clearArtifacts: () => void\n /** Legacy single-target setter for backwards compat */\n setPreviewTarget: (target: PreviewTarget | null) => void\n setTheme: (theme: ThemeValue) => void\n}\n\nfunction removeArtifactAtIndex(state: UiState, index: number) {\n const next = state.artifacts.filter((_: PreviewTarget, i: number) => i !== index)\n let nextActive = state.activeArtifactIndex\n\n if (next.length === 0) {\n return { artifacts: [], activeArtifactIndex: -1, rightPanelCollapsed: true }\n }\n\n if (index < nextActive) {\n nextActive -= 1\n } else if (index === nextActive) {\n nextActive = Math.min(index, next.length - 1)\n }\n\n return { artifacts: next, activeArtifactIndex: nextActive }\n}\n\nfunction upsertArtifactState(state: UiState, target: PreviewTarget, options?: UpsertArtifactOptions) {\n const reveal = options?.reveal ?? true\n const activate = options?.activate ?? true\n const targetKey = target.key ?? target.title\n const applyUiState = (partial: {\n artifacts: PreviewTarget[]\n activeArtifactIndex?: number\n }) => ({\n ...partial,\n ...(reveal ? { rightPanelCollapsed: false, activeRightTab: \"preview\" as const } : {}),\n })\n\n const existing = state.artifacts.findIndex((artifact) => targetKey && (artifact.key ?? artifact.title) === targetKey)\n if (existing >= 0) {\n const updated = [...state.artifacts]\n updated[existing] = target\n return applyUiState({\n artifacts: updated,\n activeArtifactIndex: activate ? existing : state.activeArtifactIndex,\n })\n }\n\n const next = [...state.artifacts, target]\n return applyUiState({\n artifacts: next,\n activeArtifactIndex: activate ? next.length - 1 : state.activeArtifactIndex >= 0 ? state.activeArtifactIndex : 0,\n })\n}\n\nexport const useUiStore = create<UiState>()((set) => ({\n ...createClientActions(set),\n leftPanelSize: 20,\n rightPanelSize: 25,\n leftPanelCollapsed: false,\n rightPanelCollapsed: false,\n activeRightTab: \"situation\",\n artifacts: [],\n activeArtifactIndex: -1,\n theme: storedTheme,\n\n setLeftPanelSize: (size) => set({ leftPanelSize: size }),\n setRightPanelSize: (size) => set({ rightPanelSize: size }),\n setLeftPanelCollapsed: (collapsed) => set({ leftPanelCollapsed: collapsed }),\n setRightPanelCollapsed: (collapsed) => set({ rightPanelCollapsed: collapsed }),\n toggleLeftPanel: () => set((s) => ({ leftPanelCollapsed: !s.leftPanelCollapsed })),\n toggleRightPanel: () => set((s) => ({ rightPanelCollapsed: !s.rightPanelCollapsed })),\n setActiveRightTab: (tab) => set({ activeRightTab: tab }),\n\n pushArtifact: (target) => set((state) => upsertArtifactState(state, target)),\n\n upsertArtifact: (target, options) => set((state) => upsertArtifactState(state, target, options)),\n\n setActiveArtifact: (index) => set({ activeArtifactIndex: index }),\n\n closeArtifact: (index) => set((state) => removeArtifactAtIndex(state, index)),\n\n removeArtifactByKey: (key) =>\n set((state) => {\n const index = state.artifacts.findIndex((artifact) => (artifact.key ?? artifact.title) === key)\n if (index < 0) return state\n return removeArtifactAtIndex(state, index)\n }),\n\n clearArtifacts: () => set({ artifacts: [], activeArtifactIndex: -1 }),\n\n setPreviewTarget: (target: PreviewTarget | null) =>\n set(() => {\n if (target === null) {\n return { artifacts: [], activeArtifactIndex: -1 }\n }\n // Push as single artifact\n return {\n artifacts: [target],\n activeArtifactIndex: 0,\n rightPanelCollapsed: false,\n activeRightTab: \"preview\",\n }\n }),\n\n setTheme: (theme: ThemeValue) => {\n localStorage.setItem(\"blade-theme\", theme)\n applyTheme(theme)\n set({ theme })\n },\n}))\n","import { create } from \"zustand\"\nimport type { Task } from \"../schemas/task\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nconst EMPTY_TASKS: Task[] = []\n\ninterface TaskState extends ClientAwareState {\n tasks: Record<string, Task[]>\n setTasks: (sessionId: string, tasks: Task[]) => void\n getTasks: (sessionId: string) => Task[]\n}\n\nexport const useTaskStore = create<TaskState>()((set, get) => ({\n ...createClientActions(set),\n tasks: {},\n\n setTasks: (sessionId, tasks) => {\n set((state) => ({\n tasks: { ...state.tasks, [sessionId]: tasks },\n }))\n },\n\n getTasks: (sessionId) => {\n return get().tasks[sessionId] ?? EMPTY_TASKS\n },\n}))\n","import { create } from \"zustand\"\nimport type { BackgroundTask } from \"../schemas/background\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\ninterface BackgroundState extends ClientAwareState {\n tasks: Record<string, BackgroundTask[]>\n selectedTaskId: Record<string, string | null>\n setTasks: (sessionId: string, tasks: BackgroundTask[]) => void\n upsertTask: (sessionId: string, task: BackgroundTask) => void\n selectTask: (sessionId: string, taskId: string | null) => void\n}\n\nexport const useBackgroundStore = create<BackgroundState>()((set) => ({\n ...createClientActions(set),\n tasks: {},\n selectedTaskId: {},\n\n setTasks: (sessionId, tasks) =>\n set((state) => ({\n tasks: { ...state.tasks, [sessionId]: tasks },\n selectedTaskId: {\n ...state.selectedTaskId,\n [sessionId]: state.selectedTaskId[sessionId] ?? tasks[0]?.id ?? null,\n },\n })),\n\n upsertTask: (sessionId, task) =>\n set((state) => {\n const existing = state.tasks[sessionId] ?? []\n const index = existing.findIndex((item) => item.id === task.id)\n const next = [...existing]\n if (index >= 0) {\n next[index] = { ...next[index], ...task }\n } else {\n next.unshift(task)\n }\n return {\n tasks: { ...state.tasks, [sessionId]: next },\n selectedTaskId: {\n ...state.selectedTaskId,\n [sessionId]: state.selectedTaskId[sessionId] ?? task.id,\n },\n }\n }),\n\n selectTask: (sessionId, taskId) =>\n set((state) => ({\n selectedTaskId: { ...state.selectedTaskId, [sessionId]: taskId },\n })),\n}))\n","import { create } from \"zustand\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\ninterface CardStateStore extends ClientAwareState {\n states: Record<string, unknown>\n getCardState: <T>(cardId: string) => T | undefined\n setCardState: <T>(cardId: string, state: T) => void\n removeCardState: (cardId: string) => void\n clearAllStates: () => void\n}\n\nexport const useCardStateStore = create<CardStateStore>((set, get) => ({\n ...createClientActions(set),\n states: {},\n\n getCardState: <T,>(cardId: string): T | undefined => {\n return get().states[cardId] as T | undefined\n },\n\n setCardState: <T,>(cardId: string, state: T) => {\n set((prev) => ({\n states: { ...prev.states, [cardId]: state },\n }))\n },\n\n removeCardState: (cardId: string) => {\n set((prev) => {\n const { [cardId]: _, ...rest } = prev.states\n return { states: rest }\n })\n },\n\n clearAllStates: () => {\n set({ states: {} })\n },\n}))\n","import { create } from \"zustand\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nexport type ConnectionStatus = \"connecting\" | \"connected\" | \"disconnected\"\n\nexport interface ConnectionState extends ClientAwareState {\n status: ConnectionStatus\n reconnectAttempt: number\n lastConnectedAt: number | null\n lastDisconnectedAt: number | null\n hasEverConnected: boolean\n markConnecting: (attempt?: number) => void\n markConnected: () => void\n markDisconnected: () => void\n reset: () => void\n}\n\nconst initialConnectionState = {\n status: \"disconnected\" as ConnectionStatus,\n reconnectAttempt: 0,\n lastConnectedAt: null,\n lastDisconnectedAt: null,\n hasEverConnected: false,\n}\n\nexport const useConnectionStore = create<ConnectionState>()((set) => ({\n ...createClientActions(set),\n ...initialConnectionState,\n\n markConnecting: (attempt = 0) =>\n set({\n status: \"connecting\",\n reconnectAttempt: attempt,\n }),\n\n markConnected: () =>\n set({\n status: \"connected\",\n reconnectAttempt: 0,\n lastConnectedAt: Date.now(),\n hasEverConnected: true,\n }),\n\n markDisconnected: () =>\n set({\n status: \"disconnected\",\n reconnectAttempt: 0,\n lastDisconnectedAt: Date.now(),\n }),\n\n reset: () => set(initialConnectionState),\n}))\n","import { create } from \"zustand\"\nimport type { GisGoal, GisMapCommand, GisResource, GisTarget } from \"../schemas/gis\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nconst EMPTY_GOALS: GisGoal[] = []\nconst EMPTY_RESOURCES: GisResource[] = []\nconst EMPTY_TARGETS: GisTarget[] = []\nconst EMPTY_COMMANDS: GisMapCommand[] = []\n\ninterface GisStateStore extends ClientAwareState {\n goalsBySession: Record<string, GisGoal[]>\n resourcesBySession: Record<string, GisResource[]>\n targetsBySession: Record<string, GisTarget[]>\n pendingMapCommandsBySession: Record<string, GisMapCommand[]>\n setGoals: (sessionId: string, goals: GisGoal[]) => void\n setResources: (sessionId: string, resources: GisResource[]) => void\n setTargets: (sessionId: string, targets: GisTarget[]) => void\n pushMapCommand: (\n sessionId: string,\n command: Omit<GisMapCommand, \"id\" | \"createdAt\">,\n ) => void\n consumeMapCommand: (sessionId: string, commandId: string) => void\n getGoals: (sessionId: string) => GisGoal[]\n getResources: (sessionId: string) => GisResource[]\n getTargets: (sessionId: string) => GisTarget[]\n getPendingMapCommands: (sessionId: string) => GisMapCommand[]\n}\n\nfunction newCommandId() {\n if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n return globalThis.crypto?.randomUUID?.() ?? `gis-map-${Date.now()}-${Math.random()}`\n }\n return `gis-map-${Date.now()}-${Math.random()}`\n}\n\nexport const useGisStore = create<GisStateStore>()((set, get) => ({\n ...createClientActions(set),\n goalsBySession: {},\n resourcesBySession: {},\n targetsBySession: {},\n pendingMapCommandsBySession: {},\n\n setGoals: (sessionId, goals) => {\n set((state) => ({\n goalsBySession: { ...state.goalsBySession, [sessionId]: goals },\n }))\n },\n\n setResources: (sessionId, resources) => {\n set((state) => ({\n resourcesBySession: { ...state.resourcesBySession, [sessionId]: resources },\n }))\n },\n\n setTargets: (sessionId, targets) => {\n set((state) => ({\n targetsBySession: { ...state.targetsBySession, [sessionId]: targets },\n }))\n },\n\n pushMapCommand: (sessionId, command) => {\n set((state) => ({\n pendingMapCommandsBySession: {\n ...state.pendingMapCommandsBySession,\n [sessionId]: [\n ...(state.pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS),\n {\n ...command,\n id: newCommandId(),\n createdAt: Date.now(),\n },\n ],\n },\n }))\n },\n\n consumeMapCommand: (sessionId, commandId) => {\n set((state) => ({\n pendingMapCommandsBySession: {\n ...state.pendingMapCommandsBySession,\n [sessionId]: (state.pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS).filter(\n (command) => command.id !== commandId,\n ),\n },\n }))\n },\n\n getGoals: (sessionId) => get().goalsBySession[sessionId] ?? EMPTY_GOALS,\n getResources: (sessionId) => get().resourcesBySession[sessionId] ?? EMPTY_RESOURCES,\n getTargets: (sessionId) => get().targetsBySession[sessionId] ?? EMPTY_TARGETS,\n getPendingMapCommands: (sessionId) =>\n get().pendingMapCommandsBySession[sessionId] ?? EMPTY_COMMANDS,\n}))\n","import { create } from \"zustand\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nexport type AsrProvider = \"volcengine\" | \"qwen\"\n\ninterface RuntimeFeaturesState extends ClientAwareState {\n asrEnabled: boolean\n asrProvider: AsrProvider\n publicSharingEnabled: boolean\n memoryEnabled: boolean\n setFeatures: (features: {\n asrEnabled?: boolean\n asrProvider?: AsrProvider\n publicSharingEnabled?: boolean\n memoryEnabled?: boolean\n }) => void\n}\n\n/**\n * 运行期特性开关(由后端 /api/config 下发)。默认全部关闭,main.tsx 启动时 fetch 一次填充。\n */\nexport const useRuntimeFeaturesStore = create<RuntimeFeaturesState>((set) => ({\n ...createClientActions(set),\n asrEnabled: false,\n asrProvider: \"volcengine\",\n publicSharingEnabled: false,\n memoryEnabled: false,\n setFeatures: (features) =>\n set((prev) => ({\n asrEnabled: features.asrEnabled ?? prev.asrEnabled,\n asrProvider: features.asrProvider ?? prev.asrProvider,\n publicSharingEnabled:\n features.publicSharingEnabled ?? prev.publicSharingEnabled,\n memoryEnabled: features.memoryEnabled ?? prev.memoryEnabled,\n })),\n}))\n","import { create } from \"zustand\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nexport interface RuntimeEvent {\n id: string\n sessionId: string\n type: string\n title: string\n status: \"info\" | \"running\" | \"done\" | \"error\"\n timestamp: string\n loopName?: string\n detail?: string\n}\n\ninterface RuntimeState extends ClientAwareState {\n events: Record<string, RuntimeEvent[]>\n addEvent: (sessionId: string, event: Omit<RuntimeEvent, \"id\" | \"sessionId\" | \"timestamp\">) => void\n clearSession: (sessionId: string) => void\n}\n\nexport const useRuntimeStore = create<RuntimeState>()((set) => ({\n ...createClientActions(set),\n events: {},\n\n addEvent: (sessionId, event) =>\n set((state) => {\n const current = state.events[sessionId] ?? []\n const nextEvent: RuntimeEvent = {\n ...event,\n id: `${Date.now()}-${current.length}`,\n sessionId,\n timestamp: new Date().toISOString(),\n }\n return {\n events: {\n ...state.events,\n [sessionId]: [...current.slice(-59), nextEvent],\n },\n }\n }),\n\n clearSession: (sessionId) =>\n set((state) => ({\n events: { ...state.events, [sessionId]: [] },\n })),\n}))\n","import { create } from \"zustand\"\nimport { createClientActions, type ClientAwareState } from \"./client-aware\"\n\nfunction buildSignalId() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID()\n }\n return `bridge-${Date.now()}-${Math.random().toString(36).slice(2)}`\n}\n\nfunction clearSignalRecord<T>(\n record: Record<string, T[]>,\n sessionId: string,\n) {\n if (!(sessionId in record)) {\n return record\n }\n\n const next = { ...record }\n delete next[sessionId]\n return next\n}\n\nexport interface PendingContextSignal {\n id: string\n label: string\n content: string\n}\n\nexport interface DraftAppendSignal {\n id: string\n text: string\n}\n\nexport interface SendRequestSignal {\n id: string\n}\n\ninterface UiBridgeState extends ClientAwareState {\n pendingContexts: Record<string, PendingContextSignal[]>\n draftAppends: Record<string, DraftAppendSignal[]>\n sendRequests: Record<string, SendRequestSignal[]>\n\n addPendingContext: (sessionId: string, context: Omit<PendingContextSignal, \"id\">) => void\n removePendingContext: (sessionId: string, contextId: string) => void\n consumePendingContexts: (sessionId: string) => PendingContextSignal[]\n clearPendingContexts: (sessionId: string) => void\n\n addDraftAppend: (sessionId: string, text: string) => void\n consumeDraftAppends: (sessionId: string) => DraftAppendSignal[]\n clearDraftAppends: (sessionId: string) => void\n\n addSendRequest: (sessionId: string) => void\n consumeSendRequests: (sessionId: string) => SendRequestSignal[]\n clearSendRequests: (sessionId: string) => void\n\n clearSession: (sessionId: string) => void\n}\n\nexport const useUiBridgeStore = create<UiBridgeState>()((set, get) => ({\n ...createClientActions(set),\n pendingContexts: {},\n draftAppends: {},\n sendRequests: {},\n\n addPendingContext: (sessionId, context) =>\n set((state) => ({\n pendingContexts: {\n ...state.pendingContexts,\n [sessionId]: [\n ...(state.pendingContexts[sessionId] ?? []),\n {\n id: buildSignalId(),\n label: context.label,\n content: context.content,\n },\n ],\n },\n })),\n removePendingContext: (sessionId, contextId) =>\n set((state) => {\n const contexts = state.pendingContexts[sessionId]\n if (!contexts?.length) {\n return state\n }\n\n const nextContexts = contexts.filter((context) => context.id !== contextId)\n if (nextContexts.length === contexts.length) {\n return state\n }\n\n return {\n pendingContexts:\n nextContexts.length > 0\n ? {\n ...state.pendingContexts,\n [sessionId]: nextContexts,\n }\n : clearSignalRecord(state.pendingContexts, sessionId),\n }\n }),\n consumePendingContexts: (sessionId) => {\n const signals = get().pendingContexts[sessionId] ?? []\n if (signals.length === 0) return []\n set((state) => ({\n pendingContexts: clearSignalRecord(state.pendingContexts, sessionId),\n }))\n return signals\n },\n clearPendingContexts: (sessionId) =>\n set((state) => ({\n pendingContexts: clearSignalRecord(state.pendingContexts, sessionId),\n })),\n\n addDraftAppend: (sessionId, text) =>\n set((state) => ({\n draftAppends: {\n ...state.draftAppends,\n [sessionId]: [\n ...(state.draftAppends[sessionId] ?? []),\n {\n id: buildSignalId(),\n text,\n },\n ],\n },\n })),\n consumeDraftAppends: (sessionId) => {\n const signals = get().draftAppends[sessionId] ?? []\n if (signals.length === 0) return []\n set((state) => ({\n draftAppends: clearSignalRecord(state.draftAppends, sessionId),\n }))\n return signals\n },\n clearDraftAppends: (sessionId) =>\n set((state) => ({\n draftAppends: clearSignalRecord(state.draftAppends, sessionId),\n })),\n\n addSendRequest: (sessionId) =>\n set((state) => ({\n sendRequests: {\n ...state.sendRequests,\n [sessionId]: [\n ...(state.sendRequests[sessionId] ?? []),\n {\n id: buildSignalId(),\n },\n ],\n },\n })),\n consumeSendRequests: (sessionId) => {\n const signals = get().sendRequests[sessionId] ?? []\n if (signals.length === 0) return []\n set((state) => ({\n sendRequests: clearSignalRecord(state.sendRequests, sessionId),\n }))\n return signals\n },\n clearSendRequests: (sessionId) =>\n set((state) => ({\n sendRequests: clearSignalRecord(state.sendRequests, sessionId),\n })),\n\n clearSession: (sessionId) =>\n set((state) => ({\n pendingContexts: clearSignalRecord(state.pendingContexts, sessionId),\n draftAppends: clearSignalRecord(state.draftAppends, sessionId),\n sendRequests: clearSignalRecord(state.sendRequests, sessionId),\n })),\n}))\n","import { BladeClient, type BladeClientOptions } from \"../client\"\nimport { attachHostBridgeListener } from \"./lib/parent-bridge\"\nimport { bridgeSocketEvents } from \"./sockets/event-bridge\"\nimport { useAnswerCallbackStore } from \"./stores/answer-callback-store\"\nimport { useAuthStore } from \"./stores/auth-store\"\nimport { useBackgroundStore } from \"./stores/background-store\"\nimport { useCardStateStore } from \"./stores/card-state-store\"\nimport { useChatStore } from \"./stores/chat-store\"\nimport { useConnectionStore } from \"./stores/connection-store\"\nimport { useGisStore } from \"./stores/gis-store\"\nimport { useRuntimeFeaturesStore } from \"./stores/runtime-features-store\"\nimport { useRuntimeStore } from \"./stores/runtime-store\"\nimport { useSessionStore } from \"./stores/session-store\"\nimport { useTaskStore } from \"./stores/task-store\"\nimport { useUiBridgeStore } from \"./stores/ui-bridge-store\"\nimport { useUiStore } from \"./stores/ui-store\"\n\nlet bootstrappedClient: BladeClient | null = null\nlet detachHostBridgeListener: (() => void) | null = null\n\nconst stores = {\n answerCallback: useAnswerCallbackStore,\n auth: useAuthStore,\n background: useBackgroundStore,\n cardState: useCardStateStore,\n chat: useChatStore,\n connection: useConnectionStore,\n gis: useGisStore,\n runtime: useRuntimeStore,\n runtimeFeatures: useRuntimeFeaturesStore,\n session: useSessionStore,\n task: useTaskStore,\n ui: useUiStore,\n uiBridge: useUiBridgeStore,\n}\n\nexport function attachClientToStores(client: BladeClient): void {\n for (const store of Object.values(stores)) {\n const state = (store as { getState: () => { setClient: (client: BladeClient) => void } }).getState()\n state.setClient(client)\n }\n bridgeSocketEvents(client, stores)\n detachHostBridgeListener?.()\n detachHostBridgeListener = attachHostBridgeListener(() => {\n const activeSessionId = useSessionStore.getState().activeSessionId\n return {\n sessionId: activeSessionId,\n activeSessionId,\n isStreaming: activeSessionId\n ? (useChatStore.getState().isStreaming[activeSessionId] ?? false)\n : false,\n }\n })\n}\n\nexport function bootstrapBladeClient(options: BladeClientOptions): BladeClient {\n const client = new BladeClient(withStoreAuth(options))\n if (options.token === undefined) {\n client._attachStoreRestTokenResolver(() => useAuthStore.getState().token)\n client._attachStoreSocketTokenResolver(() => {\n const auth = useAuthStore.getState()\n return auth.token ?? auth.socketAuthToken\n })\n }\n attachClientToStores(client)\n bootstrappedClient = client\n return client\n}\n\nexport function getBootstrappedClient(): BladeClient {\n if (!bootstrappedClient) {\n throw new Error(\"bootstrapBladeClient() must be called before any SDK usage\")\n }\n return bootstrappedClient\n}\n\nfunction withStoreAuth(options: BladeClientOptions): BladeClientOptions {\n if (options.token !== undefined) {\n return options\n }\n return {\n ...options,\n onRefreshSuccess: async () => {\n await options.onRefreshSuccess?.()\n useAuthStore.setState({ token: null })\n },\n }\n}\n","import type { BladeClient, BladeClientOptions } from \"../../client\"\nimport { getBootstrappedClient } from \"../bootstrap\"\n\nexport function getBaseUrl(): string {\n return getClient().options.baseUrl\n}\n\nexport function getAuthedUrl(path: string): string {\n return getClient().buildAuthedUrl(path)\n}\n\nexport async function apiFetch<T>(path: string, init?: RequestInit): Promise<T> {\n return getClient().jsonFromInit<T>(path, init)\n}\n\nexport async function apiFetchText(path: string, init?: RequestInit): Promise<string> {\n return getClient().textFromInit(path, init)\n}\n\nexport async function apiFetchResponse(path: string, init?: RequestInit): Promise<Response> {\n return getClient().responseFromInit(path, init)\n}\n\nexport function getClient(): BladeClient {\n return getBootstrappedClient()\n}\n\nexport type { BladeClientOptions }\n","import type { SkillsResource } from \"../../client/resources/skills\"\nimport { getClient } from \"./client\"\nexport type * from \"../../client/resources/skills\"\n\nconst r = (): SkillsResource => getClient().skills\nexport const listSkills = (...args: Parameters<SkillsResource[\"listSkills\"]>) => r().listSkills(...args)\nexport const listSessionSkills = (...args: Parameters<SkillsResource[\"listSessionSkills\"]>) => r().listSessionSkills(...args)\nexport const resyncSkills = (...args: Parameters<SkillsResource[\"resyncSkills\"]>) => r().resyncSkills(...args)\nexport const searchSkills = (...args: Parameters<SkillsResource[\"searchSkills\"]>) => r().searchSkills(...args)\nexport const getSkillStats = (...args: Parameters<SkillsResource[\"getSkillStats\"]>) => r().getSkillStats(...args)\nexport const getGlobalSkillStats = (...args: Parameters<SkillsResource[\"getGlobalSkillStats\"]>) => r().getGlobalSkillStats(...args)\nexport const getSkill = (...args: Parameters<SkillsResource[\"getSkill\"]>) => r().getSkill(...args)\nexport const installPartnerSkill = (...args: Parameters<SkillsResource[\"installPartnerSkill\"]>) => r().installPartnerSkill(...args)\n","import type { BridgeEventInput, RegisteredIframeEntry } from \"./types\"\n\nfunction isDev() {\n return (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV === true\n}\n\nconst PENDING_EVENT_LIMIT = 500\nconst pendingEvents: BridgeEventInput[] = []\n\nexport function tapBridgeEvent(event: BridgeEventInput) {\n if (!isDev()) return\n const hook = globalThis.__bladeBridgeDevtools\n if (hook) {\n hook.record(event)\n return\n }\n // hook 异步安装,启动阶段事件(如首个 postTheme、早期 host 消息)\n // 在 mount 前触达,直接丢弃会让 debugger 错过初始化链,故先入队。\n if (pendingEvents.length >= PENDING_EVENT_LIMIT) {\n pendingEvents.shift()\n }\n pendingEvents.push(event)\n}\n\nexport function flushPendingBridgeEvents() {\n const hook = globalThis.__bladeBridgeDevtools\n if (!hook) return\n for (const event of pendingEvents) {\n hook.record(event)\n }\n pendingEvents.length = 0\n}\n\ninterface PendingRegistration {\n entry: RegisteredIframeEntry\n unregister: (() => void) | null\n}\n\nconst pendingRegistrations: PendingRegistration[] = []\n\nexport function registerBridgeIframe(entry: RegisteredIframeEntry) {\n if (!isDev()) return () => {}\n const hook = globalThis.__bladeBridgeDevtools\n if (hook) {\n return hook.registerIframe(entry)\n }\n // devtools hook 在 main.tsx 里通过动态 import 异步安装,ResourceIframe\n // 可能先于 hook mount。先把 entry 排进队列,mount 时 flush 掉。\n const pending: PendingRegistration = { entry, unregister: null }\n pendingRegistrations.push(pending)\n return () => {\n const idx = pendingRegistrations.indexOf(pending)\n if (idx >= 0) pendingRegistrations.splice(idx, 1)\n pending.unregister?.()\n }\n}\n\nexport function flushPendingIframeRegistrations() {\n const hook = globalThis.__bladeBridgeDevtools\n if (!hook) return\n for (const pending of pendingRegistrations) {\n pending.unregister = hook.registerIframe(pending.entry)\n }\n pendingRegistrations.length = 0\n}\n","import { type } from \"arktype\"\n\nexport const PartnerSkillName = type(\"/^[a-z0-9-]+\\\\/[a-z0-9-]+$/\")\nexport type PartnerSkillName = typeof PartnerSkillName.infer\n\nexport const PartnerSkillFile = type({\n path: \"string > 0\",\n content: \"string\",\n})\nexport type PartnerSkillFile = typeof PartnerSkillFile.infer\n\nexport const PartnerSkillInstallPayload = type({\n name: PartnerSkillName,\n files: PartnerSkillFile.array().atLeastLength(1),\n})\nexport type PartnerSkillInstallPayload = typeof PartnerSkillInstallPayload.infer\n\nexport const PartnerSkillInstallResult = type({\n name: PartnerSkillName,\n skill_dir: \"string\",\n file_count: \"number.integer >= 0\",\n overwritten: \"boolean\",\n})\nexport type PartnerSkillInstallResult = typeof PartnerSkillInstallResult.infer\n\nexport function parsePartnerSkillInstallPayload(payload: unknown): PartnerSkillInstallPayload {\n const parsed = PartnerSkillInstallPayload.assert(payload)\n\n if (!parsed.files.some((file) => file.path === \"SKILL.md\")) {\n throw new Error(\"installSkill payload must include SKILL.md\")\n }\n\n return parsed\n}\n","import { useUiBridgeStore } from \"../stores/ui-bridge-store\"\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction getNonEmptyString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim() ? value.trim() : null\n}\n\nfunction hasUserActivation() {\n if (typeof navigator === \"undefined\") {\n return false\n }\n return navigator.userActivation?.isActive === true\n}\n\nconst BRIDGE_ACTIONS = [\"addContext\", \"appendInput\", \"sendMessage\"] as const\n\nexport type ResourceBridgeAction = (typeof BRIDGE_ACTIONS)[number]\n\nexport interface ResourceBridgeDispatchParams {\n sessionId: string\n activeSessionId: string | null\n isStreaming: boolean\n action: string\n payload?: unknown\n}\n\nfunction isBridgeAction(action: string): action is ResourceBridgeAction {\n return BRIDGE_ACTIONS.includes(action as ResourceBridgeAction)\n}\n\nexport function resourceBridgeDispatch({\n sessionId,\n activeSessionId,\n isStreaming,\n action,\n payload,\n}: ResourceBridgeDispatchParams): boolean {\n if (!sessionId || !activeSessionId || sessionId !== activeSessionId) {\n return false\n }\n\n if (!isBridgeAction(action)) {\n return false\n }\n\n const bridgeStore = useUiBridgeStore.getState()\n\n if (action === \"addContext\") {\n if (!isRecord(payload)) return false\n const content = getNonEmptyString(payload.content)\n const label = getNonEmptyString(payload.label)\n if (!content || !label) return false\n bridgeStore.addPendingContext(sessionId, { content, label })\n return true\n }\n\n if (action === \"appendInput\") {\n if (!isRecord(payload)) return false\n const text = getNonEmptyString(payload.text)\n if (!text) return false\n bridgeStore.addDraftAppend(sessionId, text)\n return true\n }\n\n if (isStreaming || !hasUserActivation()) {\n return false\n }\n\n bridgeStore.addSendRequest(sessionId)\n return true\n}\n","import type { PreviewTarget } from \"../stores/ui-store\"\n\nexport function buildToolPreviewKey(\n content: string,\n type: PreviewTarget[\"type\"],\n toolCallId: string,\n) {\n if (type === \"resource-uri\") {\n return `tool-preview-uri:${content}`\n }\n return `tool-preview:${toolCallId}`\n}\n","export interface UiMeta {\n resourceUri?: string\n resourceURI?: string\n resourceHTML?: string\n target: \"inline\" | \"preview\"\n height: number\n title?: string\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0\n}\n\nfunction isPositiveNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0\n}\n\nexport function isUiMeta(value: unknown): value is UiMeta {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false\n }\n const raw = value as Record<string, unknown>\n if (raw.target !== \"inline\" && raw.target !== \"preview\") {\n return false\n }\n if (!isPositiveNumber(raw.height)) {\n return false\n }\n if (\n !isNonEmptyString(raw.resourceHTML) &&\n !isNonEmptyString(raw.resourceUri) &&\n !isNonEmptyString(raw.resourceURI)\n ) {\n return false\n }\n if (raw.title != null && !isNonEmptyString(raw.title)) {\n return false\n }\n return true\n}\n","import { EditorContent, type Editor as TiptapEditor, useEditor } from \"@tiptap/react\"\nimport StarterKit from \"@tiptap/starter-kit\"\nimport {\n type SuggestionKeyDownProps,\n type SuggestionProps,\n exitSuggestion,\n} from \"@tiptap/suggestion\"\nimport {\n Archive,\n ChevronDown,\n File,\n FileCode2,\n FileText,\n Film,\n FolderUp,\n CircleHelp,\n Download,\n FlaskConical,\n Import,\n Lightbulb,\n Loader2,\n Mic,\n MicOff,\n Music,\n Paperclip,\n Plus,\n Rocket,\n Scissors,\n Send,\n Sparkles,\n Share2,\n Square,\n X,\n} from \"lucide-react\"\nimport { useQueryClient } from \"@tanstack/react-query\"\nimport { useEffect, useEffectEvent, useMemo, useRef, useState, type ReactNode } from \"react\"\nimport { createRoot } from \"react-dom/client\"\nimport { toast } from \"sonner\"\nimport { useTiptapVoiceInput } from \"../../asr/use-tiptap-voice-input\"\nimport type { VoiceInputError } from \"../../asr/voice-input-support\"\nimport { VoiceWaveform } from \"../../asr/VoiceWaveform\"\nimport { ModelSelector } from \"../model/ModelSelector\"\nimport { useRuntimeFeaturesStore } from \"../../stores/runtime-features-store\"\nimport { getAuthedUrl } from \"../../api/client\"\nimport { getSessionTurns, listSessions, uploadFiles, writeFile } from \"../../api/sessions\"\nimport { listSessionSkills, searchSkills } from \"../../api/skills\"\nimport { useInputHistory } from \"../../hooks/use-input-history\"\nimport { useModelConfig, usePreferredModel } from \"../../hooks/use-model-preferences\"\nimport {\n ATTACHMENT_SIZE_LIMIT_BYTES,\n splitFilesBySize,\n type OversizedFileInfo,\n} from \"../../lib/attachment-upload\"\nimport { buildMessageContent, transformSlashCommand } from \"../../lib/chat\"\nimport type { MessageContent, MessageContentPart } from \"../../schemas/message\"\nimport { skillDisplayName } from \"../../schemas/skill\"\nimport { useConnectionStore } from \"../../stores/connection-store\"\nimport type { SessionMode } from \"../../stores/session-store\"\nimport { useSessionStore } from \"../../stores/session-store\"\nimport { useUiBridgeStore } from \"../../stores/ui-bridge-store\"\nimport {\n FileCompletionMenu,\n type FileCompletionMenuProps,\n type FileCompletionMenuRef,\n getFileSuggestionItems,\n} from \"./FileCompletionMenu\"\nimport {\n SkillCompletionMenu,\n type SkillCompletionMenuRef,\n} from \"./SkillCompletionMenu\"\nimport { FileSizeLimitDialog } from \"./FileSizeLimitDialog\"\nimport { SkillStatusBar } from \"./SkillStatusBar\"\nimport {\n FileMention,\n type FileSuggestionItem,\n fileMentionSuggestionKey,\n} from \"./extensions/file-mention\"\nimport {\n COMMANDS,\n SkillMention,\n type SkillSuggestionSkillItem,\n type SkillSuggestionItem,\n skillMentionSuggestionKey,\n} from \"./extensions/skill-mention\"\n\ninterface Props {\n onSend: (message: MessageContent, targetSessionId?: string, model?: string | null) => void\n onStop: () => void\n isStreaming: boolean\n mode?: SessionMode\n onToggleMode?: () => void\n renderAttachments?: () => ReactNode\n onBeforeSend?: (content: MessageContent) => MessageContent\n /**\n * Creates (or returns) a session to upload pending attachments into when\n * the composer has files but no active session yet. The returned id is\n * used for the upload, and is also passed back to `onSend` so the send\n * path reaches exactly the session the files landed in — independent of\n * whatever the global activeSessionId is at that moment.\n */\n ensureSession?: (draftText: string) => Promise<string>\n onCommand?: (commandId: string) => void | Promise<void>\n canShareSession?: boolean\n /**\n * Optional slot rendered directly above the textarea (below any file-pill\n * bar). ship-attack uses this to mount QuoteChipList for R4.\n */\n slotAboveTextarea?: ReactNode\n /**\n * Optional external draft channel. When provided, the composer initializes\n * from `value` on mount and mirrors every internal `setInput` call into\n * `setValue`. Intended for ship-attack's cross-view draft sharing (R3.8),\n * not full controlled-input semantics — the tiptap editor remains the\n * source of truth, this is a persistence side-channel.\n */\n externalDraft?: {\n value: string\n setValue: (v: string) => void\n }\n /**\n * Optional external attachments channel. Same mirror semantics as\n * externalDraft. Upload state (pending/uploading/...) is carried on\n * `FileComposerAttachment.status`, so sharing the array is enough.\n */\n externalAttachments?: {\n value: FileComposerAttachment[]\n setValue: (a: FileComposerAttachment[]) => void\n }\n /** Tailwind class for the inner max-width wrapper. Defaults to `max-w-3xl`. */\n maxWidthClassName?: string\n onResyncSkills?: () => void\n isResyncingSkills?: boolean\n}\n\ninterface EditorJSON {\n type?: string\n text?: string\n attrs?: Record<string, unknown>\n content?: EditorJSON[]\n}\n\nexport type FileComposerAttachment = {\n id: string\n kind: \"file\"\n name: string\n size: number\n mimeType: string\n status: \"pending\" | \"uploading\" | \"uploaded\" | \"failed\"\n file?: File\n uploadedPath?: string\n textContent?: string | null\n}\n\ntype ComposerAttachment = FileComposerAttachment\n\nfunction getEditorText(editor: TiptapEditor | null) {\n return editor?.getText({ blockSeparator: \"\\n\" }) ?? \"\"\n}\n\nfunction buildPlainTextDocument(text: string): EditorJSON {\n return {\n type: \"doc\",\n content: text.split(\"\\n\").map((line) => ({\n type: \"paragraph\",\n content: line ? [{ type: \"text\", text: line }] : [],\n })),\n }\n}\n\nfunction replaceEditorText(editor: TiptapEditor | null, text: string) {\n if (!editor) {\n return\n }\n\n if (!text) {\n editor.commands.clearContent()\n editor.commands.focus(\"end\")\n return\n }\n\n editor.commands.setContent(buildPlainTextDocument(text))\n editor.commands.focus(\"end\")\n}\n\nfunction getFileCardIcon(attachment: FileComposerAttachment) {\n const lowerName = attachment.name.toLowerCase()\n\n if (attachment.mimeType.startsWith(\"audio/\")) {\n return Music\n }\n if (attachment.mimeType.startsWith(\"video/\")) {\n return Film\n }\n if (/\\.(zip|rar|7z|tar|gz|bz2|xz)$/.test(lowerName)) {\n return Archive\n }\n if (/\\.(ts|tsx|js|jsx|py|rb|go|rs|java|kt|swift|c|cc|cpp|h|hpp|css|scss|html|json|yaml|yml|toml|md)$/.test(lowerName)) {\n return FileCode2\n }\n if (attachment.mimeType.startsWith(\"text/\") || /\\.(txt|pdf|doc|docx|rtf|odt)$/.test(lowerName)) {\n return FileText\n }\n return File\n}\n\nasync function hashFileContent(file: File): Promise<string> {\n const buffer = await file.arrayBuffer()\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", buffer)\n const hashArray = Array.from(new Uint8Array(hashBuffer))\n return hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\")\n .slice(0, 12)\n}\n\nfunction getFileExtension(file: File): string {\n const name = file.name || \"\"\n const dotIndex = name.lastIndexOf(\".\")\n return dotIndex >= 0 ? name.slice(dotIndex) : \"\"\n}\n\nfunction isClipboardPastedFile(file: File): boolean {\n // Browsers assign generic names like \"image.png\" for pasted clipboard images\n return /^image\\.\\w+$/.test(file.name)\n}\n\nasync function getUploadFileName(file: File): Promise<string> {\n if (file.webkitRelativePath) return file.webkitRelativePath\n if (isClipboardPastedFile(file)) {\n const hash = await hashFileContent(file)\n return `paste_${hash}${getFileExtension(file)}`\n }\n return file.name || \"未命名文件\"\n}\n\nfunction getImagePreviewUrl(\n attachment: FileComposerAttachment,\n sessionId: string | null,\n localImageUrls: Record<string, string>,\n): string | undefined {\n if (attachment.status === \"uploaded\" && sessionId && attachment.uploadedPath) {\n return getAuthedUrl(\n `/api/sessions/${encodeURIComponent(sessionId)}/files/${encodeURIComponent(attachment.uploadedPath)}`,\n )\n }\n return localImageUrls[attachment.id]\n}\n\nfunction isMessageContentEmpty(content: MessageContent) {\n if (typeof content === \"string\") {\n return !content.trim()\n }\n\n return content.length === 0 || content.every((part) => part.type === \"text\" && !part.text.trim())\n}\n\nfunction isImageAttachment(\n attachment: ComposerAttachment,\n): attachment is FileComposerAttachment {\n return attachment.kind === \"file\" && attachment.mimeType.startsWith(\"image/\")\n}\n\nfunction buildSubmitPayload(\n text: string,\n attachments: ComposerAttachment[],\n pendingContexts: { label: string; content: string }[],\n onBeforeSend?: (content: MessageContent) => MessageContent,\n) {\n const validAttachments = attachments.filter((attachment) => attachment.status !== \"failed\")\n const payload = buildMessageContent(text, validAttachments)\n const contextParts: MessageContentPart[] = pendingContexts.map((context) => ({\n type: \"text\" as const,\n text: `[上下文: ${context.label}]\\n${context.content}`,\n }))\n\n const mergedPayload =\n contextParts.length === 0\n ? payload\n : typeof payload === \"string\"\n ? payload.trim()\n ? [...contextParts, { type: \"text\" as const, text: payload }]\n : contextParts\n : [...contextParts, ...payload]\n\n return onBeforeSend ? onBeforeSend(mergedPayload) : mergedPayload\n}\n\nfunction estimateTokenCount(text: string): number {\n const cjkCount = (text.match(/[\\u3400-\\u9FFF]/g) ?? []).length\n const visibleCount = text.replace(/\\s/g, \"\").length\n const otherCount = Math.max(0, visibleCount - cjkCount)\n return Math.max(0, Math.round(cjkCount * 1.2 + otherCount / 4))\n}\n\nfunction formatTokenK(text: string): string {\n const tokenCount = estimateTokenCount(text)\n const tokenK = tokenCount / 1000\n if (tokenK >= 10) {\n return `约 ${tokenK.toFixed(1)}k`\n }\n return `约 ${tokenK.toFixed(2)}k`\n}\n\nfunction ComposerFilePill({\n attachment,\n onRemove,\n}: {\n attachment: ComposerAttachment\n onRemove: (id: string) => void\n}) {\n const Icon = getFileCardIcon(attachment)\n const isFile = attachment.kind === \"file\"\n const isFailed = isFile && attachment.status === \"failed\"\n const isUploading = isFile && attachment.status === \"uploading\"\n\n return (\n <div\n className={`flex shrink-0 items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] ${\n isFailed\n ? \"border-red-500/30 bg-red-500/5 text-red-400\"\n : \"border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--foreground))]\"\n }`}\n >\n {isUploading ? (\n <Loader2 size={12} className=\"shrink-0 animate-spin text-[hsl(var(--muted-foreground))]\" />\n ) : (\n <Icon size={12} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" />\n )}\n <span className=\"max-w-32 truncate\">{attachment.name}</span>\n <button\n type=\"button\"\n onClick={() => onRemove(attachment.id)}\n aria-label={`移除 ${attachment.name}`}\n className=\"ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400\"\n >\n <X size={10} />\n </button>\n </div>\n )\n}\n\nfunction AddContextDialog({\n sessionId,\n onClose,\n onAdd,\n}: {\n sessionId: string\n onClose: () => void\n onAdd: (label: string, content: string) => void\n}) {\n const CONTEXT_INLINE_THRESHOLD = 200\n const [label, setLabel] = useState(\"\")\n const [content, setContent] = useState(\"\")\n const [showSessionPicker, setShowSessionPicker] = useState(false)\n const [sessions, setSessions] = useState<{ id: string; intent: string }[]>([])\n const [loadingSessions, setLoadingSessions] = useState(false)\n const [importingId, setImportingId] = useState<string | null>(null)\n const [isImportProcessing, setIsImportProcessing] = useState(false)\n\n const sanitizeContextFolderName = (raw: string) => {\n const normalized = raw.trim().toLowerCase()\n const safe = normalized.replace(/[^\\w\\-.\\u4e00-\\u9fa5]+/g, \"_\").replace(/^_+|_+$/g, \"\")\n return safe || \"untitled\"\n }\n\n const uploadContextSnippet = async (\n folder: string,\n fileName: string,\n fileContent: string,\n ): Promise<string> => {\n const filePath = `context/${folder}/${fileName}`\n await writeFile(sessionId, filePath, fileContent)\n return filePath\n }\n\n const handleLoadSessions = async () => {\n if (showSessionPicker) {\n setShowSessionPicker(false)\n return\n }\n setLoadingSessions(true)\n setShowSessionPicker(true)\n try {\n const list = await listSessions()\n setSessions(\n list\n .filter((s) => s.id !== sessionId)\n .map((s) => ({ id: s.id, intent: s.intent || s.id })),\n )\n } catch {\n setSessions([])\n } finally {\n setLoadingSessions(false)\n }\n }\n\n const handleImportSession = async (sid: string) => {\n setImportingId(sid)\n setIsImportProcessing(false)\n try {\n const turns = await getSessionTurns(sid)\n const session = sessions.find((s) => s.id === sid)\n const nextLabel = session?.intent || \"导入的会话\"\n const folder = sanitizeContextFolderName(nextLabel)\n let contextFileIndex = 1\n\n const pendingUploads: Array<{\n pendingText: string\n finalText: string\n fallbackPrefix: string\n fileName: string\n rawResultStr: string\n }> = []\n const segments: string[] = []\n for (const turn of turns.filter((t) => t.role === \"user\" || t.role === \"assistant\")) {\n const textParts = turn.blocks\n .filter((b) => b.type === \"text\")\n .map((b) => (typeof b.content === \"string\" ? b.content : \"\"))\n .filter(Boolean)\n const toolParts: string[] = []\n for (const tc of (turn.tool_calls ?? []).filter((item) => item.status === \"done\")) {\n const rawResultStr =\n typeof tc.result === \"string\"\n ? tc.result\n : tc.result != null\n ? JSON.stringify(tc.result, null, 2)\n : \"\"\n\n const hasLongResult = rawResultStr.length > CONTEXT_INLINE_THRESHOLD\n const toolName = (tc.tool_name || \"\").toLowerCase()\n const looksLikeReadFile = toolName.includes(\"read\") || toolName.includes(\"file\")\n\n let resultText = rawResultStr\n if (hasLongResult || (looksLikeReadFile && rawResultStr.length > CONTEXT_INLINE_THRESHOLD)) {\n const fileName = `tool-result-${String(contextFileIndex).padStart(3, \"0\")}.txt`\n contextFileIndex += 1\n const filePath = `context/${folder}/${fileName}`\n const pendingText = `[处理中: 将转存到工作区文件 ${filePath}]`\n pendingUploads.push({\n pendingText,\n finalText: `[内容已转存到工作区文件: ${filePath}]`,\n fallbackPrefix: \"[转存失败,保留原文片段]\",\n fileName,\n rawResultStr,\n })\n resultText = pendingText\n }\n\n toolParts.push(\n `[工具调用: ${tc.display_name || tc.tool_name}]\\n参数: ${tc.arguments}\\n结果: ${resultText}`,\n )\n }\n segments.push(`[${turn.role}]: ${[...textParts, ...toolParts].join(\"\\n\\n\")}`)\n }\n const resolvedText = segments.join(\"\\n\\n\")\n\n setLabel(nextLabel)\n setContent(resolvedText)\n setShowSessionPicker(false)\n\n if (pendingUploads.length > 0) {\n setIsImportProcessing(true)\n let finalText = resolvedText\n for (const upload of pendingUploads) {\n try {\n await uploadContextSnippet(folder, upload.fileName, upload.rawResultStr)\n finalText = finalText.split(upload.pendingText).join(upload.finalText)\n } catch (error) {\n const reason = error instanceof Error ? error.message : \"unknown error\"\n finalText = finalText.split(upload.pendingText).join(\n `${upload.fallbackPrefix}\\n原因: ${reason}\\n${upload.rawResultStr.slice(0, CONTEXT_INLINE_THRESHOLD)}...`,\n )\n }\n setContent(finalText)\n }\n setIsImportProcessing(false)\n }\n } catch {\n // ignore\n } finally {\n setIsImportProcessing(false)\n setImportingId(null)\n }\n }\n\n return (\n <div\n className=\"fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-4\"\n onClick={onClose}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") onClose()\n }}\n >\n <div\n className=\"w-full max-w-lg flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-[hsl(var(--border))] px-5 py-3\">\n <h4 className=\"text-sm font-semibold text-[hsl(var(--foreground))]\">添加上下文</h4>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n >\n <X size={14} />\n </button>\n </div>\n\n <div className=\"px-5 py-4 space-y-3\">\n {/* 操作按钮行 */}\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={handleLoadSessions}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--border))] px-2.5 py-1.5 text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <Import size={12} />\n 从其他会话导入\n <ChevronDown size={10} className={`transition-transform ${showSessionPicker ? \"rotate-180\" : \"\"}`} />\n </button>\n {showSessionPicker && (\n <div className=\"absolute left-0 top-full z-10 mt-1 max-h-48 w-full overflow-y-auto rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-lg\">\n {loadingSessions ? (\n <div className=\"flex items-center gap-2 px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]\">\n <Loader2 size={12} className=\"animate-spin\" />\n 加载会话列表…\n </div>\n ) : sessions.length === 0 ? (\n <div className=\"px-3 py-2.5 text-xs text-[hsl(var(--muted-foreground))]\">\n 暂无其他会话\n </div>\n ) : (\n sessions.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n disabled={importingId === s.id}\n onClick={() => handleImportSession(s.id)}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))] disabled:opacity-50\"\n >\n {importingId === s.id && <Loader2 size={10} className=\"shrink-0 animate-spin\" />}\n <span className=\"truncate\">{s.intent}</span>\n </button>\n ))\n )}\n </div>\n )}\n </div>\n\n {/* 标签 */}\n <div>\n <label htmlFor=\"ctx-label\" className=\"block text-xs font-medium text-[hsl(var(--foreground))] mb-1\">\n 标签\n </label>\n <input\n id=\"ctx-label\"\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder=\"例如:参考对话、背景资料…\"\n className=\"w-full rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--background))] px-3 py-1.5 text-xs text-[hsl(var(--foreground))] placeholder:text-[hsl(var(--muted-foreground))] outline-none focus-visible:border-[hsl(var(--ring))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))]\"\n />\n </div>\n\n {/* 内容 */}\n <div>\n <label htmlFor=\"ctx-content\" className=\"block text-xs font-medium text-[hsl(var(--foreground))] mb-1\">\n 内容\n </label>\n {isImportProcessing && (\n <div className=\"mb-1.5 flex items-center gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]\">\n <Loader2 size={11} className=\"animate-spin\" />\n 正在处理导入内容并写入 workspace/context,完成后可点击“确定”\n </div>\n )}\n <textarea\n id=\"ctx-content\"\n value={content}\n onChange={(e) => setContent(e.target.value)}\n placeholder=\"输入或从其他会话导入上下文内容…\"\n rows={6}\n className=\"w-full rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--background))] px-3 py-2 font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground))] placeholder:text-[hsl(var(--muted-foreground))] outline-none focus-visible:border-[hsl(var(--ring))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] resize-y\"\n />\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2 border-t border-[hsl(var(--border))] px-5 py-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-md border border-[hsl(var(--border))] px-3 py-1.5 text-xs text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n 取消\n </button>\n <button\n type=\"button\"\n onClick={() => {\n if (label.trim() && content.trim()) {\n onAdd(label.trim(), content.trim())\n onClose()\n }\n }}\n disabled={isImportProcessing || !label.trim() || !content.trim()}\n className=\"rounded-md bg-blue-500 px-3 py-1.5 text-xs text-white transition-colors hover:bg-blue-600 disabled:opacity-50\"\n >\n 确定\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nfunction ComposerContextPill({\n id,\n label,\n content,\n onRemove,\n}: {\n id: string\n label: string\n content: string\n onRemove: (id: string) => void\n}) {\n const [showDetail, setShowDetail] = useState(false)\n const tokenK = formatTokenK(content)\n\n return (\n <>\n <div className=\"flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]\">\n <button\n type=\"button\"\n onClick={() => setShowDetail(true)}\n className=\"max-w-40 truncate hover:text-blue-400 transition-colors\"\n title=\"点击查看完整内容\"\n >\n {label}\n </button>\n <span\n className=\"shrink-0 rounded bg-[hsl(var(--background))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\"\n title=\"上下文内容 token 估算值\"\n >\n {tokenK}\n </span>\n <button\n type=\"button\"\n onClick={() => onRemove(id)}\n aria-label={`移除上下文 ${label}`}\n className=\"ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full text-[hsl(var(--muted-foreground))] transition hover:text-rose-400\"\n >\n <X size={10} />\n </button>\n </div>\n {showDetail && (\n <div\n className=\"fixed inset-0 z-[60] flex items-center justify-center bg-black/55 p-6\"\n onClick={() => setShowDetail(false)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") setShowDetail(false)\n }}\n >\n <div\n className=\"w-full max-w-4xl max-h-[85vh] flex flex-col rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-[hsl(var(--border))] px-6 py-3\">\n <h4 className=\"text-xs font-semibold text-[hsl(var(--foreground))]\">{label}</h4>\n <button\n type=\"button\"\n onClick={() => setShowDetail(false)}\n className=\"rounded-md p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n >\n <X size={14} />\n </button>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-6 py-4\">\n <pre className=\"whitespace-pre-wrap break-words font-mono text-[11px] leading-[1.6] text-[hsl(var(--foreground)/0.85)]\">\n {content}\n </pre>\n </div>\n </div>\n </div>\n )}\n </>\n )\n}\n\nfunction serializeEditorContent(node: EditorJSON | null | undefined): string {\n if (!node) return \"\"\n\n if (node.type === \"text\") {\n return node.text ?? \"\"\n }\n\n if (node.type === \"hardBreak\") {\n return \"\\n\"\n }\n\n if (node.type === \"fileMention\") {\n const path = typeof node.attrs?.path === \"string\" ? node.attrs.path : \"\"\n return path ? `\\`${path}\\`` : \"\"\n }\n\n if (node.type === \"skillMention\") {\n const skillId = typeof node.attrs?.skillId === \"string\" ? node.attrs.skillId : \"\"\n return skillId ? `<skill>${skillId}</skill>` : \"\"\n }\n\n const children = (node.content ?? []).map((child: EditorJSON) => serializeEditorContent(child))\n\n if (node.type === \"doc\") {\n return children.join(\"\\n\")\n }\n\n return children.join(\"\")\n}\n\nfunction findLeadingSkillMention(node: EditorJSON | null | undefined): string | null {\n const result = scanLeadingSkillMention(node, false)\n return result.skillId\n}\n\nfunction scanLeadingSkillMention(\n node: EditorJSON | null | undefined,\n seenContent: boolean,\n): { skillId: string | null; seenContent: boolean } {\n if (!node) {\n return { skillId: null, seenContent }\n }\n\n if (node.type === \"text\") {\n return { skillId: null, seenContent: seenContent || /\\S/.test(node.text ?? \"\") }\n }\n\n if (node.type === \"hardBreak\" || node.type === \"fileMention\") {\n return { skillId: null, seenContent: true }\n }\n\n if (node.type === \"skillMention\") {\n return {\n skillId:\n seenContent ? null : (typeof node.attrs?.skillId === \"string\" ? node.attrs.skillId : null),\n seenContent: true,\n }\n }\n\n let nextSeenContent = seenContent\n for (const child of node.content ?? []) {\n const result = scanLeadingSkillMention(child, nextSeenContent)\n if (result.skillId) {\n return result\n }\n nextSeenContent = result.seenContent\n }\n\n return { skillId: null, seenContent: nextSeenContent }\n}\n\nasync function getSkillSuggestionItems(\n sessionId: string | null,\n query: string,\n): Promise<SkillSuggestionSkillItem[]> {\n const loadSessionSkills = async () => {\n if (!sessionId) {\n return []\n }\n try {\n return await listSessionSkills(sessionId)\n } catch {\n return []\n }\n }\n\n if (!query) {\n const source = await loadSessionSkills()\n return source.map((s) => ({\n type: \"skill\" as const,\n skillId: s.skill_id,\n displayName: s.display_name,\n description: s.description,\n local: s.local,\n }))\n }\n\n const q = query.toLowerCase()\n const sessionSkills = await loadSessionSkills()\n const localMatches = sessionSkills\n .filter(\n (s) =>\n s.skill_id.toLowerCase().includes(q) ||\n s.description.toLowerCase().includes(q),\n )\n .map((s) => ({\n type: \"skill\" as const,\n skillId: s.skill_id,\n displayName: s.display_name,\n description: s.description,\n local: s.local,\n }))\n\n try {\n const remoteResults = await searchSkills(query, 10)\n const seen = new Set(localMatches.map((s) => s.skillId))\n const dedupedRemote = remoteResults\n .filter((r) => !seen.has(r.skill_id))\n .map((r) => ({\n type: \"skill\" as const,\n skillId: r.skill_id,\n displayName: r.display_name,\n description: r.description,\n local: r.local,\n }))\n return [...localMatches, ...dedupedRemote]\n } catch {\n return localMatches\n }\n}\n\nfunction updateSuggestionPosition(\n element: HTMLDivElement,\n clientRect?: (() => DOMRect | null) | null,\n) {\n const rect = clientRect?.()\n if (!rect) {\n element.style.display = \"none\"\n return\n }\n\n const width = Math.min(420, window.innerWidth - 16)\n const left = Math.min(Math.max(8, rect.left), window.innerWidth - width - 8)\n // Always place above the cursor, anchored to bottom\n const bottom = window.innerHeight - rect.top + 4\n\n element.style.display = \"block\"\n element.style.position = \"fixed\"\n element.style.left = `${left}px`\n element.style.top = \"\"\n element.style.bottom = `${bottom}px`\n element.style.maxHeight = `${rect.top - 16}px`\n element.style.width = `${width}px`\n element.style.zIndex = \"60\"\n}\n\nfunction showVoiceInputErrorToast(error: VoiceInputError) {\n toast.error(error.title, {\n description: error.description,\n duration: error.description ? 15000 : undefined,\n })\n}\n\nexport function ChatInput({\n onSend,\n onStop,\n isStreaming,\n mode = \"executing\",\n onToggleMode,\n renderAttachments,\n onBeforeSend,\n ensureSession,\n onCommand,\n canShareSession = false,\n slotAboveTextarea,\n externalDraft,\n externalAttachments,\n maxWidthClassName = \"max-w-3xl\",\n onResyncSkills,\n isResyncingSkills = false,\n}: Props) {\n const [input, setInputInternal] = useState(externalDraft?.value ?? \"\")\n // Mirror every setInput into the optional external channel so the caller\n // (e.g. ship-attack's chat-draft-store) can persist the draft across view\n // switches. The internal useState stays the source of truth for tiptap.\n const setInput = useEffectEvent((value: string) => {\n setInputInternal(value)\n externalDraft?.setValue(value)\n })\n // Reverse sync: when external value changes from the outside (e.g. a sibling\n // ChatInput wrote to the shared store, or the user switched to a session with\n // a different saved draft), pull it back into both this instance's input state\n // AND the tiptap editor.\n //\n // No \"non-empty → empty\" guard: it used to be here to paper over a race where\n // ship-attack's draft store briefly observed `drafts[newId] === undefined`\n // during createSession → setActiveSession before migrateDraftKey landed. But\n // migrateDraftKey is now invoked synchronously right after setActiveSession\n // in the same React commit, so the race can't happen. Keeping the guard would\n // *break* the legitimate \"user switches to a session with no saved draft\"\n // case: external goes to \"\" and the composer would stubbornly keep the\n // previous session's text — which then gets posted into the wrong session on\n // next send, since `send` resolves against the new active session id.\n const externalDraftValue = externalDraft?.value\n const inputRef = useRef(input)\n inputRef.current = input\n useEffect(() => {\n if (externalDraftValue == null) return\n // inputRef 读当前 internal 值;updater callback 里做 diff 是 render-phase\n // 副作用,React 19 的 useEffectEvent 检查会把之后同步触发的 editor.onUpdate\n // 判为 \"被 render 调用\",这里改成 effect 体内直接 diff + 写。\n if (inputRef.current === externalDraftValue) return\n if (editorRef.current) {\n replaceEditorText(editorRef.current, externalDraftValue)\n }\n setInputInternal(externalDraftValue)\n }, [externalDraftValue])\n\n const [composerAttachments, setComposerAttachmentsInternal] = useState<ComposerAttachment[]>(\n externalAttachments?.value ?? [],\n )\n const setComposerAttachments = useEffectEvent(\n (\n valueOrUpdater:\n | ComposerAttachment[]\n | ((prev: ComposerAttachment[]) => ComposerAttachment[]),\n ) => {\n setComposerAttachmentsInternal((prev) => {\n const next =\n typeof valueOrUpdater === \"function\"\n ? (valueOrUpdater as (p: ComposerAttachment[]) => ComposerAttachment[])(prev)\n : valueOrUpdater\n externalAttachments?.setValue(next)\n return next\n })\n },\n )\n // Reverse sync for attachments — same reasoning as the draft channel above:\n // no \"non-empty → empty\" guard, because session switching legitimately needs\n // to clear the previous session's attachments and the migrate path never\n // actually goes through an empty intermediate.\n const externalAttachmentsValue = externalAttachments?.value\n const composerAttachmentsRef = useRef(composerAttachments)\n composerAttachmentsRef.current = composerAttachments\n useEffect(() => {\n if (externalAttachmentsValue == null) return\n if (composerAttachmentsRef.current === externalAttachmentsValue) return\n setComposerAttachmentsInternal(externalAttachmentsValue)\n }, [externalAttachmentsValue])\n const [dragging, setDragging] = useState(false)\n const [isEditorFocused, setIsEditorFocused] = useState(false)\n const [oversizedFiles, setOversizedFiles] = useState<OversizedFileInfo[]>([])\n const [selectedModel, setSelectedModel] = useState(\"\")\n const { defaultModel } = useModelConfig()\n const { setPreferredModel } = usePreferredModel()\n const queryClient = useQueryClient()\n const actionMenuRef = useRef<HTMLDetailsElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n const folderInputRef = useRef<HTMLInputElement>(null)\n const editorRef = useRef<TiptapEditor | null>(null)\n const localImageUrlsRef = useRef(new Map<string, string>())\n const activeSessionId = useSessionStore((state) => state.activeSessionId)\n const sessions = useSessionStore((state) => state.sessions)\n const activeSessionModel = useMemo(\n () => sessions.find((session) => session.id === activeSessionId)?.model ?? null,\n [activeSessionId, sessions],\n )\n const rewindDraft = useSessionStore((state) =>\n activeSessionId ? state.rewindDrafts[activeSessionId] : undefined,\n )\n const patchSession = useSessionStore((state) => state.patchSession)\n const setRewindDraft = useSessionStore((state) => state.setRewindDraft)\n const pendingContexts = useUiBridgeStore((state) =>\n activeSessionId ? state.pendingContexts[activeSessionId] : undefined,\n )\n const draftAppends = useUiBridgeStore((state) =>\n activeSessionId ? state.draftAppends[activeSessionId] : undefined,\n )\n useEffect(() => {\n setSelectedModel(activeSessionModel || defaultModel)\n }, [activeSessionModel, defaultModel])\n const sendRequests = useUiBridgeStore((state) =>\n activeSessionId ? state.sendRequests[activeSessionId] : undefined,\n )\n const removePendingContext = useUiBridgeStore((state) => state.removePendingContext)\n const consumePendingContexts = useUiBridgeStore((state) => state.consumePendingContexts)\n const consumeDraftAppends = useUiBridgeStore((state) => state.consumeDraftAppends)\n const consumeSendRequests = useUiBridgeStore((state) => state.consumeSendRequests)\n const connectionStatus = useConnectionStore((state) => state.status)\n const inputHistory = useInputHistory(activeSessionId)\n const getSessionId = useEffectEvent(() => activeSessionId)\n const handleSlashCommand = useEffectEvent((commandId: string) => onCommand?.(commandId))\n const [localImageUrls, setLocalImageUrls] = useState<Record<string, string>>({})\n\n useEffect(() => {\n const closeActionMenu = (event: PointerEvent) => {\n const menu = actionMenuRef.current\n if (!menu?.open || menu.contains(event.target as Node)) {\n return\n }\n menu.removeAttribute(\"open\")\n }\n const closeActionMenuOnEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n actionMenuRef.current?.removeAttribute(\"open\")\n }\n }\n\n window.addEventListener(\"pointerdown\", closeActionMenu)\n window.addEventListener(\"keydown\", closeActionMenuOnEscape)\n return () => {\n window.removeEventListener(\"pointerdown\", closeActionMenu)\n window.removeEventListener(\"keydown\", closeActionMenuOnEscape)\n }\n }, [])\n\n const getMentionSuggestionItems = useEffectEvent(\n async (query: string): Promise<SkillSuggestionItem[]> => {\n const normalizedQuery = query.trim().toLowerCase()\n const commandItems = COMMANDS.filter((item) => {\n if (!normalizedQuery) {\n return true\n }\n return (\n item.id.toLowerCase().startsWith(normalizedQuery) ||\n item.label.toLowerCase().startsWith(normalizedQuery)\n )\n })\n const skillItems = await getSkillSuggestionItems(getSessionId(), query)\n return [...commandItems, ...skillItems]\n },\n )\n\n const appendFiles = async (files: FileList | File[]) => {\n const { accepted, rejected } = splitFilesBySize(files, ATTACHMENT_SIZE_LIMIT_BYTES)\n\n if (rejected.length > 0) {\n setOversizedFiles(rejected)\n }\n\n if (accepted.length === 0) {\n return\n }\n\n // Files are always staged as `pending` with the raw File handle; upload happens\n // at submit time so that no-active-session hosts (e.g. ship-attack left panel)\n // can create the session via `ensureSession` and still upload to workdir.\n const pendingFileAttachments: FileComposerAttachment[] = await Promise.all(\n accepted.map(async (file) => {\n const uploadName = await getUploadFileName(file)\n const id = `${uploadName}-${file.size}-${file.lastModified}-${Math.random().toString(36).slice(2)}`\n return {\n id,\n kind: \"file\" as const,\n name: uploadName,\n size: file.size,\n mimeType: file.type,\n status: \"pending\" as const,\n file,\n }\n }),\n )\n\n if (pendingFileAttachments.length > 0) {\n setComposerAttachments((prev) => [...prev, ...pendingFileAttachments])\n }\n }\n\n const stableAppendFiles = useEffectEvent((files: FileList | File[]) => appendFiles(files))\n\n const stableHandleSubmit = useEffectEvent(() => handleSubmit())\n\n const getEditorState = useEffectEvent(() => ({\n input,\n connectionStatus,\n navigateUp: inputHistory.navigateUp,\n navigateDown: inputHistory.navigateDown,\n isNavigatingHistory: inputHistory.isNavigating,\n handleSubmit: stableHandleSubmit,\n }))\n\n const syncEditorState = (editorInstance: TiptapEditor) => {\n const value = getEditorText(editorInstance)\n setInput(value)\n }\n\n const resetComposer = () => {\n editorRef.current?.commands.clearContent()\n setInput(\"\")\n setComposerAttachments([])\n }\n\n const editor = useEditor({\n immediatelyRender: false,\n extensions: [\n StarterKit.configure({\n blockquote: false,\n bulletList: false,\n codeBlock: false,\n dropcursor: false,\n gapcursor: false,\n heading: false,\n horizontalRule: false,\n orderedList: false,\n }),\n FileMention.configure({\n suggestion: {\n char: \"@\",\n pluginKey: fileMentionSuggestionKey,\n items: async ({ query }) => getFileSuggestionItems(getSessionId(), query),\n command: ({ editor: suggestionEditor, props, range }) => {\n const item = props as unknown as FileSuggestionItem\n suggestionEditor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: \"fileMention\",\n attrs: {\n name: item.name,\n path: item.path,\n },\n },\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run()\n },\n render: () => {\n let container: HTMLDivElement | null = null\n let root: ReturnType<typeof createRoot> | null = null\n const menuRef = { current: null as FileCompletionMenuRef | null }\n\n const handleExit = () => {\n const view = editorRef.current?.view\n if (view) {\n exitSuggestion(view, fileMentionSuggestionKey)\n }\n }\n\n const renderMenu = (props: FileCompletionMenuProps) => {\n if (!container || !root) return\n updateSuggestionPosition(container, props.clientRect)\n root.render(\n <FileCompletionMenu\n ref={(instance) => {\n menuRef.current = instance\n }}\n {...props}\n sessionId={getSessionId()}\n onExit={handleExit}\n />,\n )\n }\n\n return {\n onStart: (props: SuggestionProps) => {\n container = document.createElement(\"div\")\n document.body.appendChild(container)\n root = createRoot(container)\n renderMenu(props as unknown as FileCompletionMenuProps)\n },\n onUpdate: (props: SuggestionProps) => {\n renderMenu(props as unknown as FileCompletionMenuProps)\n },\n onExit: () => {\n menuRef.current = null\n root?.unmount()\n container?.remove()\n root = null\n container = null\n },\n onKeyDown: ({ event, view }: SuggestionKeyDownProps) => {\n if (event.key === \"Escape\") {\n event.preventDefault()\n exitSuggestion(view, fileMentionSuggestionKey)\n return true\n }\n\n return menuRef.current?.onKeyDown(event) ?? false\n },\n }\n },\n },\n }),\n SkillMention.configure({\n suggestion: {\n char: \"/\",\n pluginKey: skillMentionSuggestionKey,\n items: ({ query }) => getMentionSuggestionItems(query),\n command: ({ editor: suggestionEditor, props, range }) => {\n const item = props as unknown as SkillSuggestionItem\n if (item.type === \"command\") {\n suggestionEditor.chain().focus().deleteRange(range).run()\n void handleSlashCommand(item.id)\n return\n }\n suggestionEditor\n .chain()\n .focus()\n .insertContentAt(range, [\n {\n type: \"skillMention\",\n attrs: {\n skillId: item.skillId,\n displayName: skillDisplayName(item),\n description: item.description,\n },\n },\n {\n type: \"text\",\n text: \" \",\n },\n ])\n .run()\n },\n render: () => {\n let container: HTMLDivElement | null = null\n let root: ReturnType<typeof createRoot> | null = null\n const menuRef = { current: null as SkillCompletionMenuRef | null }\n\n const renderMenu = (props: SuggestionProps) => {\n if (!container || !root) return\n updateSuggestionPosition(container, props.clientRect)\n root.render(\n <SkillCompletionMenu\n ref={(instance) => {\n menuRef.current = instance\n }}\n items={props.items as SkillSuggestionItem[]}\n command={(item) => props.command(item)}\n />,\n )\n }\n\n return {\n onStart: (props: SuggestionProps) => {\n container = document.createElement(\"div\")\n document.body.appendChild(container)\n root = createRoot(container)\n renderMenu(props)\n },\n onUpdate: (props: SuggestionProps) => {\n renderMenu(props)\n },\n onExit: () => {\n menuRef.current = null\n root?.unmount()\n container?.remove()\n root = null\n container = null\n },\n onKeyDown: ({ event, view }: SuggestionKeyDownProps) => {\n if (event.key === \"Escape\") {\n event.preventDefault()\n exitSuggestion(view, skillMentionSuggestionKey)\n return true\n }\n\n return menuRef.current?.onKeyDown(event) ?? false\n },\n }\n },\n },\n }),\n ],\n content: \"\",\n onCreate: ({ editor: editorInstance }) => {\n editorRef.current = editorInstance\n syncEditorState(editorInstance)\n },\n onUpdate: ({ editor: editorInstance }) => {\n syncEditorState(editorInstance)\n },\n editorProps: {\n attributes: {\n \"aria-label\": \"输入消息\",\n class:\n \"min-h-[40px] max-h-[240px] overflow-y-auto px-4 py-3 text-sm leading-relaxed text-[hsl(var(--foreground))] focus:outline-none [&_.file-mention-pill]:inline-flex [&_.file-mention-pill]:items-center [&_.file-mention-pill]:rounded-full [&_.file-mention-pill]:bg-[hsl(var(--accent))] [&_.file-mention-pill]:px-2 [&_.file-mention-pill]:py-0.5 [&_.file-mention-pill]:font-medium [&_.file-mention-pill]:text-[hsl(var(--primary))] [&_.file-mention-pill]:select-none [&_.file-mention-pill]:whitespace-nowrap [&_.skill-mention-pill]:inline-flex [&_.skill-mention-pill]:items-center [&_.skill-mention-pill]:rounded-full [&_.skill-mention-pill]:bg-[hsl(var(--primary)/0.15)] [&_.skill-mention-pill]:px-2 [&_.skill-mention-pill]:py-0.5 [&_.skill-mention-pill]:font-medium [&_.skill-mention-pill]:text-[hsl(var(--primary))] [&_.skill-mention-pill]:select-none [&_.skill-mention-pill]:whitespace-nowrap [&_p:first-child]:mt-0 [&_p:last-child]:mb-0\",\n },\n handleDOMEvents: {\n focus: () => {\n setIsEditorFocused(true)\n return false\n },\n blur: () => {\n setIsEditorFocused(false)\n return false\n },\n keydown: (_view, event) => {\n const state = getEditorState()\n const fileMentionState = editorRef.current\n ? (fileMentionSuggestionKey.getState(editorRef.current.view.state) as\n | { active?: boolean }\n | undefined)\n : undefined\n\n if (fileMentionState?.active) {\n return false\n }\n\n const skillMentionState = editorRef.current\n ? (skillMentionSuggestionKey.getState(editorRef.current.view.state) as\n | { active?: boolean }\n | undefined)\n : undefined\n\n if (skillMentionState?.active) {\n return false\n }\n\n if (!event.isComposing && event.key === \"ArrowUp\" && (state.input.trim().length === 0 || state.isNavigatingHistory)) {\n const previousEntry = state.navigateUp(state.input)\n if (!previousEntry) {\n return false\n }\n\n event.preventDefault()\n replaceEditorText(editorRef.current, previousEntry)\n return true\n }\n\n if (!event.isComposing && event.key === \"ArrowDown\") {\n const nextEntry = state.navigateDown()\n if (nextEntry == null) {\n return false\n }\n\n event.preventDefault()\n replaceEditorText(editorRef.current, nextEntry)\n return true\n }\n\n if (event.key === \"Enter\" && !event.shiftKey && !event.isComposing) {\n event.preventDefault()\n if (state.connectionStatus !== \"connected\") {\n return true\n }\n void state.handleSubmit()\n return true\n }\n\n return false\n },\n paste: (_view, event) => {\n if (event.clipboardData?.files.length) {\n event.preventDefault()\n void stableAppendFiles(event.clipboardData.files)\n return true\n }\n return false\n },\n },\n },\n })\n\n useEffect(() => {\n if (!editor || !activeSessionId || rewindDraft == null) {\n return\n }\n\n editor.commands.clearContent()\n if (rewindDraft) {\n editor.commands.insertContent({ type: \"text\", text: rewindDraft })\n }\n editor.commands.focus(\"end\")\n setRewindDraft(activeSessionId, null)\n }, [activeSessionId, editor, rewindDraft, setRewindDraft])\n\n const submittingRef = useRef(false)\n\n useEffect(() => {\n let changed = false\n const nextLocalIds = new Set<string>()\n\n for (const attachment of composerAttachments) {\n if (!isImageAttachment(attachment) || !attachment.file || attachment.status === \"uploaded\") {\n continue\n }\n nextLocalIds.add(attachment.id)\n if (!localImageUrlsRef.current.has(attachment.id)) {\n localImageUrlsRef.current.set(attachment.id, URL.createObjectURL(attachment.file))\n changed = true\n }\n }\n\n for (const [attachmentId, url] of localImageUrlsRef.current) {\n if (nextLocalIds.has(attachmentId)) {\n continue\n }\n URL.revokeObjectURL(url)\n localImageUrlsRef.current.delete(attachmentId)\n changed = true\n }\n\n if (changed) {\n setLocalImageUrls(Object.fromEntries(localImageUrlsRef.current))\n }\n }, [composerAttachments])\n\n useEffect(() => {\n return () => {\n for (const url of localImageUrlsRef.current.values()) {\n URL.revokeObjectURL(url)\n }\n localImageUrlsRef.current.clear()\n }\n }, [])\n\n const applyDraftAppends = useEffectEvent(() => {\n if (!activeSessionId || !editor) {\n return\n }\n\n const appends = consumeDraftAppends(activeSessionId)\n if (appends.length === 0) {\n return\n }\n\n const text = appends.map((append) => append.text).join(\"\")\n if (!text) {\n return\n }\n\n editor.chain().focus(\"end\").insertContent(text).run()\n })\n\n useEffect(() => {\n if (!draftAppends?.length) {\n return\n }\n\n applyDraftAppends()\n }, [applyDraftAppends, draftAppends])\n\n const applySendRequests = useEffectEvent(() => {\n if (!activeSessionId) {\n return\n }\n\n const requests = consumeSendRequests(activeSessionId)\n if (requests.length === 0) {\n return\n }\n\n void stableHandleSubmit()\n })\n\n useEffect(() => {\n if (!sendRequests?.length) {\n return\n }\n\n applySendRequests()\n }, [applySendRequests, sendRequests])\n\n // ASR 语音输入:partial 实时替换、final 落定;录音中锁定编辑器\n const viteEnv = (import.meta as unknown as { env?: Record<string, string | undefined> }).env ?? {}\n const asrEnabled = useRuntimeFeaturesStore((s) => s.asrEnabled)\n const voice = useTiptapVoiceInput({\n editorRef,\n workletUrl: `${viteEnv.BASE_URL ?? \"/\"}asr/pcm-worklet.js`,\n onError: showVoiceInputErrorToast,\n })\n const { isRecording, level: voiceLevel } = voice\n const handleMicDisabledClick = () =>\n toast.info(\"语音输入功能未开启,请在后端 .env 配置 ASR_API_KEY\")\n\n // 流式中 / session 切换 时强制停录音,避免回调打到错会话\n const voiceStopRef = useRef(voice.stop)\n voiceStopRef.current = voice.stop\n\n useEffect(() => {\n if (isStreaming && isRecording) {\n void voiceStopRef.current()\n }\n }, [isStreaming, isRecording])\n\n const prevSessionIdRef = useRef(activeSessionId)\n useEffect(() => {\n if (prevSessionIdRef.current !== activeSessionId) {\n prevSessionIdRef.current = activeSessionId\n if (isRecording) {\n void voiceStopRef.current()\n }\n }\n }, [activeSessionId, isRecording])\n\n const handleSubmit = async () => {\n if (isStreaming || connectionStatus !== \"connected\") {\n return\n }\n if (submittingRef.current) {\n return\n }\n if (\n composerAttachments.some(\n (attachment) => attachment.kind === \"file\" && attachment.status === \"uploading\",\n )\n ) {\n return\n }\n submittingRef.current = true\n try {\n const json = editor?.getJSON()\n const rawText = serializeEditorContent(json)\n const skillName = findLeadingSkillMention(json)\n const text = skillName ? transformSlashCommand(skillName, rawText) : rawText\n\n const pendingFiles = composerAttachments.filter(\n (a): a is FileComposerAttachment => a.kind === \"file\" && a.status === \"pending\" && !!a.file,\n )\n let updatedAttachments = composerAttachments\n let uploadTargetSessionId: string | undefined\n if (pendingFiles.length > 0) {\n let uploadSessionId = activeSessionId\n if (!uploadSessionId && ensureSession) {\n try {\n uploadSessionId = await ensureSession(text || \"新会话\")\n } catch {\n setComposerAttachments((prev) =>\n prev.map((a) =>\n a.kind === \"file\" && a.status === \"pending\"\n ? { ...a, status: \"failed\" as const }\n : a,\n ),\n )\n return\n }\n }\n if (uploadSessionId) {\n uploadTargetSessionId = uploadSessionId\n if (pendingFiles.length > 0) {\n setComposerAttachments((prev) =>\n prev.map((a) =>\n a.kind === \"file\" && a.status === \"pending\"\n ? { ...a, status: \"uploading\" as const }\n : a,\n ),\n )\n try {\n const result = await uploadFiles(\n uploadSessionId,\n \".\",\n pendingFiles.map((a) => ({ file: a.file!, name: a.name })),\n )\n // Map pending file id → server result synchronously,\n // so buildSubmitPayload sees the correct server-deduped names.\n const uploadResultById = new Map<string, string | null>()\n const failedSet = new Set(result.failed)\n let uploadIdx = 0\n for (const pf of pendingFiles) {\n if (failedSet.has(pf.name)) {\n failedSet.delete(pf.name)\n uploadResultById.set(pf.id, null)\n } else {\n uploadResultById.set(pf.id, result.uploaded[uploadIdx++] ?? null)\n }\n }\n updatedAttachments = composerAttachments.map((a) => {\n if (!uploadResultById.has(a.id)) return a\n const uploadedPath = uploadResultById.get(a.id)\n if (!uploadedPath) return { ...a, status: \"failed\" as const }\n const actualName = uploadedPath.split(\"/\").pop() || a.name\n return { ...a, name: actualName, status: \"uploaded\" as const, uploadedPath }\n })\n setComposerAttachments(updatedAttachments)\n if (result.uploaded.length > 0) {\n void queryClient.invalidateQueries({ queryKey: [\"file-tree\", uploadSessionId] })\n }\n } catch {\n setComposerAttachments((prev) =>\n prev.map((a) =>\n a.kind === \"file\" && a.status === \"uploading\"\n ? { ...a, status: \"failed\" as const }\n : a,\n ),\n )\n return\n }\n }\n }\n }\n\n const activePendingContexts = pendingContexts ?? []\n const nextPayload = buildSubmitPayload(\n text,\n updatedAttachments,\n activePendingContexts,\n onBeforeSend,\n )\n if (isMessageContentEmpty(nextPayload)) {\n return\n }\n if (activeSessionId && activePendingContexts.length > 0) {\n consumePendingContexts(activeSessionId)\n }\n onSend(nextPayload, uploadTargetSessionId, selectedModel || null)\n if (text.trim()) {\n inputHistory.addEntry(text)\n }\n resetComposer()\n } finally {\n submittingRef.current = false\n }\n }\n\n const removeAttachment = (id: string) => {\n setComposerAttachments((prev) => prev.filter((attachment) => attachment.id !== id))\n }\n\n const [showAddContext, setShowAddContext] = useState(false)\n const isPlanning = mode === \"planning\"\n const placeholder = isPlanning ? \"规划进行中… 可输入补充需求或等待完成\" : \"输入消息…\"\n const attachments = renderAttachments?.() ?? null\n const hasRenderedAttachments = attachments !== null\n const hasPendingContexts = (pendingContexts?.length ?? 0) > 0\n const currentSession = useSessionStore((state) =>\n activeSessionId ? state.sessions.find((s) => s.id === activeSessionId) : undefined,\n )\n const isSkillEditor =\n currentSession?.solution_id === \"skill_editor\" ||\n currentSession?.template_id === \"skill_editor\"\n const imageAttachments = composerAttachments.filter(isImageAttachment)\n const fileAttachments = composerAttachments.filter(\n (attachment): attachment is FileComposerAttachment => !isImageAttachment(attachment),\n )\n const hasUploadingFiles = composerAttachments.some(\n (attachment) => attachment.status === \"uploading\",\n )\n const hasValidAttachments = composerAttachments.some((attachment) => attachment.status !== \"failed\")\n const isSendDisabled =\n connectionStatus !== \"connected\" ||\n hasUploadingFiles ||\n (!input.trim() && !hasValidAttachments && !hasRenderedAttachments && !hasPendingContexts)\n\n return (\n <>\n <div className=\"bg-[hsl(var(--background))] px-5 py-3\">\n <div className={`mx-auto ${maxWidthClassName}`}>\n <div\n className=\"relative\"\n onDragOver={(event) => {\n event.preventDefault()\n setDragging(true)\n }}\n onDragLeave={() => setDragging(false)}\n onDrop={(event) => {\n event.preventDefault()\n setDragging(false)\n void stableAppendFiles(event.dataTransfer.files)\n }}\n >\n <div\n className={`overflow-visible rounded-2xl border bg-[hsl(var(--card))] transition-[box-shadow,border-color] duration-300 ${\n isRecording\n ? \"border-emerald-400/70! shadow-[0_0_0_3px_rgba(52,211,153,0.18),0_0_24px_rgba(52,211,153,0.28)]\"\n : dragging\n ? isPlanning\n ? \"border-amber-400/60\"\n : \"border-[hsl(var(--primary)/0.6)]\"\n : isEditorFocused\n ? isPlanning\n ? \"border-amber-400/60\"\n : \"border-[hsl(var(--primary)/0.6)]\"\n : isPlanning\n ? \"border-amber-400/30\"\n : \"border-[hsl(var(--border))]\"\n }`}\n >\n {composerAttachments.length > 0 && (\n <div className=\"flex max-h-40 flex-col gap-2 overflow-y-auto border-b border-[hsl(var(--border))] px-3 py-2\">\n {imageAttachments.length > 0 && (\n <div className=\"grid grid-cols-3 gap-2\">\n {imageAttachments.map((attachment) => (\n <div\n key={attachment.id}\n className=\"relative overflow-hidden rounded-xl border border-[hsl(var(--border))]\"\n >\n <img\n src={getImagePreviewUrl(attachment, activeSessionId, localImageUrls)}\n alt={attachment.name || \"图片预览\"}\n className=\"h-24 w-full object-cover\"\n />\n <button\n type=\"button\"\n onClick={() => removeAttachment(attachment.id)}\n aria-label={`移除 ${attachment.name || \"图片\"}`}\n className=\"absolute right-1.5 top-1.5 flex h-6 w-6 items-center justify-center rounded-full bg-[hsl(var(--background)/0.85)] text-[hsl(var(--foreground))]\"\n >\n <X size={12} />\n </button>\n </div>\n ))}\n </div>\n )}\n {fileAttachments.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {fileAttachments.map((attachment) => (\n <ComposerFilePill\n key={attachment.id}\n attachment={attachment}\n onRemove={removeAttachment}\n />\n ))}\n </div>\n )}\n </div>\n )}\n {(hasPendingContexts || isSkillEditor) ? (\n <div className=\"flex flex-wrap items-center gap-1.5 border-b border-[hsl(var(--border))] px-3 py-2\">\n {pendingContexts?.map((context) => (\n <ComposerContextPill\n key={context.id}\n id={context.id}\n label={context.label}\n content={context.content}\n onRemove={(contextId) => {\n if (!activeSessionId) {\n return\n }\n removePendingContext(activeSessionId, contextId)\n }}\n />\n ))}\n {isSkillEditor && (\n <button\n type=\"button\"\n onClick={() => setShowAddContext(true)}\n title=\"添加上下文\"\n className=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-dashed border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]\"\n >\n <Plus size={12} />\n </button>\n )}\n </div>\n ) : null}\n {showAddContext && activeSessionId && (\n <AddContextDialog\n sessionId={activeSessionId}\n onClose={() => setShowAddContext(false)}\n onAdd={(label, content) => {\n if (activeSessionId) {\n useUiBridgeStore.getState().addPendingContext(activeSessionId, { label, content })\n }\n }}\n />\n )}\n {attachments ? (\n <div className=\"border-b border-[hsl(var(--border))] px-3 py-3\">\n {attachments}\n </div>\n ) : null}\n {slotAboveTextarea ? (\n <div className=\"border-b border-[hsl(var(--border))] px-3 py-2\">\n {slotAboveTextarea}\n </div>\n ) : null}\n <div className=\"relative\">\n {input.length === 0 && (\n <div className=\"pointer-events-none absolute left-4 top-3 text-sm leading-relaxed text-[hsl(var(--muted-foreground))]\">\n {placeholder}\n </div>\n )}\n <EditorContent editor={editor} />\n </div>\n <div className=\"flex items-center justify-between border-t border-[hsl(var(--border))] px-3 py-1.5\">\n <div className=\"flex items-center gap-2\">\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"*/*\"\n multiple\n onChange={(event) => {\n if (event.target.files) {\n void appendFiles(event.target.files)\n event.target.value = \"\"\n }\n }}\n className=\"hidden\"\n />\n <input\n ref={folderInputRef}\n type=\"file\"\n multiple\n onChange={(event) => {\n if (event.target.files) {\n void appendFiles(event.target.files)\n event.target.value = \"\"\n }\n }}\n className=\"hidden\"\n // biome-ignore lint/suspicious/noExplicitAny: webkitdirectory is a non-standard HTML attribute\n {...({ webkitdirectory: \"\" } as any)}\n />\n <details ref={actionMenuRef} className=\"group relative\">\n <summary\n aria-label=\"添加内容\"\n title=\"添加内容\"\n className=\"flex h-7 w-7 shrink-0 cursor-pointer list-none items-center justify-center rounded-lg border border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] [&::-webkit-details-marker]:hidden\"\n >\n <Plus size={14} />\n </summary>\n <div className=\"absolute bottom-full left-0 z-30 mb-2 min-w-36 overflow-visible rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 text-[11px] text-[hsl(var(--popover-foreground))] shadow-lg\">\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n fileInputRef.current?.click()\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <Paperclip size={13} />\n 上传文件\n </button>\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n folderInputRef.current?.click()\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <FolderUp size={13} />\n 上传文件夹\n </button>\n {onCommand ? (\n <>\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n void onCommand(\"compact\")\n }}\n disabled={isStreaming}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {isStreaming ? <Loader2 size={13} className=\"animate-spin\" /> : <Scissors size={13} />}\n 整理对话\n </button>\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n void onCommand(\"download_session\")\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <Download size={13} />\n 导出会话\n </button>\n {canShareSession ? (\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n void onCommand(\"share_session\")\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <Share2 size={13} />\n 分享会话\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n void onCommand(\"extract_skill\")\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <FlaskConical size={13} />\n 提取技能\n </button>\n <button\n type=\"button\"\n onClick={() => {\n actionMenuRef.current?.removeAttribute(\"open\")\n void onCommand(\"generate_app\")\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <Rocket size={13} />\n 生成应用\n </button>\n </>\n ) : null}\n <div className=\"flex items-center gap-2 px-3 py-2\">\n <Sparkles size={13} />\n <span className=\"shrink-0\">模型</span>\n <ModelSelector\n value={selectedModel}\n onValueChange={(model) => {\n setSelectedModel(model)\n if (activeSessionId) {\n patchSession(activeSessionId, { model })\n }\n setPreferredModel(model)\n }}\n compact\n placement=\"top\"\n />\n </div>\n </div>\n </details>\n <button\n type=\"button\"\n onClick={onToggleMode}\n disabled={isStreaming || !onToggleMode}\n aria-pressed={isPlanning}\n aria-label={isPlanning ? \"关闭规划模式\" : \"开启规划模式\"}\n title={isPlanning ? \"规划模式已开启\" : \"开启规划模式\"}\n className={`flex h-7 w-7 shrink-0 items-center justify-center rounded-lg border transition-colors ${\n isPlanning\n ? \"border-amber-500/45 bg-amber-500/15 text-amber-400\"\n : \"border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-amber-500/35 hover:text-[hsl(var(--foreground))]\"\n } disabled:cursor-not-allowed disabled:opacity-50`}\n >\n <Lightbulb size={13} />\n </button>\n </div>\n <div className=\"flex items-center gap-1.5\">\n <div className=\"group/help relative\">\n <button\n type=\"button\"\n aria-label=\"查看输入提示\"\n className=\"flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]\"\n >\n <CircleHelp size={13} />\n </button>\n <div className=\"pointer-events-auto absolute bottom-full right-0 z-30 hidden pb-2 group-hover/help:block group-focus-within/help:block\">\n <div className=\"min-w-64 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-3 text-left text-[11px] leading-5 text-[hsl(var(--popover-foreground))] shadow-lg\">\n {activeSessionId ? (\n <div className=\"mb-2 border-b border-[hsl(var(--border))] pb-2\">\n <SkillStatusBar\n sessionId={activeSessionId}\n onResync={onResyncSkills}\n isResyncing={isResyncingSkills}\n vertical\n />\n </div>\n ) : null}\n <div className=\"space-y-0.5\">\n <div>Shift+Enter 换行</div>\n <div>/ 调用技能</div>\n <div>@ 引用文件</div>\n </div>\n </div>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={asrEnabled ? voice.toggle : handleMicDisabledClick}\n disabled={isStreaming}\n aria-label={\n !asrEnabled ? \"语音输入未开启\" : isRecording ? \"停止语音输入\" : \"开始语音输入\"\n }\n title={\n !asrEnabled ? \"语音输入未开启\" : isRecording ? \"停止语音输入\" : \"语音输入\"\n }\n className={`flex items-center justify-center rounded-lg border transition-[width,height,border-color,background-color,color,box-shadow] duration-300 disabled:opacity-40 ${\n !asrEnabled\n ? \"h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))]/50 hover:text-[hsl(var(--muted-foreground))]\"\n : isRecording\n ? \"h-9 w-9 border-emerald-400/80! bg-emerald-400/15 text-emerald-400 shadow-[0_0_0_2px_rgba(52,211,153,0.2),0_0_12px_rgba(52,211,153,0.35)]\"\n : \"h-7 w-7 border-[hsl(var(--border))] text-[hsl(var(--muted-foreground))] hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))]\"\n }`}\n >\n {!asrEnabled ? (\n <MicOff size={13} />\n ) : isRecording ? (\n <VoiceWaveform level={voiceLevel} size={18} />\n ) : (\n <Mic size={13} />\n )}\n </button>\n {isStreaming ? (\n <button\n type=\"button\"\n onClick={onStop}\n aria-label=\"停止生成\"\n className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--destructive))] text-[hsl(var(--destructive-foreground))] transition-opacity hover:opacity-80\"\n >\n <Square size={13} />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isSendDisabled || isRecording}\n aria-label=\"发送消息\"\n className=\"flex h-7 w-7 items-center justify-center rounded-lg bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-80 disabled:opacity-25\"\n >\n <Send size={13} />\n </button>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <FileSizeLimitDialog\n open={oversizedFiles.length > 0}\n onOpenChange={(open) => {\n if (!open) {\n setOversizedFiles([])\n }\n }}\n files={oversizedFiles}\n limitBytes={ATTACHMENT_SIZE_LIMIT_BYTES}\n />\n </>\n )\n}\n","import type { Editor as TiptapEditor } from \"@tiptap/react\"\nimport { useCallback, useEffect, useEffectEvent, useRef } from \"react\"\nimport { useVoiceInput, type VoiceInputStatus } from \"./use-voice-input\"\nimport type { VoiceInputError } from \"./voice-input-support\"\n\nexport interface UseTiptapVoiceInputOptions {\n /** Tiptap editor ref;null 时 voice 回调会静默丢弃 */\n editorRef: { current: TiptapEditor | null }\n /** AudioWorklet processor 文件 URL */\n workletUrl: string\n /** 外部可选回调:识别错误时拿 message */\n onError?: (error: VoiceInputError) => void\n}\n\nexport interface UseTiptapVoiceInputResult {\n status: VoiceInputStatus\n isRecording: boolean\n error: string | null\n /** 当前音频 RMS 幅度,0..1,仅在 recording 期间有意义,用于驱动波形动画 */\n level: number\n toggle: () => void\n stop: () => Promise<void>\n}\n\n/**\n * Tiptap 编辑器里的语音输入集成:\n * - partial 段用 `insertContentAt({from,to}, text)` 替换一个可变 range\n * - final 段落定后把 range 推进到末尾,下一段重新起\n * - 录音期间调用 `editor.setEditable(false)` 锁定键盘输入\n */\nexport function useTiptapVoiceInput(\n options: UseTiptapVoiceInputOptions,\n): UseTiptapVoiceInputResult {\n const { editorRef, workletUrl, onError } = options\n const partialRangeRef = useRef<{ from: number; to: number } | null>(null)\n // 最近一次 partial 的字符数:豆包 result_type=single 模式下每段话 VAD 结束后\n // 累积器会归零,下一段 partial 从空开始增长。只要新 partial 比上一次短,就\n // 说明跨过了句子边界:把之前的内容冻结在原位,为新句子开新 range。\n const lastPartialLenRef = useRef(0)\n\n const handlePartial = useEffectEvent((text: string) => {\n const ed = editorRef.current\n if (!ed) return\n let range = partialRangeRef.current\n if (range && text.length < lastPartialLenRef.current) {\n range = { from: range.to, to: range.to }\n partialRangeRef.current = range\n }\n if (!range) {\n const pos = ed.state.selection.from\n range = { from: pos, to: pos }\n partialRangeRef.current = range\n }\n const { from, to } = range\n if (text) {\n ed.chain().insertContentAt({ from, to }, text).run()\n partialRangeRef.current = { from, to: from + text.length }\n lastPartialLenRef.current = text.length\n } else if (to > from) {\n ed.chain().deleteRange({ from, to }).run()\n partialRangeRef.current = { from, to: from }\n lastPartialLenRef.current = 0\n }\n })\n\n const handleFinal = useEffectEvent((text: string) => {\n const ed = editorRef.current\n if (!ed || !text) return\n const range = partialRangeRef.current\n if (range) {\n ed.chain().insertContentAt({ from: range.from, to: range.to }, text).run()\n const newEnd = range.from + text.length\n partialRangeRef.current = { from: newEnd, to: newEnd }\n } else {\n ed.chain().focus(\"end\").insertContent(text).run()\n }\n lastPartialLenRef.current = 0\n })\n\n const handleError = useEffectEvent((error: VoiceInputError) => {\n partialRangeRef.current = null\n lastPartialLenRef.current = 0\n onError?.(error)\n })\n\n const voice = useVoiceInput({\n workletUrl,\n onPartial: handlePartial,\n onFinal: handleFinal,\n onError: handleError,\n })\n\n const isRecording = voice.status === \"recording\"\n\n // 录音中锁定编辑器\n useEffect(() => {\n const ed = editorRef.current\n if (!ed) return\n ed.setEditable(!isRecording)\n }, [isRecording, editorRef])\n\n // 回到 idle/error 时清掉 range 游标\n useEffect(() => {\n if (voice.status === \"idle\" || voice.status === \"error\") {\n partialRangeRef.current = null\n lastPartialLenRef.current = 0\n }\n }, [voice.status])\n\n const toggle = useCallback(() => {\n if (voice.status === \"recording\") {\n void voice.stop()\n } else {\n void voice.start()\n }\n }, [voice])\n\n return {\n status: voice.status,\n isRecording,\n error: voice.error,\n level: voice.level,\n toggle,\n stop: voice.stop,\n }\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\"\nimport { getSocket } from \"../api/socket\"\nimport {\n buildVoiceInputUnavailableError,\n type VoiceInputError,\n} from \"./voice-input-support\"\n\nexport type VoiceInputStatus = \"idle\" | \"starting\" | \"recording\" | \"stopping\" | \"error\"\n\nexport interface UseVoiceInputOptions {\n workletUrl: string\n onPartial?: (text: string) => void\n onFinal?: (text: string) => void\n onError?: (error: VoiceInputError) => void\n}\n\nexport interface UseVoiceInputResult {\n status: VoiceInputStatus\n error: string | null\n /** 当前音频 RMS 幅度,0..1,仅在 recording 期间有意义,用于驱动波形动画 */\n level: number\n start: () => Promise<void>\n stop: () => Promise<void>\n}\n\ninterface Session {\n requestId: string\n stream: MediaStream\n ctx: AudioContext\n source: MediaStreamAudioSourceNode\n workletNode: AudioWorkletNode\n handlers: {\n partial: (data: unknown) => void\n final: (data: unknown) => void\n error: (data: unknown) => void\n }\n disposed: boolean\n flushAck: (() => void) | null\n}\n\nconst STARTUP_TIMEOUT_MS = 6000\n// 批式 provider(如 Qwen)要等整段转写跑完才会发 asr:closed,可能 5–10s;\n// 流式 provider(火山)通常 <1s 就到 closed。给一个够宽的兜底,正常路径由\n// asr:closed 事件即时 resolve,不会真的等够这么久。\nconst STOP_TIMEOUT_MS = 30000\nconst FLUSH_ACK_TIMEOUT_MS = 200\n\nfunction matchesRequest(data: unknown, requestId: string): boolean {\n const rid = (data as { request_id?: string })?.request_id\n return !rid || rid === requestId\n}\n\nexport function useVoiceInput(options: UseVoiceInputOptions): UseVoiceInputResult {\n const [status, setStatus] = useState<VoiceInputStatus>(\"idle\")\n const [error, setError] = useState<string | null>(null)\n const [level, setLevel] = useState(0)\n const sessionRef = useRef<Session | null>(null)\n const startingRef = useRef(false)\n const stoppingRef = useRef(false)\n const unmountedRef = useRef(false)\n const optionsRef = useRef(options)\n optionsRef.current = options\n\n const reportError = useCallback((err: string | VoiceInputError) => {\n const payload = typeof err === \"string\" ? { title: err } : err\n setError(payload.title)\n setStatus(\"error\")\n setLevel(0)\n optionsRef.current.onError?.(payload)\n }, [])\n\n const disposeSession = useCallback((s: Session) => {\n if (s.disposed) return\n s.disposed = true\n const socket = getSocket()\n socket.off(\"asr:partial\", s.handlers.partial)\n socket.off(\"asr:final\", s.handlers.final)\n socket.off(\"asr:error\", s.handlers.error)\n try {\n s.workletNode.port.onmessage = null\n s.workletNode.disconnect()\n } catch {}\n try {\n s.source.disconnect()\n } catch {}\n try {\n for (const t of s.stream.getTracks()) t.stop()\n } catch {}\n try {\n void s.ctx.close()\n } catch {}\n }, [])\n\n const stop = useCallback(async () => {\n const s = sessionRef.current\n if (!s || stoppingRef.current) {\n setStatus((prev) => (prev === \"error\" ? \"error\" : \"idle\"))\n return\n }\n stoppingRef.current = true\n setStatus(\"stopping\")\n\n // 尾部 <100ms 的音频 flush,等 worklet 回 ack 再继续\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, FLUSH_ACK_TIMEOUT_MS)\n s.flushAck = () => {\n clearTimeout(timer)\n resolve()\n }\n try {\n s.workletNode.port.postMessage(\"flush\")\n } catch {\n clearTimeout(timer)\n resolve()\n }\n })\n\n // 等 closed,期间保持 partial/final 监听活着以收尾部识别结果;超时兜底\n const socket = getSocket()\n await new Promise<void>((resolve) => {\n let settled = false\n const finish = () => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n socket.off(\"asr:closed\", onClosed)\n resolve()\n }\n const onClosed = (data: unknown) => {\n if (matchesRequest(data, s.requestId)) finish()\n }\n const timer = setTimeout(finish, STOP_TIMEOUT_MS)\n socket.on(\"asr:closed\", onClosed)\n socket.emit(\"asr:stop\", { request_id: s.requestId })\n })\n\n // 等服务端 final/closed 到齐后再 off partial/final/error 并释放资源\n disposeSession(s)\n if (sessionRef.current === s) {\n sessionRef.current = null\n }\n stoppingRef.current = false\n setLevel(0)\n setStatus((prev) => (prev === \"error\" ? \"error\" : \"idle\"))\n }, [disposeSession])\n\n const start = useCallback(async () => {\n if (\n sessionRef.current ||\n startingRef.current ||\n stoppingRef.current ||\n unmountedRef.current\n ) {\n return\n }\n startingRef.current = true\n setError(null)\n setStatus(\"starting\")\n\n if (typeof window === \"undefined\" || !navigator.mediaDevices?.getUserMedia) {\n startingRef.current = false\n reportError(buildVoiceInputUnavailableError())\n return\n }\n\n let stream: MediaStream | null = null\n let ctx: AudioContext | null = null\n let source: MediaStreamAudioSourceNode | null = null\n let workletNode: AudioWorkletNode | null = null\n const socket = getSocket()\n const requestId =\n typeof crypto !== \"undefined\" && crypto.randomUUID\n ? crypto.randomUUID()\n : `asr-${Date.now()}-${Math.random().toString(36).slice(2)}`\n\n const cleanupPartial = () => {\n if (workletNode) {\n try {\n workletNode.port.onmessage = null\n workletNode.disconnect()\n } catch {}\n }\n if (source) {\n try {\n source.disconnect()\n } catch {}\n }\n if (stream) {\n try {\n for (const t of stream.getTracks()) t.stop()\n } catch {}\n }\n if (ctx) {\n try {\n void ctx.close()\n } catch {}\n }\n }\n\n const checkCancelled = (): boolean => {\n if (unmountedRef.current) {\n cleanupPartial()\n // 若已经对后端发过 asr:start,补发 asr:stop 让服务端释放 bridge\n try {\n getSocket().emit(\"asr:stop\", { request_id: requestId })\n } catch {}\n return true\n }\n return false\n }\n\n try {\n stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n channelCount: 1,\n sampleRate: 16000,\n echoCancellation: true,\n noiseSuppression: true,\n autoGainControl: true,\n },\n })\n if (checkCancelled()) return\n const AudioCtx: typeof AudioContext =\n window.AudioContext ??\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext!\n ctx = new AudioCtx({ sampleRate: 16000 })\n await ctx.audioWorklet.addModule(optionsRef.current.workletUrl)\n if (checkCancelled()) return\n source = ctx.createMediaStreamSource(stream)\n workletNode = new AudioWorkletNode(ctx, \"pcm-processor\")\n\n // 等后端 ready(带作用域)\n await new Promise<void>((resolve, reject) => {\n let settled = false\n const finish = (ok: boolean, err?: string) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n socket.off(\"asr:ready\", onReady)\n socket.off(\"asr:error\", onEarlyError)\n if (ok) resolve()\n else reject(new Error(err ?? \"unknown\"))\n }\n const onReady = (data: unknown) => {\n if (matchesRequest(data, requestId)) finish(true)\n }\n const onEarlyError = (data: unknown) => {\n if (!matchesRequest(data, requestId)) return\n finish(false, (data as { message?: string })?.message ?? \"后端语音识别启动失败\")\n }\n const timer = setTimeout(() => finish(false, \"语音识别连接超时\"), STARTUP_TIMEOUT_MS)\n socket.on(\"asr:ready\", onReady)\n socket.on(\"asr:error\", onEarlyError)\n socket.emit(\"asr:start\", { request_id: requestId })\n })\n if (checkCancelled()) return\n\n // 订阅运行期事件(按 request_id 过滤)\n const onPartial = (data: unknown) => {\n if (!matchesRequest(data, requestId)) return\n const text = (data as { text?: string })?.text\n if (text) optionsRef.current.onPartial?.(text)\n }\n const onFinal = (data: unknown) => {\n if (!matchesRequest(data, requestId)) return\n const text = (data as { text?: string })?.text\n if (text) optionsRef.current.onFinal?.(text)\n }\n const onError = (data: unknown) => {\n if (!matchesRequest(data, requestId)) return\n const msg = (data as { message?: string })?.message ?? \"语音识别失败\"\n const cur = sessionRef.current\n if (cur && cur.requestId === requestId) {\n sessionRef.current = null\n disposeSession(cur)\n }\n reportError(msg)\n }\n socket.on(\"asr:partial\", onPartial)\n socket.on(\"asr:final\", onFinal)\n socket.on(\"asr:error\", onError)\n\n const session: Session = {\n requestId,\n stream,\n ctx,\n source,\n workletNode,\n handlers: { partial: onPartial, final: onFinal, error: onError },\n disposed: false,\n flushAck: null,\n }\n\n workletNode.port.onmessage = (ev) => {\n const msg = ev.data as\n | { type: \"flushed\" }\n | { type: \"audio\"; pcm: ArrayBuffer; level: number }\n | undefined\n if (!msg || typeof msg !== \"object\") return\n if (msg.type === \"flushed\") {\n session.flushAck?.()\n session.flushAck = null\n return\n }\n if (msg.type !== \"audio\") return\n if (!(msg.pcm instanceof ArrayBuffer) || msg.pcm.byteLength === 0) return\n // RMS ~ 0..0.3 for typical speech;放大到 0..1 区间给 UI 用\n setLevel(Math.min(1, msg.level * 4))\n socket.emit(\"asr:audio\", { pcm: msg.pcm, request_id: requestId })\n }\n source.connect(workletNode)\n\n sessionRef.current = session\n setStatus(\"recording\")\n } catch (err) {\n cleanupPartial()\n const msg = err instanceof Error ? err.message : String(err)\n reportError(msg)\n } finally {\n startingRef.current = false\n }\n }, [reportError, disposeSession])\n\n // 组件卸载时停止录音与正在进行的 start 流程,避免 MediaStream / AudioContext /\n // socket listener / 后端 bridge 泄漏\n useEffect(() => {\n unmountedRef.current = false\n return () => {\n unmountedRef.current = true\n const s = sessionRef.current\n if (s) {\n sessionRef.current = null\n disposeSession(s)\n try {\n getSocket().emit(\"asr:stop\", { request_id: s.requestId })\n } catch {}\n }\n }\n }, [disposeSession])\n\n return { status, error, level, start, stop }\n}\n","export interface VoiceInputError {\n title: string\n description?: string\n}\n\nfunction isIpHost(hostname: string): boolean {\n if (!hostname) {\n return false\n }\n if (/^\\d{1,3}(?:\\.\\d{1,3}){3}$/.test(hostname)) {\n return true\n }\n return hostname.includes(\":\")\n}\n\nexport function buildVoiceInputUnavailableError(): VoiceInputError {\n if (typeof window === \"undefined\") {\n return { title: \"当前浏览器不支持麦克风采集\" }\n }\n\n const { location } = window\n if (!window.isSecureContext && location.protocol === \"http:\" && isIpHost(location.hostname)) {\n return {\n title: \"当前浏览器未开放语音输入\",\n description: [\n `你正在通过内网 IP 访问 ${location.origin}。`,\n \"Chrome / Edge 可按以下方式手工开启:\",\n \"1. 打开 chrome://flags/#unsafely-treat-insecure-origin-as-secure\",\n \" Edge 请打开 edge://flags/#unsafely-treat-insecure-origin-as-secure\",\n \"2. 启用该 flag,并填入完整 origin(必须带协议和端口)\",\n ` 当前可直接填写:${location.origin}`,\n \"3. 重启浏览器\",\n \"4. 重新打开页面,并在站点权限里允许麦克风\",\n ].join(\"\\n\"),\n }\n }\n\n return {\n title: \"当前浏览器不支持麦克风采集\",\n description: \"请使用最新版 Chrome / Edge,或改用 HTTPS、localhost 访问。\",\n }\n}\n","interface VoiceWaveformProps {\n /** RMS 幅度 0..1 */\n level: number\n /** 线条颜色;默认跟随 currentColor */\n color?: string\n /** 按钮直径参考值,决定波形尺寸 */\n size?: number\n}\n\n// 五根竖条,中间最高、两边递减。每根用不同的乘数制造错落感,但都由同一个 level 驱动:\n// 说话时整体跃起,静音时平直。CSS transform 让浏览器走 GPU 合成层,100ms 一次的\n// setState 足够顺。\nconst BAR_MULTIPLIERS = [0.45, 0.75, 1, 0.75, 0.45]\n\nexport function VoiceWaveform({ level, color = \"currentColor\", size = 16 }: VoiceWaveformProps) {\n const barWidth = Math.max(1.5, size / 10)\n const gap = Math.max(1, size / 14)\n const maxHeight = size * 0.85\n const minHeight = Math.max(2, size / 8)\n\n return (\n <div\n aria-hidden=\"true\"\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap,\n height: size,\n }}\n >\n {BAR_MULTIPLIERS.map((mul, i) => {\n const h = minHeight + (maxHeight - minHeight) * Math.min(1, level * mul)\n return (\n <span\n key={i}\n style={{\n width: barWidth,\n height: h,\n borderRadius: barWidth,\n backgroundColor: color,\n transition: \"height 80ms linear\",\n }}\n />\n )\n })}\n </div>\n )\n}\n","import { Loader2, Sparkles } from \"lucide-react\"\nimport { useEffect, useMemo, useRef, useState } from \"react\"\nimport { useModelConfig } from \"../../hooks/use-model-preferences\"\n\ntype ModelSelectorProps = {\n value: string\n onValueChange: (model: string) => void\n disabled?: boolean\n compact?: boolean\n placement?: \"top\" | \"bottom\"\n}\n\nexport function ModelSelector({\n value,\n onValueChange,\n disabled = false,\n compact = false,\n placement = \"bottom\",\n}: ModelSelectorProps) {\n const { models, defaultModel, isLoading } = useModelConfig()\n const [isOpen, setIsOpen] = useState(false)\n const [query, setQuery] = useState(\"\")\n const rootRef = useRef<HTMLDivElement | null>(null)\n\n useEffect(() => {\n if (!isOpen) return\n const closeOnPointerDown = (event: PointerEvent) => {\n if (!rootRef.current?.contains(event.target as Node)) {\n setIsOpen(false)\n }\n }\n window.addEventListener(\"pointerdown\", closeOnPointerDown)\n return () => window.removeEventListener(\"pointerdown\", closeOnPointerDown)\n }, [isOpen])\n\n const filteredModels = useMemo(() => {\n const normalized = query.trim().toLowerCase()\n if (!normalized) return models\n return models.filter(\n (model) =>\n model.id.toLowerCase().includes(normalized) ||\n model.label.toLowerCase().includes(normalized),\n )\n }, [models, query])\n\n const canSelect = models.length > 0\n const selectedLabel = models.find((model) => model.id === value)?.label\n const defaultLabel = models.find((model) => model.id === defaultModel)?.label\n const label = isLoading\n ? \"正在加载模型...\"\n : selectedLabel || defaultLabel || value.trim() || defaultModel || \"未连接到模型\"\n const dropdownPosition =\n placement === \"top\" ? \"bottom-[calc(100%+8px)]\" : \"top-[calc(100%+8px)]\"\n\n if (!canSelect) {\n return (\n <div\n className=\"flex min-w-0 items-center gap-1 rounded-lg px-2.5 py-[5px] text-[hsl(var(--muted-foreground))]\"\n title={label}\n >\n {isLoading ? (\n <Loader2 size={14} className=\"animate-spin\" aria-hidden=\"true\" />\n ) : (\n <Sparkles size={14} aria-hidden=\"true\" />\n )}\n <span className={`whitespace-nowrap text-xs ${compact ? \"\" : \"max-w-[180px]\"}`}>\n {label}\n </span>\n </div>\n )\n }\n\n return (\n <div ref={rootRef} className=\"relative\">\n <button\n type=\"button\"\n disabled={disabled}\n onClick={() => setIsOpen((current) => !current)}\n className=\"flex min-w-0 items-center gap-1 rounded-lg px-2.5 py-[5px] text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50\"\n title={label}\n >\n <Sparkles size={14} aria-hidden=\"true\" />\n <span className={`whitespace-nowrap text-xs ${compact ? \"\" : \"max-w-[180px]\"}`}>\n {label}\n </span>\n </button>\n\n {isOpen && (\n <div\n className={`absolute right-0 z-50 w-[260px] overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] shadow-xl ${\n dropdownPosition\n }`}\n >\n <div className=\"border-b border-[hsl(var(--border))] p-2\">\n <input\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n placeholder=\"筛选模型...\"\n className=\"h-8 w-full rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--background))] px-2.5 text-xs text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground))] focus:border-[hsl(var(--ring))]\"\n />\n </div>\n <div className=\"max-h-[220px] overflow-y-auto p-1\">\n {filteredModels.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">\n 没有匹配的模型\n </div>\n ) : (\n filteredModels.map((model) => (\n <button\n key={model.id}\n type=\"button\"\n onClick={() => {\n onValueChange(model.id)\n setIsOpen(false)\n setQuery(\"\")\n }}\n className={`block w-full truncate rounded-lg px-3 py-2 text-left text-xs transition-colors ${\n model.id === value\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--foreground))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n }`}\n title={model.id === model.label ? model.id : `${model.label} (${model.id})`}\n >\n {model.label}\n </button>\n ))\n )}\n </div>\n </div>\n )}\n </div>\n )\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\"\nimport { getModelsConfig, type ModelOption } from \"../api/models\"\nimport { getUserPreference, setUserPreference } from \"../api/user-preferences\"\n\nconst PREFERRED_MODEL_KEY = \"preferred_model\"\nconst MODEL_CONFIG_QUERY_KEY = [\"model-config\"] as const\nconst PREFERRED_MODEL_QUERY_KEY = [\"user-preference\", PREFERRED_MODEL_KEY] as const\n\nexport function useModelConfig(): {\n models: ModelOption[]\n defaultModel: string\n isLoading: boolean\n} {\n const { data, isLoading } = useQuery({\n queryKey: MODEL_CONFIG_QUERY_KEY,\n queryFn: () => getModelsConfig(),\n staleTime: 5 * 60 * 1000,\n // 全局 QueryClient 默认关闭 refetchOnWindowFocus,这里显式开启,\n // 让模型列表在 staleTime 过期后能随窗口聚焦自动刷新\n refetchOnWindowFocus: true,\n })\n\n return {\n models: data?.models ?? [],\n defaultModel: data?.default ?? \"\",\n isLoading,\n }\n}\n\nexport function usePreferredModel(): {\n preferredModel: string | null\n setPreferredModel: (modelId: string) => void\n} {\n const queryClient = useQueryClient()\n\n const { data } = useQuery({\n queryKey: PREFERRED_MODEL_QUERY_KEY,\n queryFn: () => getUserPreference(PREFERRED_MODEL_KEY),\n staleTime: Number.POSITIVE_INFINITY,\n })\n\n const mutation = useMutation({\n mutationFn: (modelId: string) => setUserPreference(PREFERRED_MODEL_KEY, modelId),\n onMutate: async (modelId) => {\n await queryClient.cancelQueries({ queryKey: PREFERRED_MODEL_QUERY_KEY })\n const previous = queryClient.getQueryData<string | null>(PREFERRED_MODEL_QUERY_KEY)\n queryClient.setQueryData(PREFERRED_MODEL_QUERY_KEY, modelId)\n return { previous }\n },\n onError: (_error, _modelId, context) => {\n queryClient.setQueryData(PREFERRED_MODEL_QUERY_KEY, context?.previous ?? null)\n },\n onSettled: () => {\n void queryClient.invalidateQueries({ queryKey: PREFERRED_MODEL_QUERY_KEY })\n },\n })\n\n return {\n preferredModel: data ?? null,\n setPreferredModel: (modelId: string) => mutation.mutate(modelId),\n }\n}\n","import type { ModelsResource } from \"../../client/resources/models\"\nimport { getClient } from \"./client\"\nexport * from \"../../client/resources/models\"\nconst r = (): ModelsResource => getClient().models\nexport const getModelsConfig = (...args: Parameters<ModelsResource[\"getModelsConfig\"]>) => r().getModelsConfig(...args)\n","import type { UserPreferencesResource } from \"../../client/resources/user-preferences\"\nimport { getClient } from \"./client\"\nconst r = (): UserPreferencesResource => getClient().userPreferences\nexport const getUserPreference = (...args: Parameters<UserPreferencesResource[\"getUserPreference\"]>) => r().getUserPreference(...args)\nexport const setUserPreference = (...args: Parameters<UserPreferencesResource[\"setUserPreference\"]>) => r().setUserPreference(...args)\n","import { useCallback, useEffect, useMemo, useState } from \"react\"\n\nconst MAX_HISTORY_ENTRIES = 50\n\nfunction getStorageKey(sessionId: string | null) {\n return sessionId ? `input-history:${sessionId}` : null\n}\n\nfunction readEntries(storageKey: string | null) {\n if (typeof window === \"undefined\" || !storageKey) {\n return []\n }\n\n try {\n const raw = window.sessionStorage.getItem(storageKey)\n if (!raw) {\n return []\n }\n\n const parsed = JSON.parse(raw)\n if (!Array.isArray(parsed)) {\n return []\n }\n\n return parsed.filter((item): item is string => typeof item === \"string\").slice(0, MAX_HISTORY_ENTRIES)\n } catch {\n return []\n }\n}\n\nexport function useInputHistory(sessionId: string | null) {\n const storageKey = useMemo(() => getStorageKey(sessionId), [sessionId])\n const [entries, setEntries] = useState<string[]>([])\n const [cursor, setCursor] = useState<number | null>(null)\n const [draft, setDraft] = useState(\"\")\n\n useEffect(() => {\n setEntries(readEntries(storageKey))\n setCursor(null)\n setDraft(\"\")\n }, [storageKey])\n\n const persistEntries = useCallback(\n (nextEntries: string[]) => {\n if (typeof window === \"undefined\" || !storageKey) {\n return\n }\n\n try {\n window.sessionStorage.setItem(storageKey, JSON.stringify(nextEntries))\n } catch {\n // 忽略 sessionStorage 写入失败,避免打断输入流程\n }\n },\n [storageKey],\n )\n\n const addEntry = useCallback(\n (value: string) => {\n if (!value.trim()) {\n return\n }\n\n setEntries((prev) => {\n const nextEntries = [value, ...prev].slice(0, MAX_HISTORY_ENTRIES)\n persistEntries(nextEntries)\n return nextEntries\n })\n setCursor(null)\n setDraft(\"\")\n },\n [persistEntries],\n )\n\n const navigateUp = useCallback(\n (currentDraft = \"\") => {\n if (entries.length === 0) {\n return null\n }\n\n if (cursor == null) {\n setDraft(currentDraft)\n }\n\n const nextCursor = cursor == null ? 0 : Math.min(cursor + 1, entries.length - 1)\n setCursor(nextCursor)\n return entries[nextCursor] ?? null\n },\n [cursor, entries],\n )\n\n const navigateDown = useCallback(() => {\n if (cursor == null) {\n return null\n }\n\n if (cursor <= 0) {\n setCursor(null)\n return draft\n }\n\n const nextCursor = cursor - 1\n setCursor(nextCursor)\n return entries[nextCursor] ?? draft\n }, [cursor, draft, entries])\n\n const currentEntry = cursor == null ? draft : (entries[cursor] ?? draft)\n\n return {\n addEntry,\n navigateUp,\n navigateDown,\n currentEntry,\n isNavigating: cursor != null,\n }\n}\n","export const ATTACHMENT_SIZE_LIMIT_BYTES = 1000 * 1024 * 1024\n\nexport type OversizedFileInfo = {\n name: string\n size: number\n}\n\nexport function formatFileSize(size: number) {\n if (size < 1024) {\n return `${size} B`\n }\n if (size < 1024 * 1024) {\n return `${(size / 1024).toFixed(size >= 100 * 1024 ? 0 : 1)} KB`\n }\n return `${(size / (1024 * 1024)).toFixed(size >= 10 * 1024 * 1024 ? 0 : 1)} MB`\n}\n\nexport function splitFilesBySize(\n files: FileList | File[],\n limitBytes: number = ATTACHMENT_SIZE_LIMIT_BYTES,\n) {\n const accepted: File[] = []\n const rejected: OversizedFileInfo[] = []\n\n for (const file of Array.from(files)) {\n if (file.size <= limitBytes) {\n accepted.push(file)\n continue\n }\n rejected.push({\n name: file.webkitRelativePath || file.name || \"未命名文件\",\n size: file.size,\n })\n }\n\n return { accepted, rejected }\n}\n","export interface SkillSummary {\n skill_id: string\n display_name: string\n dir_name: string\n description: string\n path: string\n references: string[]\n local: boolean\n}\n\nexport interface SkillSearchResult {\n skill_id: string\n display_name: string\n dir_name: string\n description: string\n local: boolean\n}\n\ntype SkillDisplayTarget = {\n skill_id?: string | null\n display_name?: string | null\n skillId?: string | null\n displayName?: string | null\n}\n\nexport function skillDisplayName(skill: SkillDisplayTarget): string {\n const displayName = (skill.display_name ?? skill.displayName ?? \"\").trim()\n if (displayName) {\n return displayName\n }\n return (skill.skill_id ?? skill.skillId ?? \"\").trim()\n}\n\nexport interface SkillStats {\n loaded_skill_count: number\n loaded_skill_names: string[]\n remote_configured: boolean\n remote_connected: boolean\n installed_skill_count: number\n}\n\nexport interface StepSpec {\n n: number\n label: string\n}\n\nexport interface StageSpec {\n id: string\n name: string\n steps: StepSpec[]\n}\n\nexport interface ParallelMode {\n id: string\n name: string\n prompt_hint: string\n}\n\nexport interface SkillDetail extends SkillSummary {\n content: string\n stages?: StageSpec[]\n parallel_modes?: ParallelMode[]\n}\n","import type { SuggestionProps } from \"@tiptap/suggestion\"\nimport { ChevronRight, File, Folder } from \"lucide-react\"\nimport { forwardRef, useCallback, useImperativeHandle, useMemo, useState } from \"react\"\nimport * as sessionsApi from \"../../api/sessions\"\nimport { useSessionStore } from \"../../stores/session-store\"\nimport type { FileSuggestionItem } from \"./extensions/file-mention\"\n\nconst ROOT_DIR = \".\"\n\ntype FileEntry = sessionsApi.FileEntry\n\nexport interface FileCompletionMenuProps\n extends Omit<SuggestionProps<FileSuggestionItem, FileSuggestionItem>, \"command\"> {\n command: (props: FileSuggestionItem) => void\n onExit?: () => void\n sessionId?: string | null\n}\n\nexport interface FileCompletionMenuRef {\n onKeyDown: (event: KeyboardEvent) => boolean\n}\n\ninterface ParsedQuery {\n dirPath: string\n filterQuery: string\n}\n\nfunction isVisibleEntry(entry: FileEntry) {\n return !entry.name.startsWith(\".\")\n}\n\nfunction fuzzyMatch(value: string, query: string) {\n if (!query) return true\n\n const target = value.toLowerCase()\n const source = query.toLowerCase()\n\n if (target.includes(source)) return true\n\n let cursor = 0\n for (const char of source) {\n cursor = target.indexOf(char, cursor)\n if (cursor === -1) return false\n cursor += 1\n }\n\n return true\n}\n\nfunction getEntryScore(entry: FileEntry, query: string) {\n if (!query) return 0\n\n const q = query.toLowerCase()\n const name = entry.name.toLowerCase()\n const path = entry.path.toLowerCase()\n\n if (name === q) return 5\n if (name.startsWith(q)) return 4\n if (path.startsWith(q)) return 3\n if (name.includes(q)) return 2\n if (path.includes(q)) return 1\n return 0\n}\n\nfunction filterEntries(entries: FileEntry[], query: string) {\n return entries\n .filter((entry) => isVisibleEntry(entry) && fuzzyMatch(`${entry.name} ${entry.path}`, query))\n .sort((a, b) => {\n if (a.is_dir !== b.is_dir) {\n return a.is_dir ? -1 : 1\n }\n\n const scoreDiff = getEntryScore(b, query) - getEntryScore(a, query)\n if (scoreDiff !== 0) {\n return scoreDiff\n }\n\n return a.name.localeCompare(b.name)\n })\n}\n\nfunction hasHiddenSegment(segments: string[]) {\n return segments.some((s) => s.startsWith(\".\"))\n}\n\nfunction parseSuggestionQuery(query: string): ParsedQuery {\n const normalized = query.replace(/^\\/+/, \"\")\n\n if (!normalized) {\n return { dirPath: ROOT_DIR, filterQuery: \"\" }\n }\n\n if (normalized.endsWith(\"/\")) {\n const dirPath = normalized.slice(0, -1)\n const segments = dirPath.split(\"/\").filter(Boolean)\n if (hasHiddenSegment(segments)) {\n return { dirPath: ROOT_DIR, filterQuery: \"\" }\n }\n return { dirPath: dirPath || ROOT_DIR, filterQuery: \"\" }\n }\n\n const segments = normalized.split(\"/\").filter(Boolean)\n if (segments.length <= 1) {\n return { dirPath: ROOT_DIR, filterQuery: normalized }\n }\n\n const dirSegments = segments.slice(0, -1)\n if (hasHiddenSegment(dirSegments)) {\n return { dirPath: ROOT_DIR, filterQuery: \"\" }\n }\n\n return {\n dirPath: dirSegments.join(\"/\"),\n filterQuery: segments.at(-1) ?? \"\",\n }\n}\n\nasync function listDirectory(sessionId: string, dirPath: string) {\n const entries = await sessionsApi.listDir(sessionId, dirPath)\n return entries.filter(isVisibleEntry)\n}\n\nexport async function getFileSuggestionItems(sessionId: string | null, query: string) {\n if (!sessionId) return []\n\n const { dirPath, filterQuery } = parseSuggestionQuery(query)\n const entries = await listDirectory(sessionId, dirPath)\n return filterEntries(entries, filterQuery)\n}\n\nexport const FileCompletionMenu = forwardRef<FileCompletionMenuRef, FileCompletionMenuProps>(\n function FileCompletionMenu(\n { command, editor, items, onExit, query, range, sessionId: sessionIdProp },\n ref,\n ) {\n const activeSessionId = useSessionStore((state) => state.activeSessionId)\n const sessionId = sessionIdProp ?? activeSessionId\n const { dirPath, filterQuery } = useMemo(() => parseSuggestionQuery(query), [query])\n return (\n <FileCompletionMenuContent\n key={`${sessionId ?? \"none\"}:${dirPath}:${filterQuery}`}\n ref={ref}\n command={command}\n editor={editor}\n filterQuery={filterQuery}\n items={items as FileEntry[]}\n onExit={onExit}\n range={range}\n sessionId={sessionId}\n />\n )\n },\n)\n\nconst FileCompletionMenuContent = forwardRef<\n FileCompletionMenuRef,\n {\n command: FileCompletionMenuProps[\"command\"]\n editor: FileCompletionMenuProps[\"editor\"]\n filterQuery: string\n items: FileEntry[]\n onExit?: () => void\n range: FileCompletionMenuProps[\"range\"]\n sessionId?: string | null\n }\n>(function FileCompletionMenuContent(\n { command, editor, filterQuery, items, onExit, range, sessionId },\n ref,\n) {\n const [rawSelectedIndex, setRawSelectedIndex] = useState(0)\n const filteredEntries = useMemo(() => filterEntries(items, filterQuery), [filterQuery, items])\n const selectedIndex =\n filteredEntries.length === 0 ? 0 : Math.min(rawSelectedIndex, filteredEntries.length - 1)\n\n const handleSelect = useCallback(\n (entry: FileEntry) => {\n if (entry.is_dir) {\n const nextValue = entry.path === ROOT_DIR ? \"@\" : `@${entry.path}/`\n editor.chain().focus().insertContentAt(range, nextValue).run()\n return\n }\n\n command({\n is_dir: false,\n name: entry.name,\n path: entry.path,\n })\n },\n [command, editor, range],\n )\n\n useImperativeHandle(\n ref,\n () => ({\n onKeyDown: (event: KeyboardEvent) => {\n if (event.key === \"ArrowDown\") {\n event.preventDefault()\n if (filteredEntries.length > 0) {\n setRawSelectedIndex((current) => (current + 1) % filteredEntries.length)\n }\n return true\n }\n\n if (event.key === \"ArrowUp\") {\n event.preventDefault()\n if (filteredEntries.length > 0) {\n setRawSelectedIndex(\n (current) => (current - 1 + filteredEntries.length) % filteredEntries.length,\n )\n }\n return true\n }\n\n if (event.key === \"Enter\") {\n event.preventDefault()\n const entry = filteredEntries[selectedIndex]\n if (entry) {\n handleSelect(entry)\n }\n return true\n }\n\n if (event.key === \"Escape\") {\n event.preventDefault()\n onExit?.()\n return true\n }\n\n return false\n },\n }),\n [filteredEntries, handleSelect, onExit, selectedIndex],\n )\n\n return (\n <div className=\"max-h-64 overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 shadow-lg\">\n {!sessionId ? (\n <div className=\"px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">暂无会话</div>\n ) : filteredEntries.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">没有文件</div>\n ) : (\n filteredEntries.map((entry, index) => (\n <button\n key={entry.path}\n ref={(element) => {\n if (element && index === selectedIndex) {\n element.scrollIntoView({ block: \"nearest\" })\n }\n }}\n type=\"button\"\n onMouseDown={(event) => {\n event.preventDefault()\n handleSelect(entry)\n }}\n className={`flex w-full items-center gap-2 px-3 py-1.5 text-left text-sm transition-colors ${\n index === selectedIndex\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--accent-foreground))]\"\n : \"text-[hsl(var(--popover-foreground))] hover:bg-[hsl(var(--accent))]\"\n }`}\n >\n {entry.is_dir ? (\n <Folder size={14} className=\"shrink-0 text-[hsl(var(--primary))]\" />\n ) : (\n <File size={14} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" />\n )}\n <span className=\"truncate\">{entry.name}</span>\n {entry.is_dir && <ChevronRight size={12} className=\"ml-auto shrink-0 opacity-40\" />}\n </button>\n ))\n )}\n </div>\n )\n})\n","import { skillDisplayName } from \"../../schemas/skill\"\nimport { forwardRef, useCallback, useImperativeHandle, useState } from \"react\"\nimport type { SkillSuggestionItem } from \"./extensions/skill-mention\"\n\nexport interface SkillCompletionMenuProps {\n items: SkillSuggestionItem[]\n command: (item: SkillSuggestionItem) => void\n}\n\nexport interface SkillCompletionMenuRef {\n onKeyDown: (event: KeyboardEvent) => boolean\n}\n\nexport const SkillCompletionMenu = forwardRef<SkillCompletionMenuRef, SkillCompletionMenuProps>(\n function SkillCompletionMenu({ command, items }, ref) {\n const [rawSelectedIndex, setRawSelectedIndex] = useState(0)\n const selectedIndex = items.length === 0 ? 0 : Math.min(rawSelectedIndex, items.length - 1)\n\n const handleSelect = useCallback(\n (item: SkillSuggestionItem) => {\n command(item)\n },\n [command],\n )\n\n useImperativeHandle(\n ref,\n () => ({\n onKeyDown: (event: KeyboardEvent) => {\n if (event.key === \"ArrowDown\") {\n event.preventDefault()\n if (items.length > 0) {\n setRawSelectedIndex((current) => (current + 1) % items.length)\n }\n return true\n }\n\n if (event.key === \"ArrowUp\") {\n event.preventDefault()\n if (items.length > 0) {\n setRawSelectedIndex((current) => (current - 1 + items.length) % items.length)\n }\n return true\n }\n\n if (event.key === \"Enter\") {\n event.preventDefault()\n const item = items[selectedIndex]\n if (item) {\n handleSelect(item)\n }\n return true\n }\n\n if (event.key === \"Escape\") {\n return false\n }\n\n return false\n },\n }),\n [handleSelect, items, selectedIndex],\n )\n\n const commandItems = items.filter((item) => item.type === \"command\")\n const skillItems = items.filter((item) => item.type === \"skill\")\n\n return (\n <div className=\"max-h-64 overflow-y-auto rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--popover))] py-1 shadow-lg\">\n {items.length === 0 ? (\n <div className=\"px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">\n 没有匹配的命令或技能\n </div>\n ) : (\n <div>\n {commandItems.length > 0 ? (\n <div className=\"px-2 pb-1 pt-1\">\n <div className=\"px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]\">\n 命令\n </div>\n {commandItems.map((item, index) => (\n <button\n key={item.id}\n ref={(element) => {\n if (element && index === selectedIndex) {\n element.scrollIntoView({ block: \"nearest\" })\n }\n }}\n type=\"button\"\n onMouseDown={(event) => {\n event.preventDefault()\n handleSelect(item)\n }}\n className={`flex w-full items-start gap-2 rounded-lg px-2 py-1.5 text-left transition-colors ${\n index === selectedIndex\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--accent-foreground))]\"\n : \"text-[hsl(var(--popover-foreground))] hover:bg-[hsl(var(--accent))]\"\n }`}\n >\n <span className=\"pt-0.5 text-sm\">↻</span>\n <span className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span className=\"text-sm font-medium\">{item.label}</span>\n <span className=\"text-xs text-[hsl(var(--muted-foreground))]\">\n {item.description}\n </span>\n </span>\n </button>\n ))}\n </div>\n ) : null}\n {skillItems.length > 0 ? (\n <div className=\"px-2 pb-1 pt-1\">\n <div className=\"px-1 pb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-[hsl(var(--muted-foreground))]\">\n 技能\n </div>\n {skillItems.map((item, skillIndex) => {\n const index = commandItems.length + skillIndex\n return (\n <button\n key={item.skillId}\n ref={(element) => {\n if (element && index === selectedIndex) {\n element.scrollIntoView({ block: \"nearest\" })\n }\n }}\n type=\"button\"\n onMouseDown={(event) => {\n event.preventDefault()\n handleSelect(item)\n }}\n className={`flex w-full flex-col gap-0.5 rounded-lg px-2 py-1.5 text-left transition-colors ${\n index === selectedIndex\n ? \"bg-[hsl(var(--accent))] text-[hsl(var(--accent-foreground))]\"\n : \"text-[hsl(var(--popover-foreground))] hover:bg-[hsl(var(--accent))]\"\n }`}\n >\n <span className=\"text-sm font-medium\">{skillDisplayName(item)}</span>\n <span className=\"text-xs text-[hsl(var(--muted-foreground))]\">\n {item.description}\n </span>\n </button>\n )\n })}\n </div>\n ) : null}\n </div>\n )}\n </div>\n )\n },\n)\n","import { X } from \"lucide-react\"\nimport { useEffect } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { ATTACHMENT_SIZE_LIMIT_BYTES, formatFileSize, type OversizedFileInfo } from \"../../lib/attachment-upload\"\n\ninterface Props {\n open: boolean\n onOpenChange: (open: boolean) => void\n files: OversizedFileInfo[]\n limitBytes?: number\n}\n\nexport function FileSizeLimitDialog({\n open,\n onOpenChange,\n files,\n limitBytes = ATTACHMENT_SIZE_LIMIT_BYTES,\n}: Props) {\n useEffect(() => {\n if (!open) return\n const handleKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onOpenChange(false)\n }\n }\n window.addEventListener(\"keydown\", handleKey)\n return () => window.removeEventListener(\"keydown\", handleKey)\n }, [open, onOpenChange])\n\n if (!open || files.length === 0) {\n return null\n }\n\n const limitText = formatFileSize(limitBytes)\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4\"\n onClick={() => onOpenChange(false)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n onOpenChange(false)\n }\n }}\n // biome-ignore lint/a11y/useSemanticElements: 原生 <dialog> 需要 showModal() + 内置 backdrop,本组件用外层 div 充当点击关闭的 backdrop,不走 modal API。\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"file-size-limit-dialog-title\"\n >\n <div\n className=\"w-full max-w-lg overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3\">\n <div>\n <h3 id=\"file-size-limit-dialog-title\" className=\"text-sm font-semibold text-[hsl(var(--foreground))]\">\n 附件超过大小限制\n </h3>\n <p className=\"mt-1 text-xs text-[hsl(var(--muted-foreground))]\">\n 单个附件最大支持 {limitText}。以下文件未加入附件列表。\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n title=\"关闭\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n >\n <X size={14} />\n </button>\n </div>\n <div className=\"max-h-[min(50vh,24rem)] overflow-auto px-4 py-3\">\n <div className=\"flex flex-col gap-2\">\n {files.map((file) => (\n <div\n key={`${file.name}:${file.size}`}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--accent))] px-3 py-2\"\n >\n <span className=\"min-w-0 truncate text-sm text-[hsl(var(--foreground))]\">\n {file.name}\n </span>\n <span className=\"shrink-0 text-xs text-[hsl(var(--muted-foreground))]\">\n {formatFileSize(file.size)}\n </span>\n </div>\n ))}\n </div>\n </div>\n <div className=\"flex justify-end border-t border-[hsl(var(--border))] px-4 py-3\">\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className=\"rounded-md bg-[hsl(var(--primary))] px-4 py-1.5 text-xs font-semibold text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90\"\n >\n 知道了\n </button>\n </div>\n </div>\n </div>,\n document.body,\n )\n}\n","import { useQuery } from \"@tanstack/react-query\"\nimport { RefreshCw } from \"lucide-react\"\nimport { type ReactNode, useMemo } from \"react\"\nimport { listSessionSkills } from \"../../api/skills\"\nimport { useBackgroundTasks } from \"../../hooks/use-background-tasks\"\nimport { useContextStats } from \"../../hooks/use-context-stats\"\nimport { useSkillStats } from \"../../hooks/use-skill-stats\"\nimport { useTokenPressure } from \"../../hooks/use-token-pressure\"\nimport { cn } from \"../../lib/utils\"\nimport { skillDisplayName } from \"../../schemas/skill\"\nimport { useConnectionStore } from \"../../stores/connection-store\"\nimport { ProgressCircle } from \"./ProgressCircle\"\n\nconst COMPACT_NUMBER_FORMATTER = new Intl.NumberFormat(\"zh-CN\", {\n notation: \"compact\",\n maximumFractionDigits: 1,\n})\n\nconst TOKEN_NUMBER_FORMATTER = new Intl.NumberFormat(\"zh-CN\")\n\nfunction formatCompactNumber(value: number) {\n return COMPACT_NUMBER_FORMATTER.format(value)\n}\n\nfunction formatTokensK(value: number) {\n const k = value / 1000\n return k < 10 ? `${k.toFixed(1)}k` : `${Math.round(k)}k`\n}\n\nfunction formatTokenNumber(value: number | null) {\n if (value == null) {\n return \"暂无明细\"\n }\n\n return TOKEN_NUMBER_FORMATTER.format(value)\n}\n\nfunction getConnectionMeta(\n status: \"connecting\" | \"connected\" | \"disconnected\",\n reconnectAttempt: number,\n hasEverConnected: boolean,\n) {\n if (status === \"connected\") {\n return {\n dotClass: \"bg-emerald-400\",\n label: \"连接正常\",\n toneClass:\n \"border-emerald-500/20 bg-emerald-500/8 text-emerald-100\",\n }\n }\n\n if (status === \"connecting\") {\n return {\n dotClass: \"bg-amber-400 animate-pulse\",\n label:\n reconnectAttempt > 0 ? `重连中 ${reconnectAttempt}` : \"连接中\",\n toneClass:\n \"border-amber-500/20 bg-amber-500/8 text-amber-100\",\n }\n }\n\n return {\n dotClass: \"bg-rose-400\",\n label: hasEverConnected ? \"连接断开\" : \"尚未连接\",\n toneClass: \"border-rose-500/20 bg-rose-500/8 text-rose-100\",\n }\n}\n\nfunction HoverPanel({\n title,\n children,\n}: {\n title: string\n children: ReactNode\n}) {\n return (\n <div className=\"pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block\">\n <div className=\"mb-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-slate-400\">\n {title}\n </div>\n {children}\n </div>\n )\n}\n\nexport function SkillStatusBar({\n sessionId,\n onResync,\n isResyncing = false,\n vertical = false,\n}: {\n sessionId: string\n onResync?: () => void\n isResyncing?: boolean\n vertical?: boolean\n}) {\n const { data: skillStats, error, loading } = useSkillStats(sessionId)\n const { data: sessionSkills = [] } = useQuery({\n queryKey: [\"session-skills\", sessionId],\n queryFn: ({ signal }) => listSessionSkills(sessionId, { signal }),\n enabled: Boolean(sessionId),\n })\n const { data: contextStats } = useContextStats(sessionId)\n const { data: tasks } = useBackgroundTasks(sessionId)\n const tokenPressure = useTokenPressure(sessionId)\n const connectionStatus = useConnectionStore((state) => state.status)\n const reconnectAttempt = useConnectionStore((state) => state.reconnectAttempt)\n const hasEverConnected = useConnectionStore((state) => state.hasEverConnected)\n const runningTaskItems = tasks.filter((task) => task.status === \"running\")\n const runningTasks = runningTaskItems.length\n const statsReady = !loading && !error\n const skillStoreConnected = statsReady && skillStats.remote_connected\n const connectionMeta = useMemo(\n () =>\n getConnectionMeta(\n connectionStatus,\n reconnectAttempt,\n hasEverConnected,\n ),\n [connectionStatus, reconnectAttempt, hasEverConnected],\n )\n\n const items = [\n {\n key: \"bg\",\n dotClass: runningTasks > 0 ? \"bg-amber-400\" : \"bg-[hsl(var(--muted-foreground))]\",\n text: `后台任务 ${runningTasks}`,\n },\n {\n key: \"loaded\",\n dotClass: statsReady ? \"bg-emerald-500\" : \"bg-[hsl(var(--muted-foreground))]\",\n text: statsReady ? `已加载 ${skillStats.loaded_skill_count} 个技能` : \"技能状态不可用\",\n },\n {\n key: \"total\",\n dotClass: skillStoreConnected ? \"bg-emerald-500\" : \"bg-[hsl(var(--muted-foreground))]\",\n text: skillStoreConnected\n ? `已安装 ${skillStats.installed_skill_count} 个技能`\n : \"尚未登录技能商店\",\n },\n ].filter((item) => item.key !== \"total\" || skillStats.remote_configured)\n\n const tokenSummary = useMemo(() => {\n return {\n detail: (\n <div className=\"space-y-1\">\n <div className=\"flex items-center justify-between gap-3 border-t border-slate-800 pt-1\">\n <span className=\"text-slate-400\">已用</span>\n <span className=\"font-mono\">{formatTokenNumber(contextStats.tokens_used)}</span>\n </div>\n {contextStats.context_window > 0 ? (\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-slate-400\">上下文窗口</span>\n <span className=\"font-mono\">{formatCompactNumber(contextStats.context_window)}</span>\n </div>\n ) : (\n <div className=\"pt-1 text-slate-500\">\n 未配置上下文窗口大小,可通过 CONTEXT_WINDOW 环境变量设置\n </div>\n )}\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-slate-400\">整理阈值</span>\n <span className=\"font-mono\">\n {contextStats.compaction_ratio > 0\n ? `${Math.round(contextStats.compaction_ratio * 100)}%`\n : \"已禁用\"}\n </span>\n </div>\n </div>\n ),\n label:\n contextStats.context_window > 0\n ? `${formatTokensK(contextStats.tokens_used)} / ${formatTokensK(contextStats.context_window)} 上下文`\n : `${formatTokensK(contextStats.tokens_used)} 上下文`,\n warn: tokenPressure.level === \"critical\",\n }\n }, [contextStats.compaction_ratio, contextStats.context_window, contextStats.tokens_used, tokenPressure.level])\n\n const containerClass = vertical\n ? \"text-[11px] text-[hsl(var(--muted-foreground))]\"\n : \"bg-[hsl(var(--background))] px-5 pt-2\"\n const innerClass = vertical ? \"\" : \"mx-auto max-w-3xl\"\n const listClass = vertical\n ? \"flex flex-col items-stretch gap-1.5 text-[11px] text-[hsl(var(--muted-foreground))]\"\n : \"flex flex-wrap items-center gap-2 text-[10px] text-[hsl(var(--muted-foreground))]\"\n\n return (\n <div className={containerClass}>\n <div className={innerClass}>\n <div className={listClass}>\n {tokenSummary ? (\n <div className=\"flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1\">\n <ProgressCircle\n percentage={tokenPressure.ratio * 100}\n level={tokenPressure.level}\n detail={tokenSummary.detail}\n />\n <span className=\"font-mono\">{tokenSummary.label}</span>\n {tokenSummary.warn ? (\n <span className=\"rounded-full border border-rose-500/25 bg-rose-500/10 px-1.5 py-0.5 text-[10px] font-medium text-rose-200\">\n 建议整理对话\n </span>\n ) : null}\n </div>\n ) : null}\n {connectionStatus !== \"connected\" ? (\n <div\n className={cn(\n \"flex items-center gap-2 rounded-full border px-2.5 py-1 font-mono\",\n connectionMeta.toneClass,\n )}\n >\n <span className={cn(\"inline-block h-1.5 w-1.5 rounded-full\", connectionMeta.dotClass)} />\n <span>{connectionMeta.label}</span>\n </div>\n ) : null}\n {items.map((item, index) => (\n <div\n key={item.key}\n className=\"flex items-center gap-2 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1\"\n >\n {index > 0 && !tokenPressure && (\n <span className=\"hidden text-[hsl(var(--border))]\">·</span>\n )}\n <span className={`inline-block h-1.5 w-1.5 rounded-full ${item.dotClass}`} />\n {item.key === \"bg\" ? (\n <div className=\"group relative\">\n <span className=\"cursor-help font-mono\">{item.text}</span>\n {runningTaskItems.length > 0 ? (\n <HoverPanel title=\"运行中任务\">\n <div className=\"max-h-40 overflow-y-auto\">\n {runningTaskItems.map((task) => (\n <div key={task.id} className=\"flex items-start gap-2 py-1 leading-relaxed\">\n <span className=\"mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-amber-300 bg-transparent\" />\n <div className=\"min-w-0\">\n <div className=\"font-medium\">{task.id}</div>\n <div className=\"break-words text-slate-300/85\">\n {task.description || task.command}\n </div>\n </div>\n </div>\n ))}\n </div>\n </HoverPanel>\n ) : null}\n </div>\n ) : item.key === \"loaded\" ? (\n <div className=\"group relative flex items-center gap-1.5\">\n <span className=\"cursor-help font-mono\">{item.text}</span>\n {onResync ? (\n <button\n type=\"button\"\n onClick={onResync}\n disabled={isResyncing}\n aria-label=\"同步技能\"\n className=\"inline-flex h-5 w-5 items-center justify-center rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--background))] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring))] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <RefreshCw size={11} className={isResyncing ? \"animate-spin\" : \"\"} />\n </button>\n ) : null}\n {statsReady && sessionSkills.length > 0 ? (\n <HoverPanel title=\"已加载技能\">\n <div className=\"max-h-40 overflow-y-auto\">\n {sessionSkills.map((skill) => (\n <div\n key={skill.skill_id}\n className=\"flex items-start gap-2 py-1 leading-relaxed\"\n >\n <span className=\"mt-1.5 inline-block h-2 w-2 shrink-0 rounded-full border border-emerald-300 bg-transparent\" />\n <span className=\"break-words\">{skillDisplayName(skill)}</span>\n </div>\n ))}\n </div>\n </HoverPanel>\n ) : null}\n </div>\n ) : (\n <span className=\"font-mono\">{item.text}</span>\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n )\n}\n","import { useQuery } from \"@tanstack/react-query\"\nimport { listBackgroundTasks } from \"../api/sessions\"\nimport type { BackgroundTask } from \"../schemas/background\"\nimport { useBackgroundStore } from \"../stores/background-store\"\n\nconst EMPTY_TASKS: BackgroundTask[] = []\n\nexport function useBackgroundTasks(sessionId: string | null | undefined) {\n const setTasks = useBackgroundStore((state) => state.setTasks)\n const tasks = useBackgroundStore((state) => (sessionId ? state.tasks[sessionId] : undefined))\n\n const query = useQuery({\n queryKey: [\"background-tasks\", sessionId],\n queryFn: ({ signal }) =>\n listBackgroundTasks(sessionId!, { signal }).then((items) => {\n setTasks(sessionId!, items)\n return items\n }),\n enabled: Boolean(sessionId),\n })\n\n return {\n data: tasks ?? query.data ?? EMPTY_TASKS,\n loading: query.isLoading,\n error: query.error,\n refetch: query.refetch,\n }\n}\n","import { useQuery } from \"@tanstack/react-query\"\nimport { getSessionContextStats, type SessionContextStats } from \"../api/sessions\"\n\nconst EMPTY_CONTEXT_STATS: SessionContextStats = {\n tokens_used: 0,\n context_window: 0,\n compaction_ratio: 0,\n}\n\nexport function useContextStats(sessionId: string | null | undefined) {\n const query = useQuery({\n queryKey: [\"context-stats\", sessionId],\n queryFn: ({ signal }) => getSessionContextStats(sessionId!, { signal }),\n enabled: Boolean(sessionId),\n refetchInterval: 60_000,\n })\n\n return {\n data: query.data ?? EMPTY_CONTEXT_STATS,\n loading: query.isLoading,\n error: query.error,\n refetch: query.refetch,\n }\n}\n","import { useQuery } from \"@tanstack/react-query\"\nimport { getSkillStats } from \"../api/skills\"\nimport type { SkillStats } from \"../schemas/skill\"\n\nconst EMPTY_SKILL_STATS: SkillStats = {\n loaded_skill_count: 0,\n loaded_skill_names: [],\n remote_configured: false,\n remote_connected: false,\n installed_skill_count: 0,\n}\n\nexport function useSkillStats(sessionId: string | null | undefined) {\n const query = useQuery({\n queryKey: [\"skill-stats\", sessionId],\n queryFn: ({ signal }) => getSkillStats(sessionId!, { signal }),\n enabled: Boolean(sessionId),\n refetchInterval: 300_000,\n })\n\n return {\n data: query.data ?? EMPTY_SKILL_STATS,\n loading: query.isLoading,\n error: query.error,\n refetch: query.refetch,\n }\n}\n","import { useMemo } from \"react\"\nimport { useContextStats } from \"./use-context-stats\"\n\nexport type TokenPressureLevel = \"normal\" | \"warn\" | \"critical\"\n\nexport interface TokenPressure {\n ratio: number\n level: TokenPressureLevel\n}\n\nfunction clampRatio(value: number) {\n return Math.min(1, Math.max(0, value))\n}\n\nfunction resolveLevel(ratio: number, compactionRatio: number): TokenPressureLevel {\n if (compactionRatio <= 0) {\n return \"normal\"\n }\n if (ratio >= compactionRatio) {\n return \"critical\"\n }\n if (ratio >= Math.max(0, compactionRatio - 0.1)) {\n return \"warn\"\n }\n return \"normal\"\n}\n\nexport function useTokenPressure(sessionId: string | null | undefined): TokenPressure {\n const { data } = useContextStats(sessionId)\n\n return useMemo(() => {\n const ratio =\n data.context_window > 0 ? clampRatio(data.tokens_used / data.context_window) : 0\n return {\n ratio,\n level: resolveLevel(ratio, data.compaction_ratio),\n }\n }, [data.compaction_ratio, data.context_window, data.tokens_used])\n}\n","import { type ClassValue, clsx } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\nexport async function copyToClipboard(text: string): Promise<boolean> {\n if (navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(text)\n return true\n } catch {\n // fall through to textarea fallback\n }\n }\n // Fallback for insecure contexts (HTTP non-localhost)\n const textarea = document.createElement(\"textarea\")\n textarea.value = text\n textarea.style.position = \"fixed\"\n textarea.style.opacity = \"0\"\n document.body.appendChild(textarea)\n textarea.select()\n try {\n return document.execCommand(\"copy\")\n } finally {\n document.body.removeChild(textarea)\n }\n}\n","import type { ReactNode } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport type { TokenPressureLevel } from \"../../hooks/use-token-pressure\"\n\ninterface ProgressCircleProps {\n percentage: number\n level: TokenPressureLevel\n size?: number\n strokeWidth?: number\n detail?: ReactNode\n className?: string\n}\n\nconst LEVEL_STYLES: Record<\n TokenPressureLevel,\n {\n strokeClass: string\n textClass: string\n trackClass: string\n }\n> = {\n normal: {\n strokeClass: \"stroke-slate-400\",\n textClass: \"text-slate-300\",\n trackClass: \"stroke-slate-500/20\",\n },\n warn: {\n strokeClass: \"stroke-amber-400\",\n textClass: \"text-amber-300\",\n trackClass: \"stroke-amber-500/20\",\n },\n critical: {\n strokeClass: \"stroke-rose-400\",\n textClass: \"text-rose-300\",\n trackClass: \"stroke-rose-500/20\",\n },\n}\n\nexport function ProgressCircle({\n percentage,\n level,\n size = 16,\n strokeWidth = 2,\n detail,\n className,\n}: ProgressCircleProps) {\n const clamped = Math.min(100, Math.max(0, percentage))\n const radius = (size - strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n const dashOffset = circumference * (1 - clamped / 100)\n const styles = LEVEL_STYLES[level]\n\n return (\n <div className={cn(\"group relative inline-flex\", className)}>\n <button\n type=\"button\"\n aria-label={`上下文已使用 ${Math.round(clamped)}%`}\n className=\"relative inline-flex cursor-help items-center justify-center rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-2 focus-visible:ring-offset-[hsl(var(--background))]\"\n >\n <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} aria-hidden=\"true\">\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={strokeWidth}\n className={styles.trackClass}\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n className={cn(styles.strokeClass, \"transition-[stroke-dashoffset] duration-300\")}\n transform={`rotate(-90 ${size / 2} ${size / 2})`}\n />\n </svg>\n </button>\n {detail ? (\n <div className=\"pointer-events-none absolute bottom-full left-1/2 z-20 mb-2 hidden w-64 max-w-[min(20rem,calc(100vw-2rem))] -translate-x-1/2 rounded-xl border border-slate-700 bg-slate-950 px-3 py-2 text-[11px] text-slate-100 shadow-xl group-hover:block group-focus-within:block\">\n {detail}\n </div>\n ) : null}\n </div>\n )\n}\n","import Mention from \"@tiptap/extension-mention\"\nimport { PluginKey } from \"@tiptap/pm/state\"\n\nexport interface FileMentionAttrs {\n path: string\n name: string\n}\n\nexport interface FileSuggestionItem {\n path: string\n name: string\n is_dir: boolean\n}\n\nexport const fileMentionSuggestionKey = new PluginKey(\"fileMentionSuggestion\")\n\nfunction getFileMentionName(attrs: Partial<FileMentionAttrs>) {\n return attrs.name || attrs.path || \"\"\n}\n\nexport const FileMention = Mention.extend({\n name: \"fileMention\",\n\n addOptions() {\n const parentOptions = this.parent?.()\n\n return {\n ...parentOptions,\n HTMLAttributes: {\n ...(parentOptions?.HTMLAttributes ?? {}),\n class: \"file-mention-pill\",\n },\n deleteTriggerWithBackspace: true,\n suggestion: {\n ...(parentOptions?.suggestion ?? {}),\n char: \"@\",\n pluginKey: fileMentionSuggestionKey,\n },\n suggestions: parentOptions?.suggestions ?? [],\n renderText: ({ node }) => `@${getFileMentionName(node.attrs)}`,\n renderHTML: ({ options, node }) => [\n \"span\",\n {\n ...(options.HTMLAttributes ?? {}),\n class: \"file-mention-pill\",\n \"data-name\": node.attrs.name,\n \"data-path\": node.attrs.path,\n },\n getFileMentionName(node.attrs),\n ],\n }\n },\n\n addAttributes() {\n return {\n path: {\n default: \"\",\n parseHTML: (element: HTMLElement) => element.getAttribute(\"data-path\") || \"\",\n renderHTML: (attributes: FileMentionAttrs) => ({ \"data-path\": attributes.path }),\n },\n name: {\n default: \"\",\n parseHTML: (element: HTMLElement) => element.getAttribute(\"data-name\") || \"\",\n renderHTML: (attributes: FileMentionAttrs) => ({ \"data-name\": attributes.name }),\n },\n }\n },\n})\n","import Mention from \"@tiptap/extension-mention\"\nimport { PluginKey } from \"@tiptap/pm/state\"\n\nexport interface SkillMentionAttrs {\n skillId: string\n displayName: string\n description: string\n}\n\nexport interface SkillOnlySuggestionItem {\n skillId: string\n displayName?: string\n description: string\n local?: boolean\n}\n\nexport interface SkillCommandSuggestionItem {\n type: \"command\"\n id: string\n label: string\n description: string\n}\n\nexport interface SkillSuggestionSkillItem extends SkillOnlySuggestionItem {\n type: \"skill\"\n}\n\nexport type SkillSuggestionItem = SkillSuggestionSkillItem | SkillCommandSuggestionItem\n\nexport const COMMANDS: SkillCommandSuggestionItem[] = [\n {\n type: \"command\",\n id: \"resync\",\n label: \"同步技能\",\n description: \"从配置的技能目录拉取最新内容\",\n },\n]\n\nexport const skillMentionSuggestionKey = new PluginKey(\"skillMentionSuggestion\")\n\nfunction getSkillMentionName(attrs: Partial<SkillMentionAttrs>) {\n return attrs.displayName || attrs.skillId || \"\"\n}\n\nexport const SkillMention = Mention.extend({\n name: \"skillMention\",\n\n addOptions() {\n const parentOptions = this.parent?.()\n\n return {\n ...parentOptions,\n HTMLAttributes: {\n ...(parentOptions?.HTMLAttributes ?? {}),\n class: \"skill-mention-pill\",\n },\n deleteTriggerWithBackspace: true,\n suggestion: {\n ...(parentOptions?.suggestion ?? {}),\n char: \"/\",\n pluginKey: skillMentionSuggestionKey,\n },\n suggestions: parentOptions?.suggestions ?? [],\n renderText: ({ node }) => getSkillMentionName(node.attrs),\n renderHTML: ({ options, node }) => [\n \"span\",\n {\n ...(options.HTMLAttributes ?? {}),\n class: \"skill-mention-pill\",\n \"data-skill-id\": node.attrs.skillId,\n \"data-display-name\": node.attrs.displayName,\n \"data-description\": node.attrs.description,\n },\n getSkillMentionName(node.attrs),\n ],\n }\n },\n\n addAttributes() {\n return {\n skillId: {\n default: \"\",\n parseHTML: (element: HTMLElement) => element.getAttribute(\"data-skill-id\") || \"\",\n renderHTML: (attributes: SkillMentionAttrs) => ({\n \"data-skill-id\": attributes.skillId,\n }),\n },\n displayName: {\n default: \"\",\n parseHTML: (element: HTMLElement) => element.getAttribute(\"data-display-name\") || \"\",\n renderHTML: (attributes: SkillMentionAttrs) => ({\n \"data-display-name\": attributes.displayName,\n }),\n },\n description: {\n default: \"\",\n parseHTML: (element: HTMLElement) => element.getAttribute(\"data-description\") || \"\",\n renderHTML: (attributes: SkillMentionAttrs) => ({\n \"data-description\": attributes.description,\n }),\n },\n }\n },\n})\n","import { AlertTriangle, LoaderCircle } from \"lucide-react\"\nimport { cn } from \"../../lib/utils\"\nimport { useConnectionStore } from \"../../stores/connection-store\"\n\nfunction getBannerCopy(\n status: \"connecting\" | \"connected\" | \"disconnected\",\n reconnectAttempt: number,\n hasEverConnected: boolean,\n) {\n if (status === \"connecting\") {\n return {\n icon: <LoaderCircle size={14} className=\"animate-spin\" />,\n toneClass:\n \"border-amber-500/25 bg-amber-500/10 text-amber-100\",\n title: \"连接已断开,正在重连…\",\n detail:\n reconnectAttempt > 0\n ? `正在尝试恢复实时连接(第 ${reconnectAttempt} 次)`\n : \"正在尝试恢复实时连接,请稍候\",\n }\n }\n\n return {\n icon: <AlertTriangle size={14} />,\n toneClass: \"border-rose-500/25 bg-rose-500/10 text-rose-100\",\n title: hasEverConnected ? \"连接已断开,正在等待重连…\" : \"暂时无法建立连接\",\n detail: hasEverConnected\n ? \"消息同步可能会延迟,系统会继续自动重试\"\n : \"请检查服务是否可用,系统会继续自动重试\",\n }\n}\n\nexport function ConnectionBanner() {\n const status = useConnectionStore((state) => state.status)\n const reconnectAttempt = useConnectionStore((state) => state.reconnectAttempt)\n const hasEverConnected = useConnectionStore((state) => state.hasEverConnected)\n const lastDisconnectedAt = useConnectionStore((state) => state.lastDisconnectedAt)\n\n if (\n status === \"connected\" ||\n (!hasEverConnected && lastDisconnectedAt == null)\n ) {\n return null\n }\n\n const copy = getBannerCopy(status, reconnectAttempt, hasEverConnected)\n\n return (\n <div className=\"bg-[hsl(var(--background))] px-5 pt-3\">\n <div\n className={cn(\n \"mx-auto flex max-w-3xl items-start gap-3 rounded-2xl border px-4 py-3\",\n copy.toneClass,\n )}\n >\n <span className=\"mt-0.5 shrink-0\">{copy.icon}</span>\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium\">{copy.title}</div>\n <div className=\"text-xs opacity-80\">{copy.detail}</div>\n </div>\n </div>\n </div>\n )\n}\n","import { ChevronDown, Lightbulb, MessageSquare } from \"lucide-react\"\nimport {\n useCallback,\n useEffect,\n useEffectEvent,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport { StickToBottom, useStickToBottomContext } from \"use-stick-to-bottom\"\nimport { contentPreview, isHiddenInternalMessage } from \"../../lib/chat\"\nimport type { ChatMessage } from \"../../schemas/message\"\nimport { useChatStore } from \"../../stores/chat-store\"\nimport { PlanSummaryCard } from \"../plan/PlanSummaryCard\"\nimport { extractLatestPlanMessages } from \"../plan/extract-plan-messages\"\nimport type { AskUserAnswerData } from \"./AskUserQuestionBlock\"\nimport { AssistantTurnBlock } from \"./AssistantTurnBlock\"\nimport { CompactionCard } from \"./CompactionCard\"\nimport { RenderErrorBoundary } from \"./RenderErrorBoundary\"\nimport { StickyStatusBar } from \"./StickyStatusBar\"\nimport { TurnNavRail, type TurnNavItem } from \"./TurnNavRail\"\nimport {\n ErrorMessageBlock,\n UserMessageBubble,\n isErrorMessage,\n isUserMessage,\n} from \"./UserMessageBubble\"\nimport { formatToolName } from \"./display-utils\"\n\ntype AssistantTurnRenderBlock = {\n type: \"assistant_turn\"\n messages: ChatMessage[]\n key: string\n anchorId: string\n isStreaming: boolean\n railTitle: string\n}\n\ntype RenderBlock =\n | { type: \"message\"; message: ChatMessage; key: string }\n | AssistantTurnRenderBlock\n | { type: \"compaction\"; message: ChatMessage; key: string }\n | { type: \"planning_divider\"; kind: \"planning_enter\" | \"planning_exit\"; key: string }\n\nfunction parseModeChange(message: ChatMessage): { from: string; to: string } | null {\n if (message.kind !== \"mode_change\" || typeof message.content !== \"string\") {\n return null\n }\n try {\n const parsed = JSON.parse(message.content) as { from?: unknown; to?: unknown }\n if (typeof parsed.from === \"string\" && typeof parsed.to === \"string\") {\n return { from: parsed.from, to: parsed.to }\n }\n } catch {}\n return null\n}\n\nfunction getPlanningDividerKind(message: ChatMessage): \"planning_enter\" | \"planning_exit\" | null {\n if (message.kind === \"planning_enter\" || message.kind === \"planning_exit\") {\n return message.kind\n }\n const modeChange = parseModeChange(message)\n if (modeChange?.to === \"planning\") {\n return \"planning_enter\"\n }\n if (modeChange?.from === \"planning\") {\n return \"planning_exit\"\n }\n return null\n}\n\nfunction getMessagePreview(message: ChatMessage) {\n return contentPreview(message.content, 42)\n}\n\nfunction getAssistantTurnPreview(messages: ChatMessage[]) {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const preview = getMessagePreview(messages[index])\n if (preview) {\n return preview\n }\n }\n return \"本轮回复\"\n}\n\nfunction getMessageMeasureSignature(message: ChatMessage) {\n const contentSize =\n typeof message.content === \"string\"\n ? message.content.length\n : message.content.reduce((size, part) => size + JSON.stringify(part).length, 0)\n\n return [\n message.entry_id ?? message.timestamp ?? message.role,\n message.status ?? \"\",\n message.reasoning?.length ?? 0,\n message.tool_calls?.length ?? 0,\n contentSize,\n ].join(\":\")\n}\n\nfunction getMessagesMeasureSignature(messages: ChatMessage[]) {\n return messages.map((message) => getMessageMeasureSignature(message)).join(\"|\")\n}\n\nfunction safeJson(value: unknown) {\n try {\n return JSON.stringify(value)\n } catch {\n return String(value)\n }\n}\n\nfunction hashString(value: string) {\n let hash = 0\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 31 + value.charCodeAt(index)) | 0\n }\n return hash.toString(36)\n}\n\nfunction getMessageRenderSignature(message: ChatMessage) {\n return [\n message.entry_id ?? message.timestamp ?? message.role,\n message.status ?? \"\",\n hashString(safeJson(message.content)),\n hashString(message.reasoning ?? \"\"),\n hashString(safeJson(message.tool_calls ?? [])),\n hashString(safeJson(message.blocks ?? [])),\n hashString(safeJson(message.memory_refs ?? [])),\n ].join(\":\")\n}\n\nfunction getMessagesRenderSignature(messages: ChatMessage[]) {\n return messages.map((message) => getMessageRenderSignature(message)).join(\"|\")\n}\n\nfunction findScrollContainer(start: HTMLElement | null) {\n let current = start\n while (current) {\n const overflowY = getComputedStyle(current).overflowY\n if (overflowY === \"auto\" || overflowY === \"scroll\") {\n return current\n }\n current = current.parentElement\n }\n return null\n}\n\ninterface Props {\n sessionId: string\n messages: ChatMessage[]\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n sessionStatus?: string\n onConfirmPlan?: (action: \"execute\" | \"revise\", text?: string) => void\n}\n\nexport function MessageList({\n sessionId,\n messages: rawMessages,\n onAnswer,\n sessionStatus,\n onConfirmPlan,\n}: Props) {\n const messages = Array.isArray(rawMessages) ? rawMessages : []\n const agentLoops = useChatStore((state) => state.agentLoops[sessionId])\n const askAnswers = useChatStore((state) => state.askAnswers[sessionId])\n const agentLoopNameSet = useMemo(() => new Set(Object.keys(agentLoops ?? {})), [agentLoops])\n\n const renderBlocks = useMemo(() => {\n const visible = messages.filter((message) => {\n const loopName = message.loop_name ?? \"root\"\n if (loopName !== \"root\") return false\n if (agentLoopNameSet.has(loopName)) return false\n if (isHiddenInternalMessage(message)) return false\n if (message.kind === \"compaction\") return true\n return message.role !== \"tool\" || getPlanningDividerKind(message) !== null\n })\n\n const blocks: RenderBlock[] = []\n let assistantBuffer: ChatMessage[] = []\n let assistantTurnCount = 0\n let lastUserPreview = \"\"\n\n const flushAssistant = () => {\n if (assistantBuffer.length === 0) return\n\n assistantTurnCount += 1\n const last = assistantBuffer[assistantBuffer.length - 1]\n const isStreaming = assistantBuffer.some((message) => message.status === \"streaming\")\n\n blocks.push({\n type: \"assistant_turn\",\n messages: assistantBuffer,\n key: last.entry_id ?? `assistant-${blocks.length}`,\n anchorId: `chat-turn-${assistantTurnCount}`,\n isStreaming,\n railTitle: lastUserPreview || getAssistantTurnPreview(assistantBuffer),\n })\n assistantBuffer = []\n }\n\n for (const message of visible) {\n const dividerKind = getPlanningDividerKind(message)\n if (dividerKind) {\n flushAssistant()\n blocks.push({\n type: \"planning_divider\",\n kind: dividerKind,\n key: message.entry_id ?? `${dividerKind}-${blocks.length}`,\n })\n continue\n }\n\n if (message.kind === \"compaction\") {\n flushAssistant()\n blocks.push({\n type: \"compaction\",\n message,\n key: message.entry_id ?? `compaction-${blocks.length}`,\n })\n continue\n }\n\n if (message.role === \"assistant\") {\n assistantBuffer.push(message)\n continue\n }\n\n flushAssistant()\n if (isUserMessage(message)) {\n lastUserPreview = getMessagePreview(message)\n }\n blocks.push({\n type: \"message\",\n message,\n key: message.entry_id ?? `${message.role}-${blocks.length}`,\n })\n }\n\n flushAssistant()\n\n return blocks\n }, [agentLoopNameSet, messages])\n\n const hasInterruptedTurn = useMemo(\n () =>\n renderBlocks.some(\n (block) =>\n block.type === \"assistant_turn\" &&\n block.messages.some((message) => message.status === \"interrupted\"),\n ),\n [renderBlocks],\n )\n\n const lastTurnId = useMemo(() => {\n for (let index = renderBlocks.length - 1; index >= 0; index -= 1) {\n const block = renderBlocks[index]\n if (block.type === \"assistant_turn\") return block.anchorId\n if (block.type === \"message\" && isUserMessage(block.message)) return null\n }\n return null\n }, [renderBlocks])\n\n const turnNavItems = useMemo<TurnNavItem[]>(\n () =>\n renderBlocks\n .filter((block): block is AssistantTurnRenderBlock => block.type === \"assistant_turn\")\n .map((block) => ({\n id: block.anchorId,\n title: block.railTitle,\n })),\n [renderBlocks],\n )\n\n const stickyTurn = useMemo(\n () =>\n renderBlocks.find(\n (block): block is AssistantTurnRenderBlock =>\n block.type === \"assistant_turn\" &&\n block.anchorId === lastTurnId &&\n block.isStreaming,\n ) ?? null,\n [lastTurnId, renderBlocks],\n )\n\n const containerRef = useRef<HTMLDivElement>(null)\n const scrollContainerRef = useRef<HTMLElement | null>(null)\n const frameRef = useRef<number | null>(null)\n const [activeTurnId, setActiveTurnId] = useState<string | null>(lastTurnId)\n\n const layoutSignature = useMemo(\n () => getMessagesMeasureSignature(messages),\n [messages],\n )\n\n const measureActiveTurn = useEffectEvent(() => {\n const container = scrollContainerRef.current\n const root = containerRef.current\n if (!container || !root) {\n setActiveTurnId(lastTurnId)\n return\n }\n const turnElements = Array.from(root.querySelectorAll<HTMLElement>(\"[data-turn-id]\"))\n if (turnElements.length === 0) {\n setActiveTurnId(lastTurnId)\n return\n }\n const containerRect = container.getBoundingClientRect()\n const targetY = containerRect.top + containerRect.height * 0.15\n let bestId = lastTurnId\n let bestDistance = Number.POSITIVE_INFINITY\n for (const el of turnElements) {\n const rect = el.getBoundingClientRect()\n if (rect.bottom < containerRect.top || rect.top > containerRect.bottom) continue\n const turnId = el.dataset.turnId\n if (!turnId) continue\n const distance = Math.abs(rect.top - targetY)\n if (distance < bestDistance) {\n bestDistance = distance\n bestId = turnId\n }\n }\n setActiveTurnId(bestId)\n })\n\n const scheduleMeasure = useEffectEvent(() => {\n if (frameRef.current != null) return\n frameRef.current = window.requestAnimationFrame(() => {\n frameRef.current = null\n measureActiveTurn()\n })\n })\n\n useEffect(() => {\n scrollContainerRef.current = findScrollContainer(containerRef.current)\n const sc = scrollContainerRef.current\n if (!sc) return\n sc.addEventListener(\"scroll\", scheduleMeasure, { passive: true })\n window.addEventListener(\"resize\", scheduleMeasure)\n scheduleMeasure()\n return () => {\n sc.removeEventListener(\"scroll\", scheduleMeasure)\n window.removeEventListener(\"resize\", scheduleMeasure)\n if (frameRef.current != null) {\n window.cancelAnimationFrame(frameRef.current)\n frameRef.current = null\n }\n }\n }, [scheduleMeasure])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: lastTurnId and layoutSignature are intentional triggers to re-measure\n useEffect(() => {\n scheduleMeasure()\n }, [lastTurnId, layoutSignature, scheduleMeasure])\n\n const handleSelectTurn = useCallback((turnId: string) => {\n document.getElementById(turnId)?.scrollIntoView({ behavior: \"smooth\", block: \"start\" })\n }, [])\n\n return (\n <div ref={containerRef} className=\"relative min-h-0 flex-1\">\n {turnNavItems.length > 1 ? (\n <TurnNavRail\n items={turnNavItems}\n activeTurnId={activeTurnId ?? lastTurnId}\n onSelectTurn={handleSelectTurn}\n />\n ) : null}\n <StickToBottom className=\"h-full overflow-y-hidden\" resize=\"smooth\">\n <StickToBottom.Content className=\"px-5 py-6\">\n <MessageListContent\n askAnswers={askAnswers}\n hasInterruptedTurn={hasInterruptedTurn}\n lastTurnId={lastTurnId}\n layoutSignature={layoutSignature}\n messages={messages}\n onAnswer={onAnswer}\n onConfirmPlan={onConfirmPlan}\n renderBlocks={renderBlocks}\n sessionId={sessionId}\n sessionStatus={sessionStatus}\n stickyTurn={stickyTurn}\n />\n </StickToBottom.Content>\n <ScrollToBottomButton />\n </StickToBottom>\n </div>\n )\n}\n\nfunction MessageListContent({\n askAnswers,\n hasInterruptedTurn,\n lastTurnId,\n layoutSignature,\n messages,\n onAnswer,\n onConfirmPlan,\n renderBlocks,\n sessionId,\n sessionStatus,\n stickyTurn,\n}: {\n askAnswers?: Record<string, AskUserAnswerData>\n hasInterruptedTurn: boolean\n lastTurnId: string | null\n layoutSignature: string\n messages: ChatMessage[]\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n onConfirmPlan?: (action: \"execute\" | \"revise\", text?: string) => void\n renderBlocks: RenderBlock[]\n sessionId: string\n sessionStatus?: string\n stickyTurn: AssistantTurnRenderBlock | null\n}) {\n const { scrollToBottom } = useStickToBottomContext()\n\n const handleJumpToLatest = useCallback(() => {\n if (lastTurnId) {\n document.getElementById(lastTurnId)?.scrollIntoView({ behavior: \"smooth\", block: \"end\" })\n return\n }\n scrollToBottom()\n }, [lastTurnId, scrollToBottom])\n\n return (\n <div className=\"mx-auto max-w-3xl\">\n <div className=\"min-w-0 flex flex-col gap-8\">\n {stickyTurn ? (\n <StickyStatusBar\n sessionId={sessionId}\n messages={stickyTurn.messages}\n isLastTurn={stickyTurn.anchorId === lastTurnId}\n isStreaming={stickyTurn.isStreaming}\n onJumpToLatest={handleJumpToLatest}\n />\n ) : null}\n\n {renderBlocks.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-3 py-24 text-[hsl(var(--muted-foreground))]\">\n <MessageSquare size={40} strokeWidth={1.5} />\n <span className=\"text-base font-medium\">开始对话</span>\n <span className=\"text-sm opacity-60\">在下方输入消息开始聊天</span>\n </div>\n ) : (\n renderBlocks.map((block, blockIndex) => {\n if (block.type === \"message\") {\n return (\n <div key={block.key} className=\"msg-animate\">\n {isUserMessage(block.message) ? (\n <UserMessageBubble message={block.message} />\n ) : isErrorMessage(block.message) ? (\n <ErrorMessageBlock message={block.message} />\n ) : null}\n </div>\n )\n }\n\n if (block.type === \"assistant_turn\") {\n const nextBlock = renderBlocks[blockIndex + 1]\n const hasExitPlan = block.messages.some((message) =>\n message.tool_calls?.some(\n (toolCall) =>\n formatToolName(toolCall.name) === \"ExitPlanMode\" &&\n toolCall.status !== \"error\" &&\n toolCall.status !== \"cancelled\",\n ),\n )\n const isFollowedByPlanningExit =\n nextBlock?.type === \"planning_divider\" && nextBlock.kind === \"planning_exit\"\n const showPlanCard =\n (hasExitPlan || isFollowedByPlanningExit) &&\n onConfirmPlan &&\n sessionStatus === \"waiting_for_input\"\n\n return (\n <div\n key={block.key}\n id={block.anchorId}\n data-turn-id={block.anchorId}\n className=\"msg-animate flex scroll-mt-6 flex-col gap-4\"\n >\n <RenderErrorBoundary\n label=\"助手消息\"\n details={block.key}\n resetKey={getMessagesRenderSignature(block.messages)}\n >\n <AssistantTurnBlock\n turnKey={block.key}\n sessionId={sessionId}\n messages={block.messages}\n isStreaming={block.isStreaming}\n isLastTurn={block.anchorId === lastTurnId}\n askAnswers={askAnswers}\n onAnswer={onAnswer}\n sessionStatus={sessionStatus}\n />\n </RenderErrorBoundary>\n {showPlanCard ? (\n <RenderErrorBoundary\n label=\"规划摘要\"\n details={block.key}\n resetKey={`${sessionStatus ?? \"\"}:${layoutSignature}`}\n >\n <PlanSummaryCard\n messages={extractLatestPlanMessages(messages)}\n sessionStatus={sessionStatus}\n onConfirmPlan={onConfirmPlan}\n />\n </RenderErrorBoundary>\n ) : null}\n </div>\n )\n }\n\n if (block.type === \"compaction\") {\n return (\n <div key={block.key} className=\"msg-animate\">\n <CompactionCard\n sessionId={sessionId}\n compaction={block.message.compaction}\n status={block.message.status}\n />\n </div>\n )\n }\n\n return <PlanningDivider key={block.key} kind={block.kind} />\n })\n )}\n\n {sessionStatus === \"interrupted\" && !hasInterruptedTurn ? (\n <div className=\"flex\">\n <div className=\"rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300\">\n 已中断\n </div>\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n\nfunction ScrollToBottomButton() {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext()\n if (isAtBottom) return null\n\n return (\n <button\n type=\"button\"\n onClick={() => scrollToBottom()}\n className=\"absolute bottom-4 right-4 flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-3 py-1.5 text-xs text-[hsl(var(--muted-foreground))] shadow-lg transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n >\n <ChevronDown size={14} />\n <span>滚动到底部</span>\n </button>\n )\n}\n\nfunction PlanningDivider({ kind }: { kind: \"planning_enter\" | \"planning_exit\" }) {\n const isEnter = kind === \"planning_enter\"\n\n return (\n <div className=\"flex items-center gap-3 py-1\">\n <div className=\"h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent\" />\n <div className=\"inline-flex items-center gap-1.5 rounded-full border border-amber-500/30 bg-amber-500/10 px-3 py-1 text-[11px] text-amber-300\">\n <Lightbulb size={12} />\n <span>{isEnter ? \"进入规划模式\" : \"规划完成\"}</span>\n </div>\n <div className=\"h-px flex-1 bg-gradient-to-r from-transparent via-amber-400/40 to-transparent\" />\n </div>\n )\n}\n","/*!---------------------------------------------------------------------------------------------\n * Copyright (c) StackBlitz. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nimport { useCallback, useMemo, useRef, useState, } from \"react\";\nconst DEFAULT_SPRING_ANIMATION = {\n /**\n * A value from 0 to 1, on how much to damp the animation.\n * 0 means no damping, 1 means full damping.\n *\n * @default 0.7\n */\n damping: 0.7,\n /**\n * The stiffness of how fast/slow the animation gets up to speed.\n *\n * @default 0.05\n */\n stiffness: 0.05,\n /**\n * The inertial mass associated with the animation.\n * Higher numbers make the animation slower.\n *\n * @default 1.25\n */\n mass: 1.25,\n};\nconst STICK_TO_BOTTOM_OFFSET_PX = 70;\nconst SIXTY_FPS_INTERVAL_MS = 1000 / 60;\nconst RETAIN_ANIMATION_DURATION_MS = 350;\nlet mouseDown = false;\nglobalThis.document?.addEventListener(\"mousedown\", () => {\n mouseDown = true;\n});\nglobalThis.document?.addEventListener(\"mouseup\", () => {\n mouseDown = false;\n});\nglobalThis.document?.addEventListener(\"click\", () => {\n mouseDown = false;\n});\nexport const useStickToBottom = (options = {}) => {\n const [escapedFromLock, updateEscapedFromLock] = useState(false);\n const [isAtBottom, updateIsAtBottom] = useState(options.initial !== false);\n const [isNearBottom, setIsNearBottom] = useState(false);\n const optionsRef = useRef(null);\n optionsRef.current = options;\n const isSelecting = useCallback(() => {\n if (!mouseDown) {\n return false;\n }\n const selection = window.getSelection();\n if (!selection || !selection.rangeCount) {\n return false;\n }\n const range = selection.getRangeAt(0);\n return (range.commonAncestorContainer.contains(scrollRef.current) ||\n scrollRef.current?.contains(range.commonAncestorContainer));\n }, []);\n const setIsAtBottom = useCallback((isAtBottom) => {\n state.isAtBottom = isAtBottom;\n updateIsAtBottom(isAtBottom);\n }, []);\n const setEscapedFromLock = useCallback((escapedFromLock) => {\n state.escapedFromLock = escapedFromLock;\n updateEscapedFromLock(escapedFromLock);\n }, []);\n // biome-ignore lint/correctness/useExhaustiveDependencies: not needed\n const state = useMemo(() => {\n let lastCalculation;\n return {\n escapedFromLock,\n isAtBottom,\n resizeDifference: 0,\n accumulated: 0,\n velocity: 0,\n listeners: new Set(),\n get scrollTop() {\n return scrollRef.current?.scrollTop ?? 0;\n },\n set scrollTop(scrollTop) {\n if (scrollRef.current) {\n scrollRef.current.scrollTop = scrollTop;\n state.ignoreScrollToTop = scrollRef.current.scrollTop;\n }\n },\n get targetScrollTop() {\n if (!scrollRef.current || !contentRef.current) {\n return 0;\n }\n return (scrollRef.current.scrollHeight - 1 - scrollRef.current.clientHeight);\n },\n get calculatedTargetScrollTop() {\n if (!scrollRef.current || !contentRef.current) {\n return 0;\n }\n const { targetScrollTop } = this;\n if (!options.targetScrollTop) {\n return targetScrollTop;\n }\n if (lastCalculation?.targetScrollTop === targetScrollTop) {\n return lastCalculation.calculatedScrollTop;\n }\n const calculatedScrollTop = Math.max(Math.min(options.targetScrollTop(targetScrollTop, {\n scrollElement: scrollRef.current,\n contentElement: contentRef.current,\n }), targetScrollTop), 0);\n lastCalculation = { targetScrollTop, calculatedScrollTop };\n requestAnimationFrame(() => {\n lastCalculation = undefined;\n });\n return calculatedScrollTop;\n },\n get scrollDifference() {\n return this.calculatedTargetScrollTop - this.scrollTop;\n },\n get isNearBottom() {\n return this.scrollDifference <= STICK_TO_BOTTOM_OFFSET_PX;\n },\n };\n }, []);\n const scrollToBottom = useCallback((scrollOptions = {}) => {\n if (typeof scrollOptions === \"string\") {\n scrollOptions = { animation: scrollOptions };\n }\n if (!scrollOptions.preserveScrollPosition) {\n setIsAtBottom(true);\n }\n const waitElapsed = Date.now() + (Number(scrollOptions.wait) || 0);\n const behavior = mergeAnimations(optionsRef.current, scrollOptions.animation);\n const { ignoreEscapes = false } = scrollOptions;\n let durationElapsed;\n let startTarget = state.calculatedTargetScrollTop;\n if (scrollOptions.duration instanceof Promise) {\n scrollOptions.duration.finally(() => {\n durationElapsed = Date.now();\n });\n }\n else {\n durationElapsed = waitElapsed + (scrollOptions.duration ?? 0);\n }\n const next = async () => {\n const promise = new Promise(requestAnimationFrame).then(() => {\n if (!state.isAtBottom) {\n state.animation = undefined;\n return false;\n }\n const { scrollTop } = state;\n const tick = performance.now();\n const tickDelta = (tick - (state.lastTick ?? tick)) / SIXTY_FPS_INTERVAL_MS;\n state.animation || (state.animation = { behavior, promise, ignoreEscapes });\n if (state.animation.behavior === behavior) {\n state.lastTick = tick;\n }\n if (isSelecting()) {\n return next();\n }\n if (waitElapsed > Date.now()) {\n return next();\n }\n if (scrollTop < Math.min(startTarget, state.calculatedTargetScrollTop)) {\n if (state.animation?.behavior === behavior) {\n if (behavior === \"instant\") {\n state.scrollTop = state.calculatedTargetScrollTop;\n return next();\n }\n state.velocity =\n (behavior.damping * state.velocity +\n behavior.stiffness * state.scrollDifference) /\n behavior.mass;\n state.accumulated += state.velocity * tickDelta;\n state.scrollTop += state.accumulated;\n if (state.scrollTop !== scrollTop) {\n state.accumulated = 0;\n }\n }\n return next();\n }\n if (durationElapsed > Date.now()) {\n startTarget = state.calculatedTargetScrollTop;\n return next();\n }\n state.animation = undefined;\n /**\n * If we're still below the target, then queue\n * up another scroll to the bottom with the last\n * requested animatino.\n */\n if (state.scrollTop < state.calculatedTargetScrollTop) {\n return scrollToBottom({\n animation: mergeAnimations(optionsRef.current, optionsRef.current.resize),\n ignoreEscapes,\n duration: Math.max(0, durationElapsed - Date.now()) || undefined,\n });\n }\n return state.isAtBottom;\n });\n return promise.then((isAtBottom) => {\n requestAnimationFrame(() => {\n if (!state.animation) {\n state.lastTick = undefined;\n state.velocity = 0;\n }\n });\n return isAtBottom;\n });\n };\n if (scrollOptions.wait !== true) {\n state.animation = undefined;\n }\n if (state.animation?.behavior === behavior) {\n return state.animation.promise;\n }\n return next();\n }, [setIsAtBottom, isSelecting, state]);\n const stopScroll = useCallback(() => {\n setEscapedFromLock(true);\n setIsAtBottom(false);\n }, [setEscapedFromLock, setIsAtBottom]);\n const handleScroll = useCallback(({ target }) => {\n if (target !== scrollRef.current) {\n return;\n }\n const { scrollTop, ignoreScrollToTop } = state;\n let { lastScrollTop = scrollTop } = state;\n state.lastScrollTop = scrollTop;\n state.ignoreScrollToTop = undefined;\n if (ignoreScrollToTop && ignoreScrollToTop > scrollTop) {\n /**\n * When the user scrolls up while the animation plays, the `scrollTop` may\n * not come in separate events; if this happens, to make sure `isScrollingUp`\n * is correct, set the lastScrollTop to the ignored event.\n */\n lastScrollTop = ignoreScrollToTop;\n }\n setIsNearBottom(state.isNearBottom);\n /**\n * Scroll events may come before a ResizeObserver event,\n * so in order to ignore resize events correctly we use a\n * timeout.\n *\n * @see https://github.com/WICG/resize-observer/issues/25#issuecomment-248757228\n */\n setTimeout(() => {\n /**\n * When theres a resize difference ignore the resize event.\n */\n if (state.resizeDifference || scrollTop === ignoreScrollToTop) {\n return;\n }\n if (isSelecting()) {\n setEscapedFromLock(true);\n setIsAtBottom(false);\n return;\n }\n const isScrollingDown = scrollTop > lastScrollTop;\n const isScrollingUp = scrollTop < lastScrollTop;\n if (state.animation?.ignoreEscapes) {\n state.scrollTop = lastScrollTop;\n return;\n }\n if (isScrollingUp) {\n setEscapedFromLock(true);\n setIsAtBottom(false);\n }\n if (isScrollingDown) {\n setEscapedFromLock(false);\n }\n if (!state.escapedFromLock && state.isNearBottom) {\n setIsAtBottom(true);\n }\n }, 1);\n }, [setEscapedFromLock, setIsAtBottom, isSelecting, state]);\n const handleWheel = useCallback(({ target, deltaY }) => {\n let element = target;\n while (![\"scroll\", \"auto\"].includes(getComputedStyle(element).overflow)) {\n if (!element.parentElement) {\n return;\n }\n element = element.parentElement;\n }\n /**\n * The browser may cancel the scrolling from the mouse wheel\n * if we update it from the animation in meantime.\n * To prevent this, always escape when the wheel is scrolled up.\n */\n if (element === scrollRef.current &&\n deltaY < 0 &&\n scrollRef.current.scrollHeight > scrollRef.current.clientHeight &&\n !state.animation?.ignoreEscapes) {\n setEscapedFromLock(true);\n setIsAtBottom(false);\n }\n }, [setEscapedFromLock, setIsAtBottom, state]);\n const scrollRef = useRefCallback((scroll) => {\n scrollRef.current?.removeEventListener(\"scroll\", handleScroll);\n scrollRef.current?.removeEventListener(\"wheel\", handleWheel);\n scroll?.addEventListener(\"scroll\", handleScroll, { passive: true });\n scroll?.addEventListener(\"wheel\", handleWheel, { passive: true });\n }, []);\n const contentRef = useRefCallback((content) => {\n state.resizeObserver?.disconnect();\n if (!content) {\n return;\n }\n let previousHeight;\n state.resizeObserver = new ResizeObserver(([entry]) => {\n const { height } = entry.contentRect;\n const difference = height - (previousHeight ?? height);\n state.resizeDifference = difference;\n /**\n * Sometimes the browser can overscroll past the target,\n * so check for this and adjust appropriately.\n */\n if (state.scrollTop > state.targetScrollTop) {\n state.scrollTop = state.targetScrollTop;\n }\n setIsNearBottom(state.isNearBottom);\n if (difference >= 0) {\n /**\n * If it's a positive resize, scroll to the bottom when\n * we're already at the bottom.\n */\n const animation = mergeAnimations(optionsRef.current, previousHeight\n ? optionsRef.current.resize\n : optionsRef.current.initial);\n scrollToBottom({\n animation,\n wait: true,\n preserveScrollPosition: true,\n duration: animation === \"instant\" ? undefined : RETAIN_ANIMATION_DURATION_MS,\n });\n }\n else {\n /**\n * Else if it's a negative resize, check if we're near the bottom\n * if we are want to un-escape from the lock, because the resize\n * could have caused the container to be at the bottom.\n */\n if (state.isNearBottom) {\n setEscapedFromLock(false);\n setIsAtBottom(true);\n }\n }\n previousHeight = height;\n /**\n * Reset the resize difference after the scroll event\n * has fired. Requires a rAF to wait for the scroll event,\n * and a setTimeout to wait for the other timeout we have in\n * resizeObserver in case the scroll event happens after the\n * resize event.\n */\n requestAnimationFrame(() => {\n setTimeout(() => {\n if (state.resizeDifference === difference) {\n state.resizeDifference = 0;\n }\n }, 1);\n });\n });\n state.resizeObserver?.observe(content);\n }, []);\n return {\n contentRef,\n scrollRef,\n scrollToBottom,\n stopScroll,\n isAtBottom: isAtBottom || isNearBottom,\n isNearBottom,\n escapedFromLock,\n state,\n };\n};\nfunction useRefCallback(callback, deps) {\n // biome-ignore lint/correctness/useExhaustiveDependencies: not needed\n const result = useCallback((ref) => {\n result.current = ref;\n return callback(ref);\n }, deps);\n return result;\n}\nconst animationCache = new Map();\nfunction mergeAnimations(...animations) {\n const result = { ...DEFAULT_SPRING_ANIMATION };\n let instant = false;\n for (const animation of animations) {\n if (animation === \"instant\") {\n instant = true;\n continue;\n }\n if (typeof animation !== \"object\") {\n continue;\n }\n instant = false;\n result.damping = animation.damping ?? result.damping;\n result.stiffness = animation.stiffness ?? result.stiffness;\n result.mass = animation.mass ?? result.mass;\n }\n const key = JSON.stringify(result);\n if (!animationCache.has(key)) {\n animationCache.set(key, Object.freeze(result));\n }\n return instant ? \"instant\" : animationCache.get(key);\n}\n","/*!---------------------------------------------------------------------------------------------\n * Copyright (c) StackBlitz. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nimport * as React from \"react\";\nimport { createContext, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, } from \"react\";\nimport { useStickToBottom, } from \"./useStickToBottom.js\";\nconst StickToBottomContext = createContext(null);\nconst useIsomorphicLayoutEffect = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\nexport function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {\n const customTargetScrollTop = useRef(null);\n const targetScrollTop = React.useCallback((target, elements) => {\n const get = context?.targetScrollTop ?? currentTargetScrollTop;\n return get?.(target, elements) ?? target;\n }, [currentTargetScrollTop]);\n const defaultInstance = useStickToBottom({\n mass,\n damping,\n stiffness,\n resize,\n initial,\n targetScrollTop,\n });\n const { scrollRef, contentRef, scrollToBottom, stopScroll, isAtBottom, escapedFromLock, state, } = instance ?? defaultInstance;\n const context = useMemo(() => ({\n scrollToBottom,\n stopScroll,\n scrollRef,\n isAtBottom,\n escapedFromLock,\n contentRef,\n state,\n get targetScrollTop() {\n return customTargetScrollTop.current;\n },\n set targetScrollTop(targetScrollTop) {\n customTargetScrollTop.current = targetScrollTop;\n },\n }), [\n scrollToBottom,\n isAtBottom,\n contentRef,\n scrollRef,\n stopScroll,\n escapedFromLock,\n state,\n ]);\n useImperativeHandle(contextRef, () => context, [context]);\n useIsomorphicLayoutEffect(() => {\n if (!scrollRef.current) {\n return;\n }\n if (getComputedStyle(scrollRef.current).overflow === \"visible\") {\n scrollRef.current.style.overflow = \"auto\";\n }\n }, []);\n return (React.createElement(StickToBottomContext.Provider, { value: context },\n React.createElement(\"div\", { ...props }, typeof children === \"function\" ? children(context) : children)));\n}\n(function (StickToBottom) {\n function Content({ children, scrollClassName, ...props }) {\n const context = useStickToBottomContext();\n return (React.createElement(\"div\", { ref: context.scrollRef, style: {\n height: \"100%\",\n width: \"100%\",\n scrollbarGutter: \"stable both-edges\",\n }, className: scrollClassName },\n React.createElement(\"div\", { ...props, ref: context.contentRef }, typeof children === \"function\" ? children(context) : children)));\n }\n StickToBottom.Content = Content;\n})(StickToBottom || (StickToBottom = {}));\n/**\n * Use this hook inside a <StickToBottom> component to gain access to whether the component is at the bottom of the scrollable area.\n */\nexport function useStickToBottomContext() {\n const context = useContext(StickToBottomContext);\n if (!context) {\n throw new Error(\"use-stick-to-bottom component context must be used within a StickToBottom component\");\n }\n return context;\n}\n","import { CheckCircle2, ChevronRight, PencilLine, Play, Sparkles } from \"lucide-react\"\nimport { useMemo, useState } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport type { ChatMessage } from \"../../schemas/message\"\nimport { useUiStore } from \"../../stores/ui-store\"\nimport { parsePlanMessages } from \"./parse-plan-messages\"\n\ninterface Props {\n messages: ChatMessage[]\n sessionStatus?: string\n onConfirmPlan?: (action: \"execute\" | \"revise\", text?: string) => void\n}\n\ntype SummaryState =\n | { kind: \"complete\"; label: string }\n | { kind: \"failed\"; label: string }\n | { kind: \"interrupted\"; label: string }\n | { kind: \"progress\"; label: string; dots: string }\n\nexport function PlanSummaryCard({\n messages,\n sessionStatus,\n onConfirmPlan,\n}: Props) {\n const data = useMemo(() => parsePlanMessages(messages), [messages])\n const rightPanelCollapsed = useUiStore((state) => state.rightPanelCollapsed)\n const toggleRightPanel = useUiStore((state) => state.toggleRightPanel)\n const setActiveRightTab = useUiStore((state) => state.setActiveRightTab)\n const summaryState = useMemo(() => getSummaryState(data, sessionStatus), [data, sessionStatus])\n const stepCount = useMemo(() => countPlanSteps(data.plan), [data.plan])\n const isWaitingForInput = sessionStatus === \"waiting_for_input\"\n const canConfirm =\n Boolean(onConfirmPlan) &&\n isWaitingForInput &&\n data.lastPauseTool === \"ExitPlanMode\"\n\n const openPlanPanel = () => {\n if (rightPanelCollapsed) {\n toggleRightPanel()\n }\n setActiveRightTab(\"situation\")\n }\n\n return (\n <div className=\"flex w-full flex-col gap-4 rounded-2xl border border-[hsl(var(--border))] bg-[hsl(var(--card)/0.55)] p-4\">\n <button\n type=\"button\"\n onClick={openPlanPanel}\n className=\"flex w-full flex-col gap-4 text-left transition-colors hover:text-[hsl(var(--foreground))]\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 space-y-2\">\n <div className=\"flex items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]\">\n <Sparkles size={12} />\n <span>规划摘要</span>\n </div>\n <div className=\"truncate text-base font-medium text-[hsl(var(--foreground))]\">\n {data.intent || \"当前规划\"}\n </div>\n <div className=\"flex flex-wrap items-center gap-2 text-xs\">\n {summaryState.kind === \"progress\" ? (\n <>\n <span className=\"rounded-full bg-[hsl(var(--accent))] px-2.5 py-1 text-[hsl(var(--foreground))]\">\n {summaryState.label}\n </span>\n <span className=\"font-mono tracking-[0.25em] text-[hsl(var(--muted-foreground))]\">\n {summaryState.dots}\n </span>\n </>\n ) : (\n <span\n className={cn(\n \"rounded-full px-2.5 py-1\",\n summaryState.kind === \"complete\" &&\n \"bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]\",\n summaryState.kind === \"failed\" &&\n \"bg-[hsl(var(--destructive)/0.12)] text-[hsl(var(--destructive))]\",\n summaryState.kind === \"interrupted\" && \"bg-orange-500/12 text-orange-300\",\n )}\n >\n {summaryState.label}\n </span>\n )}\n </div>\n </div>\n <ChevronRight\n size={16}\n className=\"mt-1 shrink-0 text-[hsl(var(--muted-foreground))]\"\n aria-hidden=\"true\"\n />\n </div>\n\n {summaryState.kind === \"complete\" && (\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]\">\n <span className=\"rounded-full border border-[hsl(var(--border))] px-2.5 py-1\">\n {data.selectedSkills.length} 个技能\n </span>\n <span className=\"rounded-full border border-[hsl(var(--border))] px-2.5 py-1\">\n {stepCount} 个步骤\n </span>\n <span className=\"inline-flex items-center gap-1 text-[hsl(var(--muted-foreground))]\">\n <CheckCircle2 size={12} />\n 右侧查看详情\n </span>\n </div>\n )}\n </button>\n\n {canConfirm && <PlanConfirmationPanel onConfirmPlan={onConfirmPlan} />}\n </div>\n )\n}\n\nfunction PlanConfirmationPanel({\n onConfirmPlan,\n}: {\n onConfirmPlan?: (action: \"execute\" | \"revise\", text?: string) => void\n}) {\n const [isEditing, setIsEditing] = useState(false)\n const [revisionText, setRevisionText] = useState(\"\")\n\n const submitRevision = () => {\n const trimmed = revisionText.trim()\n if (!trimmed) return\n onConfirmPlan?.(\"revise\", trimmed)\n setRevisionText(\"\")\n setIsEditing(false)\n }\n\n return (\n <div className=\"space-y-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background)/0.45)] p-3\">\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => onConfirmPlan?.(\"execute\")}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-[hsl(var(--primary))] px-3 py-2 text-sm font-medium text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90\"\n >\n <Play size={14} />\n 开始执行\n </button>\n <button\n type=\"button\"\n onClick={() => setIsEditing((value) => !value)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-[hsl(var(--border))] px-3 py-2 text-sm text-[hsl(var(--foreground))] transition-colors hover:bg-[hsl(var(--accent))]\"\n >\n <PencilLine size={14} />\n 修改\n </button>\n </div>\n\n {isEditing && (\n <div className=\"space-y-2\">\n <textarea\n value={revisionText}\n onChange={(event) => setRevisionText(event.target.value)}\n placeholder=\"输入修改建议...\"\n className=\"min-h-24 w-full resize-y rounded-lg border border-[hsl(var(--border))] bg-transparent px-3 py-2 text-sm text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground))]\"\n />\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n disabled={!revisionText.trim()}\n onClick={submitRevision}\n className=\"rounded-lg bg-[hsl(var(--primary))] px-3 py-1.5 text-xs font-medium text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90 disabled:opacity-30\"\n >\n 提交修改意见\n </button>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nfunction getSummaryState(\n data: ReturnType<typeof parsePlanMessages>,\n sessionStatus?: string,\n): SummaryState {\n if (sessionStatus === \"failed\") {\n return { kind: \"failed\", label: \"出错\" }\n }\n if (sessionStatus === \"interrupted\") {\n return { kind: \"interrupted\", label: \"已中断\" }\n }\n if (data.parseError) {\n return { kind: \"failed\", label: \"解析失败\" }\n }\n if (data.hasPlanContent || data.plan != null) {\n return { kind: \"complete\", label: \"已生成\" }\n }\n if (data.selectedSkills.length > 0) {\n return { kind: \"progress\", label: \"技能分析中\", dots: \"●●○\" }\n }\n if (data.searchResults.length > 0) {\n return { kind: \"progress\", label: \"技能发现中\", dots: \"●○○\" }\n }\n return { kind: \"progress\", label: \"规划准备中\", dots: \"○○○\" }\n}\n\nfunction countPlanSteps(plan: ReturnType<typeof parsePlanMessages>[\"plan\"]): number {\n if (!plan) return 0\n\n const countNode = (node: (typeof plan.root)[\"children\"][number] | typeof plan.root): number => {\n const children = Array.isArray(node.children) ? node.children : []\n return 1 + children.reduce((total, child) => total + countNode(child), 0)\n }\n\n if (plan.root.id === \"plan-root\") {\n const children = Array.isArray(plan.root.children) ? plan.root.children : []\n return children.reduce((total, child) => total + countNode(child), 0)\n }\n\n return countNode(plan.root)\n}\n","import { Check, Loader2, MessageSquareMore } from \"lucide-react\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { cn } from \"../../lib/utils\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\n\ninterface OptionItem {\n label: string\n description: string\n}\n\ninterface QuestionItem {\n question: string\n options: OptionItem[]\n multiSelect?: boolean\n}\n\ninterface SourceLoopInfo {\n loop_name: string\n description: string\n}\n\ninterface AskUserQuestionData {\n questions: QuestionItem[]\n source_loop?: SourceLoopInfo | null\n}\n\nexport type AskUserAnswerData = {\n selections: Record<number, number[]>\n custom: Record<number, string>\n}\n\ninterface Props {\n data: AskUserQuestionData\n answered: boolean\n toolCallId: string\n sessionStatus: string\n answerData?: AskUserAnswerData | undefined\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n}\n\nexport function AskUserQuestionBlock({\n data,\n answered,\n toolCallId,\n sessionStatus,\n answerData,\n onAnswer,\n}: Props) {\n // Per-question state: selected option indices or custom text\n const [selections, setSelections] = useState<Map<number, Set<number>>>(new Map())\n const [customTexts, setCustomTexts] = useState<Map<number, string>>(new Map())\n const [usingCustom, setUsingCustom] = useState<Set<number>>(new Set())\n const [submitted, setSubmitted] = useState(false)\n\n useEffect(() => {\n if (sessionStatus === \"failed\" || sessionStatus === \"interrupted\") {\n setSubmitted(false)\n }\n }, [sessionStatus])\n\n const displayAnswerState = useMemo(() => {\n if (!(answered && answerData)) {\n return {\n selections,\n customTexts,\n usingCustom,\n }\n }\n\n const nextSelections = new Map<number, Set<number>>()\n const nextCustomTexts = new Map<number, string>()\n const nextUsingCustom = new Set<number>()\n\n for (const [questionKey, optionIndexes] of Object.entries(answerData.selections)) {\n nextSelections.set(Number(questionKey), new Set(optionIndexes))\n }\n\n for (const [questionKey, text] of Object.entries(answerData.custom)) {\n const qIdx = Number(questionKey)\n nextCustomTexts.set(qIdx, text)\n nextUsingCustom.add(qIdx)\n }\n\n return {\n selections: nextSelections,\n customTexts: nextCustomTexts,\n usingCustom: nextUsingCustom,\n }\n }, [answerData, answered, customTexts, selections, usingCustom])\n\n const displaySelections = displayAnswerState.selections\n const displayCustomTexts = displayAnswerState.customTexts\n const displayUsingCustom = displayAnswerState.usingCustom\n\n const toggleOption = (qIdx: number, optIdx: number, multi: boolean) => {\n if (answered || submitted) return\n setSelections((prev) => {\n const next = new Map(prev)\n const current = new Set(next.get(qIdx) ?? [])\n if (multi) {\n if (current.has(optIdx)) current.delete(optIdx)\n else current.add(optIdx)\n } else {\n current.clear()\n current.add(optIdx)\n }\n next.set(qIdx, current)\n return next\n })\n // Clear custom for this question\n setUsingCustom((prev) => {\n const next = new Set(prev)\n next.delete(qIdx)\n return next\n })\n }\n\n const handleCustomFocus = (qIdx: number) => {\n if (answered || submitted) return\n setSelections((prev) => {\n const next = new Map(prev)\n next.delete(qIdx)\n return next\n })\n setUsingCustom((prev) => new Set(prev).add(qIdx))\n }\n\n const setCustomText = (qIdx: number, text: string) => {\n if (answered || submitted) return\n setCustomTexts((prev) => new Map(prev).set(qIdx, text))\n }\n\n const getAnswer = (qIdx: number): string | null => {\n const q = data.questions[qIdx]\n if (usingCustom.has(qIdx)) {\n const text = (customTexts.get(qIdx) ?? \"\").trim()\n return text || null\n }\n const sel = selections.get(qIdx)\n if (!sel || sel.size === 0) return null\n return [...sel]\n .sort()\n .map((i) => q.options[i].label)\n .join(\", \")\n }\n\n const allAnswered = data.questions.every((_, i) => getAnswer(i) !== null)\n\n const handleSubmit = () => {\n if (answered || submitted || !allAnswered || !onAnswer) return\n\n const nextAnswerData: AskUserAnswerData = {\n selections: Object.fromEntries(\n Array.from(selections.entries()).map(([qIdx, optionIndexes]) => [\n qIdx,\n Array.from(optionIndexes).sort((a, b) => a - b),\n ]),\n ) as Record<number, number[]>,\n custom: Object.fromEntries(\n Array.from(usingCustom)\n .map((qIdx) => [qIdx, (customTexts.get(qIdx) ?? \"\").trim()] as const)\n .filter(([, text]) => text.length > 0),\n ) as Record<number, string>,\n }\n\n const parts = data.questions.map((q, i) => `- ${q.question} -> ${getAnswer(i)}`)\n const text = `关于需要确认的问题,用户的回答如下:\\n${parts.join(\"\\n\")}`\n setSubmitted(true)\n onAnswer(text, toolCallId, nextAnswerData)\n }\n\n return (\n <div\n className={cn(\n \"ml-4 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))]\",\n answered\n ? \"max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80\"\n : \"max-w-lg space-y-5 p-4 text-sm\",\n )}\n >\n {data.source_loop?.description && (\n <div className=\"rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]\">\n 子智能体「{data.source_loop.description}」在等待你的回答\n </div>\n )}\n {data.questions.map((q, qIdx) => (\n <QuestionCard\n key={q.question}\n question={q}\n qIdx={qIdx}\n answered={answered}\n selected={displaySelections.get(qIdx) ?? new Set()}\n isCustom={displayUsingCustom.has(qIdx)}\n customText={displayCustomTexts.get(qIdx) ?? \"\"}\n onToggle={toggleOption}\n onCustomFocus={handleCustomFocus}\n onCustomChange={setCustomText}\n />\n ))}\n\n {!answered && !submitted && onAnswer && (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!allAnswered}\n className=\"w-full rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {allAnswered ? \"确认\" : \"请先选择一个选项\"}\n </button>\n )}\n\n {submitted && !answered && (\n <button\n type=\"button\"\n disabled\n className=\"flex w-full items-center justify-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] opacity-80\"\n >\n <Loader2 size={14} className=\"animate-spin\" />\n 确认中\n </button>\n )}\n </div>\n )\n}\n\nfunction QuestionCard({\n question,\n qIdx,\n answered,\n selected,\n isCustom,\n customText,\n onToggle,\n onCustomFocus,\n onCustomChange,\n}: {\n question: QuestionItem\n qIdx: number\n answered: boolean\n selected: Set<number>\n isCustom: boolean\n customText: string\n onToggle: (qIdx: number, optIdx: number, multi: boolean) => void\n onCustomFocus: (qIdx: number) => void\n onCustomChange: (qIdx: number, text: string) => void\n}) {\n const multi = question.multiSelect ?? false\n\n return (\n <div>\n <div className={cn(\"flex items-start gap-2\", answered ? \"mb-2\" : \"mb-3\")}>\n <MessageSquareMore\n size={answered ? 12 : 13}\n className=\"mt-0.5 shrink-0 text-[hsl(var(--primary))]\"\n />\n <div\n className={cn(\n \"min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]\",\n answered ? \"text-xs\" : \"text-sm\",\n )}\n >\n <MarkdownContent\n className={cn(\n \"prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_ol]:my-1 [&_p]:my-1 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1\",\n answered ? \"text-xs\" : \"text-sm\",\n )}\n controls={{ code: true }}\n >\n {question.question}\n </MarkdownContent>\n </div>\n </div>\n\n <div className={cn(\"flex flex-col pl-5\", answered ? \"gap-1\" : \"gap-1.5\")}>\n {question.options.map((opt, optIdx) => {\n const isSel = selected.has(optIdx)\n return (\n <button\n key={opt.label}\n type=\"button\"\n disabled={answered}\n onClick={() => onToggle(qIdx, optIdx, multi)}\n className={cn(\n \"flex items-start gap-2.5 rounded-lg border text-left transition-all\",\n answered ? \"px-2.5 py-1.5\" : \"px-3 py-2.5\",\n isSel && !answered\n ? \"border-[hsl(var(--primary)/0.8)] bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]\"\n : isSel\n ? \"border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.08)] text-[hsl(var(--foreground))]\"\n : \"border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.2)]\",\n !answered && !isSel && \"hover:border-[hsl(var(--ring)/0.4)] hover:bg-[hsl(var(--accent))]\",\n answered && \"cursor-default opacity-70\",\n )}\n >\n {multi && (\n <div\n className={cn(\n \"mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors\",\n isSel && !answered\n ? \"border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]\"\n : isSel\n ? \"border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]\"\n : \"border-[hsl(var(--border))]\",\n )}\n >\n {isSel && (\n <Check\n size={9}\n className={\n answered\n ? \"text-[hsl(var(--primary))]\"\n : \"text-[hsl(var(--primary-foreground))]\"\n }\n />\n )}\n </div>\n )}\n <div className=\"min-w-0\">\n <div className={cn(\"font-medium\", answered ? \"text-xs\" : \"text-[13px]\")}>\n {opt.label}\n </div>\n {opt.description && (\n <div\n className={cn(\n \"mt-0.5\",\n answered ? \"text-[11px]\" : \"text-xs\",\n isSel && !answered ? \"opacity-75\" : \"text-[hsl(var(--muted-foreground))]\",\n )}\n >\n {opt.description}\n </div>\n )}\n </div>\n </button>\n )\n })}\n\n {/* \"Other\" inline input */}\n {answered && !isCustom ? null : (\n <div\n className={cn(\n \"flex items-center gap-2 rounded-lg border transition-all\",\n answered ? \"px-2.5 py-1.5\" : \"px-3 py-2.5\",\n isCustom\n ? \"border-[hsl(var(--ring)/0.6)] bg-[hsl(var(--accent))]\"\n : \"border-[hsl(var(--border))] hover:border-[hsl(var(--ring)/0.3)] hover:bg-[hsl(var(--accent))]\",\n answered && \"cursor-default opacity-70\",\n )}\n >\n <span className=\"shrink-0 text-xs text-[hsl(var(--muted-foreground))]\">其他:</span>\n <input\n type=\"text\"\n value={customText}\n disabled={answered}\n onChange={(e) => onCustomChange(qIdx, e.target.value)}\n onFocus={() => onCustomFocus(qIdx)}\n aria-label=\"自定义回答\"\n placeholder=\"输入你的答案...\"\n className={cn(\n \"min-w-0 flex-1 bg-transparent text-[hsl(var(--foreground))] outline-none placeholder:text-[hsl(var(--muted-foreground)/0.5)]\",\n answered ? \"text-xs\" : \"text-sm\",\n )}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n\nexport function parseAskUserQuestion(\n toolResult: string | null | undefined,\n): AskUserQuestionData | null {\n if (!toolResult) return null\n try {\n const parsed = JSON.parse(toolResult)\n let questions = parsed?.questions\n // 容错:LLM 偶尔将 questions 输出为 JSON 字符串而非数组\n if (typeof questions === \"string\") {\n try {\n questions = JSON.parse(questions)\n } catch {\n return null\n }\n }\n if (Array.isArray(questions) && questions.every(isQuestionItem)) {\n return { ...parsed, questions } as AskUserQuestionData\n }\n } catch {\n // not JSON\n }\n return null\n}\n\nfunction isQuestionItem(value: unknown): value is QuestionItem {\n if (!value || typeof value !== \"object\") return false\n const question = (value as { question?: unknown }).question\n const options = (value as { options?: unknown }).options\n return typeof question === \"string\" && Array.isArray(options) && options.every(isOptionItem)\n}\n\nfunction isOptionItem(value: unknown): value is OptionItem {\n if (!value || typeof value !== \"object\") return false\n const option = value as { label?: unknown; description?: unknown }\n return typeof option.label === \"string\" && typeof option.description === \"string\"\n}\n","import { mermaid } from \"@streamdown/mermaid\"\nimport { Check, Copy, Download } from \"lucide-react\"\nimport {\n type ComponentProps,\n type ComponentPropsWithRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport { type ExtraProps, Streamdown } from \"streamdown\"\nimport { getAuthedUrl } from \"../../api/client\"\nimport { cn, copyToClipboard } from \"../../lib/utils\"\nimport { CardCodeBlock } from \"../card/CardCodeBlock\"\n\ntype StreamdownProps = ComponentProps<typeof Streamdown>\n\nconst STREAMDOWN_PLUGINS = { mermaid } satisfies NonNullable<StreamdownProps[\"plugins\"]>\n\nconst SYSTEM_REMINDER_TAG = \"system-reminder\"\nconst HIDDEN_SYSTEM_REMINDER_TAGS: NonNullable<StreamdownProps[\"allowedTags\"]> = {\n [SYSTEM_REMINDER_TAG]: [],\n}\nconst HIDDEN_SYSTEM_REMINDER_COMPONENTS = {\n [SYSTEM_REMINDER_TAG]: () => null,\n} as NonNullable<StreamdownProps[\"components\"]>\n\ntype PreProps = ComponentPropsWithRef<\"pre\"> & ExtraProps\n\nfunction CodeBlockPre({ children, node: _node, ...props }: PreProps) {\n const preRef = useRef<HTMLPreElement>(null)\n const [copied, setCopied] = useState(false)\n const [hasCodeNode, setHasCodeNode] = useState(false)\n\n useEffect(() => {\n setHasCodeNode(!!preRef.current?.querySelector(\"code\"))\n }, [])\n\n const getRawCode = () => preRef.current?.querySelector(\"code\")?.textContent ?? \"\"\n\n const handleCopy = async () => {\n const ok = await copyToClipboard(getRawCode())\n if (ok) {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n const handleDownload = () => {\n const codeEl = preRef.current?.querySelector(\"code\")\n const text = codeEl?.textContent ?? \"\"\n const ext = codeEl?.className.match(/language-(\\S+)/)?.[1] ?? \"txt\"\n const blob = new Blob([text], { type: \"text/plain\" })\n const url = URL.createObjectURL(blob)\n const a = document.createElement(\"a\")\n a.href = url\n a.download = `code.${ext}`\n a.click()\n URL.revokeObjectURL(url)\n }\n\n return (\n <div className=\"relative group\">\n <pre ref={preRef} {...props}>\n {children}\n </pre>\n {hasCodeNode && (\n <div className=\"absolute top-2 right-2 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] transition-colors\",\n copied\n ? \"text-[hsl(var(--primary))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]\",\n )}\n >\n {copied ? <Check size={12} /> : <Copy size={12} />}\n <span>{copied ? \"已复制\" : \"复制\"}</span>\n </button>\n <button\n type=\"button\"\n onClick={handleDownload}\n className=\"flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] transition-colors text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]\"\n >\n <Download size={12} />\n <span>下载</span>\n </button>\n </div>\n )}\n </div>\n )\n}\n\nfunction isExternalImageSrc(src: string): boolean {\n if (!src) return false\n if (src.startsWith(\"data:\") || src.startsWith(\"blob:\")) return true\n if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(src)) return true\n if (src.startsWith(\"/\")) return true\n return false\n}\n\nfunction decodeMarkdownPath(src: string): string {\n try {\n return decodeURIComponent(src)\n } catch {\n return src\n }\n}\n\nconst MARKDOWN_IMAGE_PATTERN =\n /!\\[((?:\\\\.|[^\\]\\\\])*)\\]\\(\\s*(?:<([^>\\n]+)>|([^\\s)]+))(\\s+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\)))?\\s*\\)/g\n\nfunction resolveSessionImageMarkdown(children: string, sessionId: string): string {\n return children.replace(\n MARKDOWN_IMAGE_PATTERN,\n (match, alt: string, angleSrc: string | undefined, plainSrc: string | undefined, title = \"\") => {\n const src = angleSrc ?? plainSrc\n if (!src || isExternalImageSrc(src)) {\n return match\n }\n\n const resolved = getAuthedUrl(\n `/api/sessions/${encodeURIComponent(sessionId)}/files/${encodeURIComponent(decodeMarkdownPath(src))}`,\n )\n return ``\n },\n )\n}\n\ntype MarkdownContentProps = StreamdownProps & {\n /** 当提供时,markdown 中相对路径的 <img> src 会解析为 session 工作区文件 URL */\n sessionId?: string\n}\n\nexport function MarkdownContent({\n allowedTags,\n children,\n components,\n mode,\n plugins,\n sessionId,\n ...props\n}: MarkdownContentProps) {\n const resolvedChildren = useMemo(\n () =>\n sessionId && typeof children === \"string\"\n ? resolveSessionImageMarkdown(children, sessionId)\n : children,\n [children, sessionId],\n )\n\n return (\n <Streamdown\n {...props}\n mode={mode ?? \"static\"}\n allowedTags={{\n ...(allowedTags ?? {}),\n ...HIDDEN_SYSTEM_REMINDER_TAGS,\n }}\n components={{\n code: CardCodeBlock,\n pre: CodeBlockPre,\n ...(components ?? {}),\n ...HIDDEN_SYSTEM_REMINDER_COMPONENTS,\n }}\n plugins={{\n ...STREAMDOWN_PLUGINS,\n ...(plugins ?? {}),\n }}\n >\n {resolvedChildren}\n </Streamdown>\n )\n}\n","import type { JSX } from \"react\"\nimport { useIsCodeFenceIncomplete } from \"streamdown\"\nimport type { ExtraProps } from \"streamdown\"\nimport { CardJSON } from \"../../lib/card-registry\"\nimport { normalizeCodeLanguage, useHighlightedCodeHtml } from \"../../lib/code-highlight\"\nimport { CardRenderer } from \"./CardRenderer\"\n\ntype CodeProps = JSX.IntrinsicElements[\"code\"] & ExtraProps\n\nexport function CardCodeBlock({ className, children, node, ...props }: CodeProps) {\n const isIncomplete = useIsCodeFenceIncomplete()\n const match = /language-(\\S+)/.exec(className || \"\")\n const lang = match?.[1]\n const isInline = !className\n const raw = String(children ?? \"\")\n const normalizedLang = normalizeCodeLanguage(lang)\n const { highlightedHtml } = useHighlightedCodeHtml(raw, normalizedLang)\n\n if (!isInline && CardJSON.isCardsLanguage(lang)) {\n return (\n <CardRenderer\n raw={raw}\n blockPosition={node?.position?.start?.line}\n isCodeFenceIncomplete={isIncomplete}\n />\n )\n }\n\n if (!isInline && highlightedHtml) {\n return (\n <code\n className={className}\n {...props}\n // biome-ignore lint/security/noDangerouslySetInnerHtml: syntax highlighting output is generated locally\n dangerouslySetInnerHTML={{ __html: highlightedHtml }}\n />\n )\n }\n\n return (\n <code className={className} {...props}>\n {children}\n </code>\n )\n}\n","import type { ComponentType } from \"react\"\n\nexport interface Card {\n type: string\n title?: string\n payload?: Record<string, unknown>\n data?: unknown\n id?: string\n}\n\nexport interface CardComponentProps {\n card: Card\n sendMessage?: (content: string) => Promise<void>\n sessionId?: string\n}\n\nexport type CardComponent = ComponentType<CardComponentProps>\n\nexport class CardComponentRegistry {\n private readonly components: Map<string, CardComponent>\n\n constructor(initial?: Record<string, CardComponent> | Map<string, CardComponent>) {\n if (initial instanceof Map) {\n this.components = new Map(initial)\n } else if (initial) {\n this.components = new Map(Object.entries(initial))\n } else {\n this.components = new Map()\n }\n }\n\n register(type: string, component: CardComponent): void {\n this.components.set(type, component)\n }\n\n get(type: string): CardComponent | undefined {\n return this.components.get(type)\n }\n\n has(type: string): boolean {\n return this.components.has(type)\n }\n\n keys(): string[] {\n return Array.from(this.components.keys())\n }\n\n clear(): void {\n this.components.clear()\n }\n\n get size(): number {\n return this.components.size\n }\n}\n\nexport const cardRegistry = new CardComponentRegistry()\n\nexport interface ParseResult<T> {\n ok: boolean\n value?: T\n error?: string\n}\n\nexport const CardJSON = {\n safeParseJSON<T = unknown>(text: string): ParseResult<T> {\n try {\n const value = JSON.parse(text) as T\n return { ok: true, value }\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : \"Unknown parsing error\",\n }\n }\n },\n\n toCardArray(value: unknown): Card[] | null {\n if (\n value &&\n typeof value === \"object\" &&\n \"type\" in (value as Record<string, unknown>) &&\n typeof (value as { type?: unknown }).type === \"string\"\n ) {\n return [value as Card]\n }\n\n if (Array.isArray(value)) {\n const cards = value.filter(\n (item): item is Card =>\n item &&\n typeof item === \"object\" &&\n \"type\" in (item as Record<string, unknown>) &&\n typeof (item as { type?: unknown }).type === \"string\",\n )\n return cards.length > 0 ? cards : null\n }\n\n return null\n },\n\n isCardsLanguage(lang?: string): boolean {\n return lang === \"card+json\"\n },\n}\n","import { useEffect, useMemo, useState } from \"react\"\n\nconst DARK_THEME = \"github-dark-default\"\nconst LIGHT_THEME = \"github-light-default\"\n\nconst SUPPORTED_LANGUAGES = [\n \"python\",\n \"javascript\",\n \"typescript\",\n \"tsx\",\n \"jsx\",\n \"yaml\",\n \"markdown\",\n \"bash\",\n \"json\",\n \"go\",\n \"rust\",\n \"css\",\n \"html\",\n] as const\n\nexport type SupportedCodeLanguage = (typeof SUPPORTED_LANGUAGES)[number]\n\nconst LANGUAGE_ALIASES: Record<string, SupportedCodeLanguage> = {\n bash: \"bash\",\n css: \"css\",\n go: \"go\",\n golang: \"go\",\n htm: \"html\",\n html: \"html\",\n javascript: \"javascript\",\n js: \"javascript\",\n json: \"json\",\n jsonc: \"json\",\n jsx: \"jsx\",\n markdown: \"markdown\",\n md: \"markdown\",\n py: \"python\",\n python: \"python\",\n rs: \"rust\",\n rust: \"rust\",\n scss: \"css\",\n sh: \"bash\",\n shell: \"bash\",\n ts: \"typescript\",\n tsx: \"tsx\",\n typescript: \"typescript\",\n yaml: \"yaml\",\n yml: \"yaml\",\n zsh: \"bash\",\n}\n\ntype CodeHighlighter = {\n codeToHtml: (\n code: string,\n options: {\n lang: SupportedCodeLanguage\n themes: { light: string; dark: string }\n defaultColor?: false\n },\n ) => string\n}\n\nlet highlighterPromise: Promise<CodeHighlighter> | null = null\n\nconst CACHE_MAX_SIZE = 200\nconst highlightCache = new Map<string, Promise<string | null>>()\n\nexport function normalizeCodeLanguage(language?: string | null): SupportedCodeLanguage | null {\n if (!language) return null\n\n return LANGUAGE_ALIASES[language.trim().toLowerCase()] ?? null\n}\n\nexport function useHighlightedCodeHtml(code: string, language?: string | null) {\n const normalizedLanguage = useMemo(() => normalizeCodeLanguage(language), [language])\n const [highlightedHtml, setHighlightedHtml] = useState<string | null>(null)\n\n useEffect(() => {\n let cancelled = false\n\n setHighlightedHtml(null)\n\n if (!normalizedLanguage) {\n return () => {\n cancelled = true\n }\n }\n\n void highlightCodeToInnerHtml(code, normalizedLanguage).then((result) => {\n if (!cancelled) {\n setHighlightedHtml(result)\n }\n })\n\n return () => {\n cancelled = true\n }\n }, [code, normalizedLanguage])\n\n return { highlightedHtml, language: normalizedLanguage }\n}\n\nasync function highlightCodeToInnerHtml(code: string, language: SupportedCodeLanguage) {\n const cacheKey = `${language}\\u0000${code}`\n const cached = highlightCache.get(cacheKey)\n\n if (cached) {\n return cached\n }\n\n const request = loadCodeHighlighter()\n .then((highlighter) => {\n const html = highlighter.codeToHtml(code, {\n lang: language,\n themes: { light: LIGHT_THEME, dark: DARK_THEME },\n defaultColor: false,\n })\n return extractInnerCodeHtml(html)\n })\n .catch(() => {\n highlightCache.delete(cacheKey)\n return null\n })\n\n if (highlightCache.size >= CACHE_MAX_SIZE) {\n const oldest = highlightCache.keys().next().value\n if (oldest !== undefined) highlightCache.delete(oldest)\n }\n highlightCache.set(cacheKey, request)\n return request\n}\n\nasync function loadCodeHighlighter(): Promise<CodeHighlighter> {\n if (!highlighterPromise) {\n highlighterPromise = Promise.all([\n import(\"shiki/core\"),\n import(\"shiki/engine/javascript\"),\n import(\"@shikijs/langs/bash\"),\n import(\"@shikijs/langs/css\"),\n import(\"@shikijs/langs/go\"),\n import(\"@shikijs/langs/html\"),\n import(\"@shikijs/langs/javascript\"),\n import(\"@shikijs/langs/json\"),\n import(\"@shikijs/langs/jsx\"),\n import(\"@shikijs/langs/markdown\"),\n import(\"@shikijs/langs/python\"),\n import(\"@shikijs/langs/rust\"),\n import(\"@shikijs/langs/tsx\"),\n import(\"@shikijs/langs/typescript\"),\n import(\"@shikijs/langs/yaml\"),\n import(\"@shikijs/themes/github-dark-default\"),\n import(\"@shikijs/themes/github-light-default\"),\n ]).then(\n ([\n core,\n engine,\n bash,\n css,\n go,\n html,\n javascript,\n json,\n jsx,\n markdown,\n python,\n rust,\n tsx,\n typescript,\n yaml,\n darkTheme,\n lightTheme,\n ]) =>\n core.createHighlighterCore({\n engine: engine.createJavaScriptRegexEngine(),\n langs: [\n bash.default,\n css.default,\n go.default,\n html.default,\n javascript.default,\n json.default,\n jsx.default,\n markdown.default,\n python.default,\n rust.default,\n tsx.default,\n typescript.default,\n yaml.default,\n ],\n themes: [darkTheme.default, lightTheme.default],\n }),\n ).catch((err) => {\n highlighterPromise = null\n throw err\n })\n }\n\n return highlighterPromise as Promise<CodeHighlighter>\n}\n\nfunction extractInnerCodeHtml(html: string) {\n const match = html.match(/<code[^>]*>([\\s\\S]*)<\\/code><\\/pre>\\s*$/)\n return match?.[1] ?? null\n}\n","import { Component, type ErrorInfo, type ReactNode } from \"react\"\nimport { type Card, CardJSON, cardRegistry } from \"../../lib/card-registry\"\nimport { useUiStore } from \"../../stores/ui-store\"\nimport { useCardContext } from \"./CardContext\"\nimport { CardErrorState, CardLoadingState, CardWarningState } from \"./CardStates\"\n\ninterface Props {\n raw: string\n blockPosition?: number\n isCodeFenceIncomplete?: boolean\n}\n\nfunction looksIncomplete(text: string): boolean {\n const t = text.trim()\n if (!t) return true\n const openBraces = (t.match(/{/g) || []).length\n const closeBraces = (t.match(/}/g) || []).length\n const openBrackets = (t.match(/\\[/g) || []).length\n const closeBrackets = (t.match(/]/g) || []).length\n const quotes = (t.match(/\"/g) || []).length\n\n return (\n (!t.endsWith(\"}\") && !t.endsWith(\"]\")) ||\n openBraces !== closeBraces ||\n openBrackets !== closeBrackets ||\n t.endsWith(\",\") ||\n t.endsWith(\":\") ||\n quotes % 2 !== 0\n )\n}\n\ninterface ErrorBoundaryProps {\n fallback: ReactNode\n children: ReactNode\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean\n}\n\nclass CardErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n state: ErrorBoundaryState = { hasError: false }\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { hasError: true }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo) {\n console.error(\"Card render error:\", error, info)\n }\n\n render() {\n if (this.state.hasError) return this.props.fallback\n return this.props.children\n }\n}\n\nfunction OpenInPreviewButton({ card }: { card: Card }) {\n const pushArtifact = useUiStore((s) => s.pushArtifact)\n\n return (\n <button\n type=\"button\"\n onClick={() =>\n pushArtifact({\n type: \"card\",\n content: JSON.stringify(card, null, 2),\n title: card.title || card.type,\n key: `card-${card.id}`,\n })\n }\n className=\"absolute right-2 top-2 rounded bg-[hsl(var(--accent))] px-1.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))] opacity-0 transition-opacity group-hover/card:opacity-100 hover:text-[hsl(var(--foreground))]\"\n >\n 预览\n </button>\n )\n}\n\nexport function CardRenderer({ raw, blockPosition, isCodeFenceIncomplete }: Props) {\n const { sessionId, messageId, sendMessage } = useCardContext()\n const trimmed = raw.trim()\n\n if (!trimmed) return <CardLoadingState content=\"\" />\n\n // If code fence is still streaming, show loading\n if (isCodeFenceIncomplete) {\n return <CardLoadingState content={trimmed} />\n }\n\n const parsed = CardJSON.safeParseJSON(trimmed)\n\n if (!parsed.ok) {\n if (looksIncomplete(trimmed)) {\n return <CardLoadingState content={trimmed} />\n }\n return <CardErrorState content={trimmed} message={parsed.error} />\n }\n\n const cards = CardJSON.toCardArray(parsed.value)\n if (!cards) {\n return <CardWarningState content={trimmed} message=\"JSON 格式正确但不符合卡片结构\" />\n }\n\n const cardsWithIds = cards.map((c, i) => {\n if (c.id) return c\n return {\n ...c,\n id: `${messageId || \"msg\"}-block-${blockPosition ?? 0}-card-${i}`,\n }\n })\n\n return (\n <>\n {cardsWithIds.map((card) => {\n const CardComponent = cardRegistry.get(card.type)\n if (!CardComponent) {\n return (\n <CardWarningState\n key={card.id}\n content={JSON.stringify(card, null, 2)}\n message={`未知的卡片类型: ${card.type}`}\n />\n )\n }\n return (\n <div key={card.id} className=\"group/card relative my-4\">\n <CardErrorBoundary\n fallback={\n <CardErrorState\n content={JSON.stringify(card, null, 2)}\n message=\"卡片渲染出错\"\n />\n }\n >\n <CardComponent card={card} sendMessage={sendMessage} sessionId={sessionId} />\n <OpenInPreviewButton card={card} />\n </CardErrorBoundary>\n </div>\n )\n })}\n </>\n )\n}\n","import { createContext, useContext } from \"react\"\n\nexport interface CardContextValue {\n sendMessage?: (content: string) => Promise<void>\n sessionId?: string\n messageId?: string\n}\n\nexport const CardContext = createContext<CardContextValue>({})\n\nexport const useCardContext = () => useContext(CardContext)\n","interface CardStateProps {\n content: string\n message?: string\n}\n\nexport function CardLoadingState({ content }: CardStateProps) {\n return (\n <div className=\"my-4 rounded-md border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--primary)/0.05)] p-4\">\n <div className=\"mb-2 flex items-center gap-2\">\n <div className=\"h-4 w-4 animate-spin rounded-full border-2 border-[hsl(var(--primary))] border-t-transparent\" />\n <p className=\"text-sm text-[hsl(var(--primary))]\">正在加载卡片数据...</p>\n </div>\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-[hsl(var(--primary)/0.7)]\">查看接收中的数据</summary>\n <pre className=\"mt-1 whitespace-pre-wrap rounded bg-[hsl(var(--primary)/0.1)] p-2 font-mono text-xs text-[hsl(var(--primary)/0.8)]\">\n {content}\n </pre>\n </details>\n </div>\n )\n}\n\nexport function CardErrorState({ content, message }: CardStateProps) {\n return (\n <div className=\"my-4 rounded-md border border-red-500/20 bg-red-500/5 p-4\">\n <p className=\"mb-2 text-sm text-red-400\">{message || \"卡片数据解析失败\"}</p>\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-red-400/70 hover:underline\">\n 查看原始代码块\n </summary>\n <pre className=\"mt-2 overflow-x-auto whitespace-pre-wrap rounded bg-red-500/10 p-3 font-mono text-xs text-red-400/80\">\n {content}\n </pre>\n </details>\n </div>\n )\n}\n\nexport function CardWarningState({ content, message }: CardStateProps) {\n return (\n <div className=\"my-4 rounded-md border border-yellow-500/20 bg-yellow-500/5 p-4\">\n <p className=\"mb-2 text-sm text-yellow-400\">{message || \"数据格式不符合卡片要求\"}</p>\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-yellow-400/70\">查看原始数据</summary>\n <pre className=\"mt-1 whitespace-pre-wrap rounded bg-yellow-500/10 p-2 font-mono text-xs text-yellow-400/80\">\n {content}\n </pre>\n </details>\n </div>\n )\n}\n","import { load } from \"js-yaml\"\nimport type { PlanNode } from \"./types\"\n\ninterface PlanStep {\n label: string\n skill?: string\n id?: string\n status?: string\n children?: PlanStep[]\n}\n\ninterface PlanDocument {\n title: string\n objective: string\n steps: PlanStep[]\n notes?: string[]\n}\n\ninterface ParsedPlanResult {\n plan: { root: PlanNode; notes: string[] } | null\n error: string | null\n}\n\nexport type PlanStatusMap = Record<string, PlanNode[\"status\"]>\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.trim().length > 0\n}\n\nfunction isPlanStep(value: unknown): value is PlanStep {\n if (!value || typeof value !== \"object\") return false\n const step = value as Record<string, unknown>\n if (!isNonEmptyString(step.label)) return false\n if (\"skill\" in step && step.skill !== undefined && !isNonEmptyString(step.skill)) return false\n if (\"children\" in step && !Array.isArray(step.children)) return false\n\n const children = Array.isArray(step.children) ? step.children : []\n if (children.length > 0 && !isNonEmptyString(step.skill)) return false\n return children.every((child) => isPlanStep(child))\n}\n\nfunction isPlanDocument(value: unknown): value is PlanDocument {\n if (!value || typeof value !== \"object\") return false\n const doc = value as Record<string, unknown>\n if (!isNonEmptyString(doc.title) || !isNonEmptyString(doc.objective)) return false\n if (!Array.isArray(doc.steps) || doc.steps.length === 0) return false\n if (!doc.steps.every((step) => isPlanStep(step))) return false\n if (\"notes\" in doc) {\n if (!Array.isArray(doc.notes)) return false\n if (!doc.notes.every((note) => isNonEmptyString(note))) return false\n }\n return true\n}\n\nfunction getPlanDocumentError(value: unknown): string {\n if (!value || typeof value !== \"object\") return \"PLAN.yaml 顶层结构必须是对象\"\n\n const doc = value as Record<string, unknown>\n if (!isNonEmptyString(doc.title)) return \"PLAN.yaml 缺少非空 title\"\n if (!isNonEmptyString(doc.objective)) return \"PLAN.yaml 缺少非空 objective\"\n if (!Array.isArray(doc.steps) || doc.steps.length === 0) return \"PLAN.yaml 缺少非空 steps\"\n if (!doc.steps.every((step) => isPlanStep(step))) {\n return \"PLAN.yaml 步骤结构无效,请检查 label / skill / children\"\n }\n if (\"notes\" in doc) {\n if (!Array.isArray(doc.notes) || !doc.notes.every((note) => isNonEmptyString(note))) {\n return \"PLAN.yaml notes 必须是非空字符串列表\"\n }\n }\n return \"PLAN.yaml 结构无效\"\n}\n\nfunction toPlanStatus(value: unknown): PlanNode[\"status\"] {\n if (!isNonEmptyString(value)) return \"pending\"\n const normalized = value.trim().toLowerCase()\n return normalized === \"pending\" || normalized === \"running\" || normalized === \"done\" || normalized === \"failed\"\n ? normalized\n : \"pending\"\n}\n\nexport function parsePlanTree(content: string): { root: PlanNode; notes: string[] } | null {\n return parsePlanTreeResult(content).plan\n}\n\nexport function applyPlanStatusesById(root: PlanNode, statuses: PlanStatusMap): PlanNode {\n const nextStatus = statuses[root.id] ?? root.status\n const children = Array.isArray(root.children) ? root.children : []\n return {\n ...root,\n status: nextStatus,\n children: children.map((child) => applyPlanStatusesById(child, statuses)),\n }\n}\n\nexport function parsePlanTreeResult(content: string): ParsedPlanResult {\n if (!content.trim()) {\n return { plan: null, error: null }\n }\n\n let parsed: unknown\n try {\n parsed = load(content)\n } catch (error) {\n return {\n plan: null,\n error: error instanceof Error ? `PLAN.yaml YAML 语法错误:${error.message}` : \"PLAN.yaml YAML 语法错误\",\n }\n }\n\n if (!isPlanDocument(parsed)) {\n return { plan: null, error: getPlanDocumentError(parsed) }\n }\n\n const createNode = (step: PlanStep, depth: number, fallbackId: string): PlanNode => {\n const children = Array.isArray(step.children) ? step.children : []\n return {\n id: isNonEmptyString(step.id) ? step.id.trim() : fallbackId,\n label: step.label.trim(),\n skillRef: isNonEmptyString(step.skill) ? step.skill.trim() : null,\n status: toPlanStatus(step.status),\n children: children.map((child, index) => createNode(child, depth + 1, `${fallbackId}.${index + 1}`)),\n depth,\n }\n }\n\n const root: PlanNode = {\n id: \"plan-root\",\n label: parsed.title.trim(),\n skillRef: null,\n status: \"pending\",\n children: parsed.steps.map((step, index) => createNode(step, 1, `${index + 1}`)),\n depth: 0,\n }\n\n const notes = [parsed.objective.trim(), ...(parsed.notes ?? []).map((note) => note.trim())]\n\n return { plan: { root, notes }, error: null }\n}\n","import type { ChatMessage } from \"../../schemas/message\"\nimport { parseAskUserQuestion } from \"../chat/AskUserQuestionBlock\"\nimport { applyPlanStatusesById, parsePlanTreeResult, type PlanStatusMap } from \"./parse-plan-tree\"\nimport type { PlanData, SkillInfo } from \"./types\"\n\nfunction resultAsString(result: unknown): string | null {\n if (typeof result === \"string\") return result\n return null\n}\n\nconst PAUSE_TOOLS = new Set([\"AskUserQuestion\", \"ExitPlanMode\"])\nconst READ_FILE_TOOLS = new Set([\"Read\"])\nconst PLAN_WRITE_TOOLS = new Set([\"Write\"])\nconst PLAN_EDIT_TOOLS = new Set([\"Edit\"])\n\nfunction getSkillId(payload: { skill_id?: string; name?: string } | null | undefined): string {\n if (!payload) {\n return \"\"\n }\n if (typeof payload.skill_id === \"string\" && payload.skill_id) {\n return payload.skill_id\n }\n if (typeof payload.name === \"string\" && payload.name) {\n return payload.name\n }\n return \"\"\n}\n\nfunction getSkillDisplayName(\n payload: { display_name?: string; skill_id?: string; name?: string } | null | undefined,\n): string | undefined {\n if (!payload || typeof payload.display_name !== \"string\") {\n return undefined\n }\n const displayName = payload.display_name.trim()\n if (!displayName) {\n return undefined\n }\n const skillId = getSkillId(payload)\n return displayName === skillId ? undefined : displayName\n}\n\nfunction parseModeChange(message: ChatMessage): { from: string; to: string } | null {\n if (message.kind !== \"mode_change\" || typeof message.content !== \"string\") {\n return null\n }\n try {\n const parsed = JSON.parse(message.content) as { from?: unknown; to?: unknown }\n if (typeof parsed.from === \"string\" && typeof parsed.to === \"string\") {\n return { from: parsed.from, to: parsed.to }\n }\n } catch {}\n return null\n}\n\nfunction isPlanningBoundaryMessage(message: ChatMessage): boolean {\n if (message.kind === \"planning_enter\" || message.kind === \"planning_exit\") {\n return true\n }\n const modeChange = parseModeChange(message)\n if (!modeChange) {\n return false\n }\n return modeChange.to === \"planning\" || modeChange.from === \"planning\"\n}\n\n/**\n * Extract structured plan data from planning phase messages.\n *\n * Expects messages between planning_enter/exit markers containing:\n * - search_skills tool calls (Phase 1)\n * - get_skill_content tool calls (Phase 2)\n * - Write tool call to PLAN.yaml with plan YAML (Phase 3)\n */\nexport function parsePlanMessages(allMessages: ChatMessage[]): PlanData {\n const messages = Array.isArray(allMessages) ? allMessages : []\n // Extract intent from the first search_skills query\n let intent = \"\"\n for (const msg of messages) {\n if (!msg.tool_calls) continue\n const searchTc = msg.tool_calls.find(\n (tc) => tc.name === \"search_skills\" || tc.name === \"SearchSkills\",\n )\n if (searchTc) {\n try {\n intent = JSON.parse(searchTc.arguments).query ?? \"\"\n } catch {}\n if (intent) break\n }\n }\n\n const plannerMsgs = messages.filter(\n (message) => !isPlanningBoundaryMessage(message),\n )\n const searchResults: SkillInfo[] = []\n const searchMap = new Map<string, SkillInfo>()\n const selectedSkills: SkillInfo[] = []\n const selectedSet = new Set<string>()\n const askQuestions: PlanData[\"askQuestions\"] = []\n const readFiles: PlanData[\"readFiles\"] = []\n let lastPauseTool: PlanData[\"lastPauseTool\"] = null\n let planContent = \"\"\n let planContentPriority = 0\n let latestStatuses: PlanStatusMap = {}\n\n const setPlanContent = (nextContent: unknown, priority: number) => {\n if (typeof nextContent !== \"string\" || !nextContent.trim()) {\n return\n }\n if (priority < planContentPriority) {\n return\n }\n planContent = nextContent\n planContentPriority = priority\n }\n\n const applyPlanEdit = (args: Record<string, unknown>) => {\n const oldString = typeof args.old_string === \"string\" ? args.old_string : \"\"\n const newString = typeof args.new_string === \"string\" ? args.new_string : \"\"\n if (!planContent || !oldString || !planContent.includes(oldString)) {\n return\n }\n planContent = planContent.replace(oldString, newString)\n }\n\n const maybeParsePlanStatus = (msg: ChatMessage) => {\n if (msg.kind !== \"plan_status\") return\n if (typeof msg.content !== \"string\" || !msg.content.trim()) return\n try {\n const data = JSON.parse(msg.content) as { plan_yaml?: unknown; statuses?: unknown }\n setPlanContent(data.plan_yaml, 3)\n if (data.statuses && typeof data.statuses === \"object\" && !Array.isArray(data.statuses)) {\n latestStatuses = Object.fromEntries(\n Object.entries(data.statuses)\n .filter((entry): entry is [string, string] => typeof entry[0] === \"string\" && typeof entry[1] === \"string\")\n .map(([stepId, status]) => [stepId, normalizePlanStatus(status)]),\n )\n }\n } catch {}\n }\n\n for (const msg of plannerMsgs) {\n maybeParsePlanStatus(msg)\n if (!msg.tool_calls) continue\n for (const tc of msg.tool_calls) {\n if ((tc.name === \"search_skills\" || tc.name === \"SearchSkills\") && resultAsString(tc.result)) {\n try {\n const parsed = JSON.parse(resultAsString(tc.result)!)\n const results: Array<{\n skill_id?: string\n name?: string\n display_name?: string\n description?: string\n }> =\n Array.isArray(parsed) ? parsed : Array.isArray(parsed?.results) ? parsed.results : []\n for (const r of results) {\n const skillId = getSkillId(r)\n if (!skillId || searchMap.has(skillId)) continue\n const skill: SkillInfo = {\n skillId,\n displayName: getSkillDisplayName(r),\n description: r.description ?? \"\",\n }\n searchMap.set(skillId, skill)\n searchResults.push(skill)\n }\n } catch {}\n }\n if (\n (tc.name === \"get_skill_content\" || tc.name === \"GetSkillContent\") &&\n resultAsString(tc.result)\n ) {\n try {\n const data = JSON.parse(resultAsString(tc.result)!) as {\n skill_id?: string\n name?: string\n display_name?: string\n description?: string\n content?: string\n }\n const skillId = getSkillId(data)\n if (!skillId || selectedSet.has(skillId)) continue\n let existing = searchMap.get(skillId)\n if (!existing) {\n // Skill fetched directly without prior search — auto-add to searchResults\n existing = {\n skillId,\n displayName: getSkillDisplayName(data),\n description: data.description ?? \"\",\n }\n searchMap.set(skillId, existing)\n searchResults.push(existing)\n }\n existing.displayName ??= getSkillDisplayName(data)\n existing.content = data.content\n existing.references = extractRefs(data.content ?? \"\")\n selectedSkills.push(existing)\n selectedSet.add(skillId)\n } catch {}\n }\n if (tc.name === \"AskUserQuestion\" && resultAsString(tc.result)) {\n const data = parseAskUserQuestion(resultAsString(tc.result))\n if (data) {\n askQuestions.push({ toolCallId: tc.id, data })\n }\n }\n if (READ_FILE_TOOLS.has(tc.name) && tc.arguments) {\n try {\n const args = JSON.parse(tc.arguments)\n if (typeof args.file_path === \"string\" && args.file_path) {\n readFiles.push({ path: args.file_path, status: tc.status ?? \"done\" })\n }\n } catch {}\n }\n if (\n PLAN_WRITE_TOOLS.has(tc.name) &&\n tc.arguments &&\n tc.status === \"done\" &&\n !(typeof tc.result === \"string\" && tc.result.startsWith(\"错误\"))\n ) {\n try {\n const args = JSON.parse(tc.arguments) as {\n file_path?: unknown\n content?: unknown\n }\n if (\n typeof args.file_path === \"string\" &&\n (args.file_path === \"PLAN.yaml\" || args.file_path.endsWith(\"/PLAN.yaml\")) &&\n typeof args.content === \"string\"\n ) {\n setPlanContent(args.content, 1)\n }\n } catch {}\n }\n if (\n PLAN_EDIT_TOOLS.has(tc.name) &&\n tc.arguments &&\n tc.status === \"done\" &&\n !(typeof tc.result === \"string\" && tc.result.startsWith(\"错误\"))\n ) {\n try {\n const args = JSON.parse(tc.arguments) as {\n file_path?: unknown\n old_string?: unknown\n new_string?: unknown\n }\n if (\n typeof args.file_path === \"string\" &&\n (args.file_path === \"PLAN.yaml\" || args.file_path.endsWith(\"/PLAN.yaml\"))\n ) {\n applyPlanEdit(args as Record<string, unknown>)\n }\n } catch {}\n }\n // Track the last pause-triggering tool across the whole phase.\n // Multi-round planning produces multiple pauses (e.g. AskUserQuestion\n // then ExitPlanMode); the UI needs the most recent one.\n if (PAUSE_TOOLS.has(tc.name) && tc.status === \"done\") {\n lastPauseTool = tc.name as PlanData[\"lastPauseTool\"]\n }\n if (tc.name === \"ExitPlanMode\" && resultAsString(tc.result)) {\n try {\n const data = JSON.parse(resultAsString(tc.result)!) as { plan?: unknown }\n setPlanContent(data.plan, 2)\n } catch {}\n }\n }\n }\n\n const { plan: parsedPlan, error: parseError } = parsePlanTreeResult(planContent)\n const plan =\n parsedPlan == null\n ? null\n : {\n ...parsedPlan,\n root: applyPlanStatusesById(parsedPlan.root, latestStatuses),\n }\n\n return {\n intent,\n searchResults,\n selectedSkills,\n plan,\n hasPlanContent: planContent.trim().length > 0,\n parseError,\n askQuestions,\n readFiles,\n lastPauseTool,\n }\n}\n\nfunction normalizePlanStatus(value: string): \"pending\" | \"running\" | \"done\" | \"failed\" {\n const normalized = value.trim().toLowerCase()\n return normalized === \"running\" || normalized === \"done\" || normalized === \"failed\"\n ? normalized\n : \"pending\"\n}\n\nfunction extractRefs(content: string): string[] {\n const seen = new Set<string>()\n const refs: string[] = []\n for (const m of content.matchAll(/\\[\\[([^\\]]+)\\]\\]/g)) {\n const ref = m[1].trim()\n if (ref && !seen.has(ref)) {\n seen.add(ref)\n refs.push(ref)\n }\n }\n return refs\n}\n","import type { ChatMessage } from \"../../schemas/message\"\n\nfunction parseModeChange(message: ChatMessage): { from: string; to: string } | null {\n if (message.kind !== \"mode_change\" || typeof message.content !== \"string\") {\n return null\n }\n try {\n const parsed = JSON.parse(message.content) as { from?: unknown; to?: unknown }\n if (typeof parsed.from === \"string\" && typeof parsed.to === \"string\") {\n return { from: parsed.from, to: parsed.to }\n }\n } catch {}\n return null\n}\n\nfunction isPlanningEnter(message: ChatMessage): boolean {\n if (message.kind === \"planning_enter\") {\n return true\n }\n const modeChange = parseModeChange(message)\n return modeChange?.to === \"planning\"\n}\n\nfunction isPlanningExit(message: ChatMessage): boolean {\n if (message.kind === \"planning_exit\") {\n return true\n }\n const modeChange = parseModeChange(message)\n return modeChange?.from === \"planning\"\n}\n\nexport function extractLatestPlanMessages(messages: ChatMessage[]): ChatMessage[] {\n const safeMessages = Array.isArray(messages) ? messages : []\n let enterIndex = -1\n let exitIndex = -1\n\n for (let i = safeMessages.length - 1; i >= 0; i -= 1) {\n const message = safeMessages[i]\n if (isPlanningExit(message) && exitIndex === -1) {\n exitIndex = i\n continue\n }\n if (isPlanningEnter(message)) {\n enterIndex = i\n break\n }\n }\n\n if (enterIndex === -1) {\n return []\n }\n\n return safeMessages\n .slice(enterIndex + 1)\n .filter((message, offset) => {\n const absoluteIndex = enterIndex + 1 + offset\n if (isPlanningEnter(message) || isPlanningExit(message)) {\n return false\n }\n if (exitIndex !== -1 && absoluteIndex > exitIndex) {\n return message.kind === \"plan_status\"\n }\n return true\n })\n}\n","import { AlertCircle, BookOpen, Check, ChevronRight } from \"lucide-react\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { getSocket } from \"../../api/socket\"\nimport { getFileParts, getImageParts } from \"../../lib/chat\"\nimport { isUiMeta } from \"../../lib/ui-meta\"\nimport { cn } from \"../../lib/utils\"\nimport { MEMORIES_ROUTE } from \"../../routes\"\nimport type { ChatMessage, MemoryRefInfo, ToolCallInfo } from \"../../schemas/message\"\nimport { useChatStore } from \"../../stores/chat-store\"\nimport {\n Reasoning,\n ReasoningContent,\n ReasoningTrigger,\n ThinkingBadge,\n} from \"../ai-elements/reasoning\"\nimport { CardContext, type CardContextValue } from \"../card/CardContext\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\nimport { AgentLoopBlock } from \"./AgentLoopBlock\"\nimport type { AskUserAnswerData } from \"./AskUserQuestionBlock\"\nimport { MessageFileAttachmentList } from \"./MessageFileAttachmentList\"\nimport { ResourceIframe } from \"./ResourceIframe\"\nimport { ToolCallBlock } from \"./ToolCallBlock\"\nimport {\n extractToolFilePath,\n formatToolName,\n} from \"./display-utils\"\n\ninterface Props {\n turnKey: string\n sessionId: string\n messages: ChatMessage[]\n isStreaming?: boolean\n isLastTurn?: boolean\n askAnswers?: Record<string, AskUserAnswerData>\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n sessionStatus?: string\n level?: 1 | 2\n forceExpanded?: boolean\n}\n\nfunction getMessageText(message: ChatMessage) {\n return typeof message.content === \"string\"\n ? message.content.trim()\n : message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n .trim()\n}\n\nfunction getLastTextMessage(messages: ChatMessage[]) {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (getMessageText(messages[index])) {\n return messages[index]\n }\n }\n return null\n}\n\nfunction getInlineResourceBlocks(messages: ChatMessage[]) {\n return messages.flatMap((message) =>\n (message.blocks ?? []).flatMap((block, index) =>\n block.type === \"tool_ui\" &&\n block.tool_call_id &&\n isUiMeta(block.content) &&\n block.content.target === \"inline\"\n ? [\n {\n key: `${message.entry_id ?? message.timestamp ?? \"message\"}-${block.tool_call_id}-${index}`,\n ui: block.content,\n },\n ]\n : [],\n ),\n )\n}\n\ntype ToolRenderItem =\n | { key: string; kind: \"single\"; toolCall: ToolCallInfo }\n | { key: string; kind: \"read_group\"; toolCalls: ToolCallInfo[] }\n | { key: string; kind: \"load_skill_group\"; toolCalls: ToolCallInfo[] }\n\nfunction groupDetailedToolCalls(toolCalls: ToolCallInfo[]): ToolRenderItem[] {\n const items: ToolRenderItem[] = []\n let index = 0\n\n while (index < toolCalls.length) {\n const toolCall = toolCalls[index]\n const normalizedName = formatToolName(toolCall.name)\n if (normalizedName !== \"Read\" && normalizedName !== \"LoadSkillTools\") {\n items.push({ key: toolCall.id, kind: \"single\", toolCall })\n index += 1\n continue\n }\n\n const group = [toolCall]\n index += 1\n while (index < toolCalls.length && formatToolName(toolCalls[index].name) === normalizedName) {\n group.push(toolCalls[index])\n index += 1\n }\n\n const kind = normalizedName === \"Read\" ? \"read_group\" : \"load_skill_group\"\n items.push(\n group.length === 1 && normalizedName === \"Read\"\n ? { key: group[0].id, kind: \"single\", toolCall: group[0] }\n : {\n key: `${kind}-${group.map((item) => item.id).join(\"-\")}`,\n kind,\n toolCalls: group,\n },\n )\n }\n\n return items\n}\n\nfunction formatToolDuration(durationMs: number) {\n if (durationMs < 1000) return `${Math.round(durationMs)}ms`\n const seconds = durationMs / 1000\n if (seconds < 60) return `${seconds.toFixed(seconds >= 10 ? 0 : 1)}s`\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = Math.round(seconds % 60)\n return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`\n}\n\nfunction formatFileName(filePath: string) {\n return filePath.split(\"/\").pop() ?? filePath\n}\n\nfunction parseToolArguments(value: string | null | undefined): Record<string, unknown> | null {\n if (!value) return null\n try {\n const parsed = JSON.parse(value)\n return typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : null\n } catch {\n return null\n }\n}\n\nfunction getLoadedSkillName(toolCall: ToolCallInfo) {\n const args = parseToolArguments(toolCall.arguments)\n const skillId = typeof args?.skill_id === \"string\" ? args.skill_id.trim() : \"\"\n if (skillId) return skillId\n const skillName = typeof args?.skill_name === \"string\" ? args.skill_name.trim() : \"\"\n return skillName || \"未知技能\"\n}\n\nfunction getAgentToolCallIds(messages: ChatMessage[]) {\n return new Set(\n messages\n .flatMap((message) => message.tool_calls ?? [])\n .filter((toolCall) => formatToolName(toolCall.name) === \"Agent\")\n .map((toolCall) => toolCall.id),\n )\n}\n\nfunction collectTurnMessages({\n rootMessages,\n sessionMessages,\n agentLoops,\n}: {\n rootMessages: ChatMessage[]\n sessionMessages: ChatMessage[]\n agentLoops: Record<string, { toolCallId: string }>\n}) {\n const collectedLoopNames = new Set<string>()\n const visitedToolCallIds = new Set<string>()\n let pendingToolCallIds = [...getAgentToolCallIds(rootMessages)]\n\n while (pendingToolCallIds.length > 0) {\n const currentIds = pendingToolCallIds\n pendingToolCallIds = []\n\n for (const [loopName, info] of Object.entries(agentLoops)) {\n if (collectedLoopNames.has(loopName) || visitedToolCallIds.has(info.toolCallId)) {\n continue\n }\n if (!currentIds.includes(info.toolCallId)) {\n continue\n }\n visitedToolCallIds.add(info.toolCallId)\n collectedLoopNames.add(loopName)\n const childMessages = sessionMessages.filter((message) => message.loop_name === loopName)\n pendingToolCallIds.push(...getAgentToolCallIds(childMessages))\n }\n }\n\n if (collectedLoopNames.size === 0) {\n return rootMessages\n }\n\n const rootIds = new Set(rootMessages.map((message) => message.entry_id).filter(Boolean))\n const childMessages = sessionMessages.filter(\n (message) =>\n message.loop_name &&\n collectedLoopNames.has(message.loop_name) &&\n (!message.entry_id || !rootIds.has(message.entry_id)),\n )\n const merged = [...rootMessages, ...childMessages]\n merged.sort((a, b) => {\n const ta = a.timestamp ?? \"\"\n const tb = b.timestamp ?? \"\"\n return ta < tb ? -1 : ta > tb ? 1 : 0\n })\n return merged\n}\n\nexport function AssistantTurnBlock({\n sessionId,\n messages: rawMessages,\n isStreaming = false,\n askAnswers,\n onAnswer,\n sessionStatus,\n level = 1,\n forceExpanded = false,\n}: Props) {\n const messages = Array.isArray(rawMessages) ? rawMessages : []\n const allToolCalls = useMemo(() => messages.flatMap((m) => m.tool_calls ?? []), [messages])\n const hasActionableToolCall = useMemo(\n () =>\n allToolCalls.some(\n (tc) =>\n tc.status === \"error\" ||\n tc.status === \"cancelled\" ||\n (formatToolName(tc.name) === \"AskUserQuestion\" && tc.status === \"awaiting_answer\"),\n ),\n [allToolCalls],\n )\n const [displayMode, setDisplayMode] = useState<\"compact\" | \"detail\">(\n forceExpanded ? \"detail\" : \"compact\",\n )\n const wasStreamingRef = useRef(isStreaming)\n useEffect(() => {\n if (wasStreamingRef.current && !isStreaming && !forceExpanded) {\n setDisplayMode(\"compact\")\n }\n wasStreamingRef.current = isStreaming\n }, [forceExpanded, isStreaming])\n\n const sessionMessages = useChatStore((state) => state.messages[sessionId] ?? [])\n const agentLoops = useChatStore((state) => state.agentLoops[sessionId] ?? {})\n const turnMessages = useMemo(\n () => collectTurnMessages({ rootMessages: messages, sessionMessages, agentLoops }),\n [agentLoops, messages, sessionMessages],\n )\n const resourceBlocks = useMemo(() => getInlineResourceBlocks(turnMessages), [turnMessages])\n const finalMessage = useMemo(() => getLastTextMessage(turnMessages), [turnMessages])\n const hasInterruptedState = messages.some((message) => message.status === \"interrupted\")\n const effectiveMode = isStreaming\n ? \"detail\"\n : displayMode === \"compact\" && hasActionableToolCall\n ? \"detail\"\n : displayMode\n\n const memoryRefs = Array.isArray(messages[0]?.memory_refs) ? messages[0].memory_refs : []\n\n return (\n <div className={cn(\"flex flex-col gap-3\", level === 2 && \"gap-2.5\")}>\n {memoryRefs.length > 0 && (\n <MemoryRefsHint refs={memoryRefs} />\n )}\n {hasInterruptedState && (\n <div className=\"ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300\">\n 已中断\n </div>\n )}\n {!isStreaming && (\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n onClick={() => setDisplayMode(displayMode === \"detail\" ? \"compact\" : \"detail\")}\n className=\"inline-flex shrink-0 items-center gap-1 text-xs text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]\"\n >\n <span>{effectiveMode === \"detail\" ? \"精简\" : \"详细\"}</span>\n <ChevronRight\n size={18}\n className={cn(\"transition-transform\", effectiveMode === \"detail\" && \"rotate-180\")}\n />\n </button>\n </div>\n )}\n {effectiveMode === \"detail\" ? (\n <div className=\"flex flex-col gap-3\">\n <AssistantMessages\n messages={messages}\n isStreaming={isStreaming}\n sessionId={sessionId}\n askAnswers={askAnswers}\n onAnswer={onAnswer}\n sessionStatus={sessionStatus}\n level={level}\n showToolDetails\n />\n </div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-4\">\n {resourceBlocks.length > 0 ? (\n <div className=\"flex flex-col gap-3\">\n {resourceBlocks.map((block) => (\n <ResourceIframe key={block.key} ui={block.ui} sessionId={sessionId} />\n ))}\n </div>\n ) : null}\n\n {finalMessage ? (\n <div\n className={cn(\n resourceBlocks.length > 0 && \"border-t border-[hsl(var(--border))] pt-4\",\n )}\n >\n <AssistantMessageContent\n message={finalMessage}\n isStreaming={isStreaming && finalMessage === messages[messages.length - 1]}\n sessionId={sessionId}\n reasoning={finalMessage.reasoning}\n />\n </div>\n ) : isStreaming ? (\n <span className=\"text-sm text-[hsl(var(--muted-foreground))]\">正在生成...</span>\n ) : null}\n </div>\n </div>\n )}\n </div>\n )\n}\n\nfunction AssistantMessages({\n messages,\n isStreaming,\n sessionId,\n askAnswers,\n onAnswer,\n sessionStatus,\n level,\n showToolDetails,\n}: {\n messages: ChatMessage[]\n isStreaming: boolean\n sessionId: string\n askAnswers?: Record<string, AskUserAnswerData>\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n sessionStatus?: string\n level: 1 | 2\n showToolDetails: boolean\n}) {\n return messages.map((message, index) =>\n isRenderableAssistantMessage(message, isStreaming && index === messages.length - 1)\n ? (() => {\n const isStreamingLastMessage = isStreaming && index === messages.length - 1\n const hasText = !!getMessageText(message)\n const reasoning = message.reasoning\n const hasReasoning = !!reasoning\n const hasAttachments =\n getImageParts(message.content).length > 0 || getFileParts(message.content).length > 0\n const toolCalls = message.tool_calls ?? []\n const hasToolCalls = toolCalls.length > 0\n const firstToolCallId = toolCalls[0]?.id\n const toolRenderItems = groupDetailedToolCalls(toolCalls)\n const toolReasoning =\n hasReasoning && !hasText && !hasAttachments && hasToolCalls && !isStreamingLastMessage\n ? reasoning\n : undefined\n const contentReasoning =\n hasReasoning && !isStreamingLastMessage && (hasText || hasAttachments || !hasToolCalls)\n ? reasoning\n : undefined\n\n return (\n <div\n key={message.entry_id ?? `${message.timestamp ?? \"assistant\"}-${index}`}\n className=\"flex flex-col gap-3\"\n >\n {hasReasoning && isStreamingLastMessage && (\n <Reasoning isStreaming={isStreamingLastMessage}>\n <ReasoningTrigger />\n <ReasoningContent>{reasoning}</ReasoningContent>\n </Reasoning>\n )}\n <AssistantMessageContent\n message={message}\n isStreaming={isStreamingLastMessage}\n sessionId={sessionId}\n reasoning={contentReasoning}\n />\n\n {hasToolCalls && showToolDetails && (\n <div className=\"flex flex-col gap-2\">\n {toolRenderItems.map((item) => {\n if (item.kind === \"read_group\" || item.kind === \"load_skill_group\") {\n return (\n <CompactToolGroupBlock\n key={item.key}\n toolCalls={item.toolCalls}\n kind={item.kind}\n reasoning={\n item.toolCalls[0]?.id === firstToolCallId ? toolReasoning : undefined\n }\n sessionId={sessionId}\n sessionStatus={sessionStatus}\n askAnswers={askAnswers}\n onAnswer={onAnswer}\n turnBlocks={message.blocks}\n level={level}\n />\n )\n }\n\n const { toolCall } = item\n return formatToolName(toolCall.name) === \"Agent\" ? (\n <AgentLoopBlock\n key={toolCall.id}\n toolCall={toolCall}\n sessionId={sessionId}\n reasoning={toolCall.id === firstToolCallId ? toolReasoning : undefined}\n />\n ) : (\n <ToolCallBlock\n key={toolCall.id}\n toolCall={toolCall}\n answerData={askAnswers?.[toolCall.id]}\n onAnswer={onAnswer}\n answered={sessionStatus !== \"waiting_for_input\"}\n sessionId={sessionId}\n sessionStatus={sessionStatus}\n level={level}\n turnBlocks={message.blocks}\n reasoning={toolCall.id === firstToolCallId ? toolReasoning : undefined}\n />\n )\n })}\n </div>\n )}\n {showToolDetails && message.blocks?.some((block) => block.type === \"tool_ui\") ? (\n <div className=\"flex flex-col gap-2\">\n {message.blocks.map((block, blockIndex) =>\n block.type === \"tool_ui\" &&\n block.tool_call_id &&\n isUiMeta(block.content) &&\n block.content.target === \"inline\" ? (\n <div key={`${block.tool_call_id}-${blockIndex}`} className=\"ml-4\">\n <ResourceIframe ui={block.content} sessionId={sessionId} />\n </div>\n ) : null,\n )}\n </div>\n ) : null}\n </div>\n )\n })()\n : null,\n )\n}\n\nfunction isRenderableAssistantMessage(message: ChatMessage, isStreaming: boolean) {\n if (message.reasoning || (message.tool_calls?.length ?? 0) > 0) {\n return true\n }\n\n const fileParts = getFileParts(message.content)\n const imageParts = getImageParts(message.content)\n const text = getMessageText(message)\n\n if (text || imageParts.length > 0 || fileParts.length > 0 || isStreaming) {\n return true\n }\n\n return (\n message.blocks?.some(\n (block) =>\n block.type === \"tool_ui\" &&\n block.tool_call_id &&\n isUiMeta(block.content) &&\n block.content.target === \"inline\",\n ) ?? false\n )\n}\n\nfunction CompactToolGroupBlock({\n toolCalls,\n kind,\n reasoning,\n sessionId,\n sessionStatus,\n askAnswers,\n onAnswer,\n turnBlocks,\n level,\n}: {\n toolCalls: ToolCallInfo[]\n kind: \"read_group\" | \"load_skill_group\"\n reasoning?: string\n sessionId: string\n sessionStatus?: string\n askAnswers?: Record<string, AskUserAnswerData>\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n turnBlocks?: NonNullable<ChatMessage[\"blocks\"]>\n level: 1 | 2\n}) {\n const [expanded, setExpanded] = useState(false)\n const indentClass = level === 2 ? \"ml-3\" : \"ml-4\"\n const hasError = toolCalls.some(\n (tc) => tc.status === \"error\" || tc.status === \"cancelled\",\n )\n const totalDurationMs = toolCalls.reduce(\n (total, toolCall) =>\n total + (typeof toolCall.duration_ms === \"number\" && toolCall.duration_ms > 0 ? toolCall.duration_ms : 0),\n 0,\n )\n const fileNames = toolCalls.map((toolCall) => {\n const filePath = extractToolFilePath(toolCall)\n return filePath ? formatFileName(filePath) : \"未知文件\"\n })\n const tags = kind === \"read_group\" ? fileNames : toolCalls.map(getLoadedSkillName)\n const title =\n kind === \"read_group\"\n ? `读取 ${toolCalls.length} 个文件`\n : toolCalls.length > 1\n ? `加载 ${toolCalls.length} 个技能`\n : \"加载技能\"\n\n return (\n <div className={cn(indentClass, \"text-xs\")}>\n <div className={cn(\n \"flex items-center gap-2 border-l-[3px] px-3 py-2\",\n hasError ? \"border-l-[hsl(var(--destructive))]\" : \"border-l-[hsl(var(--primary))]\",\n )}>\n <button\n type=\"button\"\n onClick={() => setExpanded((value) => !value)}\n className=\"flex min-w-0 shrink-0 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n aria-expanded={expanded}\n >\n <ChevronRight\n size={11}\n className={cn(\n \"shrink-0 text-[hsl(var(--muted-foreground))] transition-transform\",\n expanded && \"rotate-90\",\n )}\n />\n {hasError ? (\n <span className=\"flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--destructive))]\">\n <AlertCircle size={11} />\n <span>失败</span>\n </span>\n ) : (\n <span className=\"flex shrink-0 items-center gap-1 text-[10px] text-[hsl(var(--primary))]\">\n <Check size={11} />\n <span>完成</span>\n </span>\n )}\n <span className=\"min-w-0 shrink-0 font-medium text-[hsl(var(--foreground))]\">\n {title}\n </span>\n </button>\n <div className=\"flex min-w-0 flex-1 flex-wrap gap-1.5\">\n {tags.map((tag, index) => (\n <span\n key={`${tag}-${index}`}\n className=\"max-w-40 truncate rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.35)] px-1.5 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]\"\n title={tag}\n >\n {tag}\n </span>\n ))}\n </div>\n {reasoning ? <ThinkingBadge reasoning={reasoning} variant=\"block\" /> : null}\n {totalDurationMs > 0 ? (\n <span className=\"shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {formatToolDuration(totalDurationMs)}\n </span>\n ) : null}\n </div>\n {expanded ? (\n <div className=\"mt-1 flex flex-col gap-1\">\n {toolCalls.map((toolCall) => (\n <ToolCallBlock\n key={toolCall.id}\n toolCall={toolCall}\n answerData={askAnswers?.[toolCall.id]}\n onAnswer={onAnswer}\n answered={sessionStatus !== \"waiting_for_input\"}\n sessionId={sessionId}\n sessionStatus={sessionStatus}\n level={level}\n turnBlocks={turnBlocks}\n />\n ))}\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction AssistantMessageContent({\n message,\n isStreaming,\n sessionId,\n reasoning,\n}: {\n message: ChatMessage\n isStreaming: boolean\n sessionId: string\n reasoning?: string\n}) {\n const fileParts = getFileParts(message.content)\n const imageParts = getImageParts(message.content)\n const text =\n typeof message.content === \"string\"\n ? message.content.trim()\n : message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n .trim()\n\n if (!text && imageParts.length === 0 && fileParts.length === 0 && !isStreaming && !reasoning) {\n return null\n }\n\n return (\n <div className=\"flex flex-col gap-3\">\n {imageParts.length > 0 && (\n <div className=\"grid gap-2\">\n {imageParts.map((part) => (\n <img\n key={part.image_url.url}\n src={part.image_url.url}\n alt=\"消息附件\"\n className=\"max-h-72 rounded-xl border border-[hsl(var(--border))] object-cover\"\n />\n ))}\n </div>\n )}\n <MessageFileAttachmentList files={fileParts} />\n {text ? (\n <AssistantText\n text={text}\n sessionId={sessionId}\n messageId={message.entry_id}\n reasoning={reasoning}\n />\n ) : null}\n {!text && isStreaming && (\n <span className=\"text-sm text-[hsl(var(--muted-foreground))]\">正在生成...</span>\n )}\n {!text && reasoning ? <ThinkingBadge reasoning={reasoning} variant=\"block\" /> : null}\n </div>\n )\n}\n\nfunction AssistantText({\n text,\n sessionId,\n messageId,\n reasoning,\n}: {\n text: string\n sessionId: string\n messageId?: string\n reasoning?: string\n}) {\n const sendMessage = useCallback(\n async (content: string) => {\n getSocket().send(sessionId, content)\n },\n [sessionId],\n )\n\n const cardCtx = useMemo<CardContextValue>(\n () => ({ sessionId, messageId, sendMessage }),\n [sessionId, messageId, sendMessage],\n )\n\n return (\n <div className=\"text-[15px] leading-8 text-[hsl(var(--foreground))]\">\n <CardContext.Provider value={cardCtx}>\n <MarkdownContent\n mode=\"streaming\"\n sessionId={sessionId}\n className=\"prose prose-sm prose-invert inline max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0 [&_p:last-child]:inline\"\n controls={{ code: true }}\n >\n {text}\n </MarkdownContent>\n </CardContext.Provider>\n {reasoning ? <ThinkingBadge reasoning={reasoning} /> : null}\n </div>\n )\n}\n\nfunction MemoryRefsHint({ refs: rawRefs }: { refs: MemoryRefInfo[] }) {\n const refs = Array.isArray(rawRefs) ? rawRefs : []\n const [expanded, setExpanded] = useState(false)\n const hasSkill = refs.some((r) => r.skill_name)\n const label = hasSkill ? \"参考了该技能的历史经验\" : \"参考了历史经验\"\n\n return (\n <div className=\"ml-4\">\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-[hsl(var(--primary)/0.25)] bg-[hsl(var(--primary)/0.08)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary))] transition-colors hover:bg-[hsl(var(--primary)/0.12)]\"\n >\n <BookOpen size={12} />\n <span>{label}({refs.length})</span>\n <ChevronRight\n size={10}\n className={cn(\"transition-transform\", expanded && \"rotate-90\")}\n />\n </button>\n {expanded && (\n <div className=\"mt-1.5 flex flex-col gap-1 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.45)] px-3 py-2\">\n {refs.map((ref) => (\n <div key={ref.id} className=\"flex items-start gap-2 text-[11px] text-[hsl(var(--foreground)/0.82)]\">\n <span className=\"mt-0.5 shrink-0 text-[hsl(var(--primary)/0.75)]\">•</span>\n <span className=\"line-clamp-1\">{ref.content_preview}</span>\n {ref.skill_name && (\n <span className=\"ml-auto shrink-0 rounded bg-[hsl(var(--primary)/0.12)] px-1.5 py-0.5 text-[10px] text-[hsl(var(--primary))]\">\n {ref.skill_name}\n </span>\n )}\n </div>\n ))}\n <a\n href={MEMORIES_ROUTE}\n className=\"mt-1 self-start text-[10px] text-[hsl(var(--primary))] transition-colors hover:opacity-80\"\n >\n 查看全部经验 →\n </a>\n </div>\n )}\n </div>\n )\n}\n","export const MEMORIES_ROUTE = \"/memories\"\n","\"use client\"\n\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\"\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"../ui/collapsible\"\nimport { cn } from \"../../lib/utils\"\nimport { cjk } from \"@streamdown/cjk\"\nimport { math } from \"@streamdown/math\"\nimport { mermaid } from \"@streamdown/mermaid\"\nimport { BrainIcon, ChevronDownIcon, XIcon } from \"lucide-react\"\nimport type { ComponentProps, ReactNode } from \"react\"\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { Streamdown } from \"streamdown\"\n\nimport { Shimmer } from \"./shimmer\"\nimport { CardCodeBlock } from \"../card/CardCodeBlock\"\n\ninterface ReasoningContextValue {\n isStreaming: boolean\n isOpen: boolean\n setIsOpen: (open: boolean) => void\n duration: number | undefined\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null)\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext)\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\")\n }\n return context\n}\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n duration?: number\n}\n\nconst AUTO_CLOSE_DELAY = 3000\nconst MS_IN_S = 1000\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n })\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n })\n\n const hasEverStreamedRef = useRef(isStreaming)\n const [hasAutoClosed, setHasAutoClosed] = useState(false)\n const startTimeRef = useRef<number | null>(null)\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now()\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S))\n startTimeRef.current = null\n }\n }, [isStreaming, setDuration])\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true)\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed])\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (\n hasEverStreamedRef.current &&\n !isStreaming &&\n isOpen &&\n !hasAutoClosed\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false)\n setHasAutoClosed(true)\n }, AUTO_CLOSE_DELAY)\n\n return () => clearTimeout(timer)\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed])\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen)\n },\n [setIsOpen],\n )\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen],\n )\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn(\"not-prose mb-4\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n )\n },\n)\n\nexport type ReasoningTriggerProps = ComponentProps<\n typeof CollapsibleTrigger\n> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode\n}\n\nconst defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>深度思考中...</Shimmer>\n }\n if (duration === undefined) {\n return <p>已深度思考</p>\n }\n return <p>已深度思考 {duration} 秒</p>\n}\n\nexport const ReasoningTrigger = memo(\n ({\n className,\n children,\n getThinkingMessage = defaultGetThinkingMessage,\n ...props\n }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning()\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className,\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 transition-transform\",\n isOpen ? \"rotate-180\" : \"rotate-0\",\n )}\n />\n </>\n )}\n </CollapsibleTrigger>\n )\n },\n)\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string\n}\n\nconst streamdownPlugins = { cjk, math, mermaid }\nconst streamdownComponents = { code: CardCodeBlock }\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className,\n )}\n {...props}\n >\n <Streamdown components={streamdownComponents} plugins={streamdownPlugins}>\n {children}\n </Streamdown>\n </CollapsibleContent>\n ),\n)\n\nexport type ThinkingBadgeProps = {\n reasoning: string\n variant?: \"inline\" | \"block\"\n onClick?: ComponentProps<\"button\">[\"onClick\"]\n}\n\nfunction compactReasoningText(text: string): string {\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim()\n}\n\nexport function ThinkingBadge({ reasoning, variant = \"inline\", onClick }: ThinkingBadgeProps) {\n const compactReasoning = compactReasoningText(reasoning)\n const [open, setOpen] = useState(false)\n\n return (\n <span\n className={cn(\n \"relative inline-flex align-baseline\",\n variant === \"inline\" ? \"ml-1\" : \"ml-1 shrink-0\",\n )}\n >\n <button\n type=\"button\"\n onClick={(event) => {\n onClick?.(event)\n setOpen(true)\n }}\n className=\"inline-flex items-center rounded-full bg-[hsl(var(--muted))]/40 px-2 py-0.5 text-[10px] leading-none text-[hsl(var(--muted-foreground))]/70 transition-colors hover:bg-[hsl(var(--muted))]/60 hover:text-[hsl(var(--muted-foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n aria-label=\"查看深度思考\"\n aria-expanded={open}\n >\n 思考详情\n </button>\n {open\n ? createPortal(\n <div\n className=\"fixed inset-0 z-[70] flex items-center justify-center bg-black/10 p-6\"\n role=\"presentation\"\n tabIndex={-1}\n onClick={(event) => {\n if (event.target === event.currentTarget) {\n setOpen(false)\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n setOpen(false)\n }\n }}\n >\n <div\n className=\"m-0 flex max-h-[min(520px,calc(100vh-48px))] w-[min(760px,calc(100vw-48px))] flex-col overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] text-left text-[13px] leading-6 text-[hsl(var(--popover-foreground))] shadow-xl\"\n aria-label=\"思考详情\"\n >\n <div className=\"flex items-center justify-between gap-3 border-b border-[hsl(var(--border))] px-4 py-2\">\n <span className=\"text-xs font-medium text-[hsl(var(--muted-foreground))]\">\n 思考详情\n </span>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"inline-flex h-6 w-6 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n aria-label=\"关闭思考详情\"\n >\n <XIcon size={14} aria-hidden=\"true\" />\n </button>\n </div>\n <div className=\"overflow-auto px-4 py-3 whitespace-normal [&_*]:whitespace-normal [&_p]:my-1.5 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0 [&_ul]:my-1.5 [&_ol]:my-1.5\">\n <Streamdown components={streamdownComponents} plugins={streamdownPlugins}>\n {compactReasoning}\n </Streamdown>\n </div>\n </div>\n </div>,\n document.body,\n )\n : null}\n </span>\n )\n}\n\nReasoning.displayName = \"Reasoning\"\nReasoningTrigger.displayName = \"ReasoningTrigger\"\nReasoningContent.displayName = \"ReasoningContent\"\n","import { Collapsible as CollapsiblePrimitive } from \"radix-ui\"\n\nfunction Collapsible({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {\n return (\n <CollapsiblePrimitive.CollapsibleTrigger\n data-slot=\"collapsible-trigger\"\n {...props}\n />\n )\n}\n\nfunction CollapsibleContent({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {\n return (\n <CollapsiblePrimitive.CollapsibleContent\n data-slot=\"collapsible-content\"\n {...props}\n />\n )\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n","\"use client\"\n\nimport { cn } from \"../../lib/utils\"\nimport type { MotionProps } from \"motion/react\"\nimport { motion } from \"motion/react\"\nimport type { CSSProperties, ElementType, JSX } from \"react\"\nimport { memo, useMemo } from \"react\"\n\ntype MotionHTMLProps = MotionProps & Record<string, unknown>\n\n// Cache motion components at module level to avoid creating during render\nconst motionComponentCache = new Map<\n keyof JSX.IntrinsicElements,\n React.ComponentType<MotionHTMLProps>\n>()\n\nconst getMotionComponent = (element: keyof JSX.IntrinsicElements) => {\n let component = motionComponentCache.get(element)\n if (!component) {\n component = motion.create(element)\n motionComponentCache.set(element, component)\n }\n return component\n}\n\nexport interface TextShimmerProps {\n children: string\n as?: ElementType\n className?: string\n duration?: number\n spread?: number\n}\n\nconst ShimmerComponent = ({\n children,\n as: Component = \"p\",\n className,\n duration = 2,\n spread = 2,\n}: TextShimmerProps) => {\n const MotionComponent = getMotionComponent(\n Component as keyof JSX.IntrinsicElements,\n )\n\n const dynamicSpread = useMemo(\n () => (children?.length ?? 0) * spread,\n [children, spread],\n )\n\n return (\n <MotionComponent\n animate={{ backgroundPosition: \"0% center\" }}\n className={cn(\n \"relative inline-block bg-[length:250%_100%,auto] bg-clip-text text-transparent\",\n \"[--bg:linear-gradient(90deg,#0000_calc(50%-var(--spread)),var(--color-background),#0000_calc(50%+var(--spread)))] [background-repeat:no-repeat,padding-box]\",\n className,\n )}\n initial={{ backgroundPosition: \"100% center\" }}\n style={\n {\n \"--spread\": `${dynamicSpread}px`,\n backgroundImage:\n \"var(--bg), linear-gradient(var(--color-muted-foreground), var(--color-muted-foreground))\",\n } as CSSProperties\n }\n transition={{\n duration,\n ease: \"linear\",\n repeat: Number.POSITIVE_INFINITY,\n }}\n >\n {children}\n </MotionComponent>\n )\n}\n\nexport const Shimmer = memo(ShimmerComponent)\n","import { Bot, Check, ChevronRight, FileText, Loader2, MessageSquareMore } from \"lucide-react\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { isUiMeta } from \"../../lib/ui-meta\"\nimport { cn } from \"../../lib/utils\"\nimport type { ChatMessage, ToolCallInfo } from \"../../schemas/message\"\nimport { useChatStore } from \"../../stores/chat-store\"\nimport {\n Reasoning,\n ReasoningContent,\n ReasoningTrigger,\n ThinkingBadge,\n} from \"../ai-elements/reasoning\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\nimport { ResourceIframe } from \"./ResourceIframe\"\nimport { ToolCallBlock } from \"./ToolCallBlock\"\nimport { type UserChatMessage, UserMessageBubble } from \"./UserMessageBubble\"\nimport { formatToolName, getToolDisplayLabel, getToolOutputTag } from \"./display-utils\"\n\ninterface Props {\n toolCall: ToolCallInfo\n sessionId: string\n reasoning?: string\n}\n\ntype LoopStatus = \"running\" | \"done\" | \"error\" | \"cancelled\" | \"awaiting_answer\"\n\nconst EMPTY_MESSAGES: ChatMessage[] = []\nconst EMPTY_AGENT_LOOPS: Record<\n string,\n {\n toolCallId: string\n description: string\n status: \"running\" | \"done\" | \"error\" | \"cancelled\" | \"awaiting_answer\"\n }\n> = {}\n\nconst COLLAPSED_SUMMARY_HIDDEN_TOOLS = new Set([\n \"SearchSkills\",\n \"GetSkillContent\",\n \"ListSkillTools\",\n \"LoadSkillTools\",\n \"Read\",\n])\n\ntype CompletedToolLabel = {\n key: string\n label: string\n kind: \"file\" | \"tool\"\n}\n\nfunction safeParseDescription(argsStr: string): string {\n try {\n return JSON.parse(argsStr)?.description ?? \"子智能体\"\n } catch {\n return \"子智能体\"\n }\n}\n\nfunction stripFileExtension(fileName: string): string {\n return fileName.replace(/\\.[^.]+$/, \"\")\n}\n\nexport function AgentLoopBlock({ toolCall, sessionId, reasoning }: Props) {\n const agentLoops = useChatStore((state) => state.agentLoops[sessionId] ?? EMPTY_AGENT_LOOPS)\n const messages = useChatStore((state) => state.messages[sessionId] ?? EMPTY_MESSAGES)\n\n const loopEntry = useMemo(() => {\n for (const [loopName, info] of Object.entries(agentLoops)) {\n if (info.toolCallId === toolCall.id) {\n return { loopName, info }\n }\n }\n return null\n }, [agentLoops, toolCall.id])\n\n const childMessages = useMemo(() => {\n if (!loopEntry) return []\n return messages.filter((message) => (message.loop_name ?? \"root\") === loopEntry.loopName)\n }, [loopEntry, messages])\n\n const loopToolCalls = useMemo(\n () => childMessages.flatMap((message) => message.tool_calls ?? []),\n [childMessages],\n )\n const visibleLoopToolCalls = useMemo(\n () => loopToolCalls.filter((childToolCall) => formatToolName(childToolCall.name) !== \"Agent\"),\n [loopToolCalls],\n )\n const hasAwaitingAnswer = useMemo(\n () => visibleLoopToolCalls.some((childToolCall) => childToolCall.status === \"awaiting_answer\"),\n [visibleLoopToolCalls],\n )\n const [expanded, setExpanded] = useState(hasAwaitingAnswer)\n const completedToolLabels = useMemo<CompletedToolLabel[]>(\n () =>\n visibleLoopToolCalls\n .flatMap((childToolCall): CompletedToolLabel[] => {\n const isCompleted =\n childToolCall.status === \"done\" ||\n (childToolCall.status !== \"pending\" &&\n childToolCall.status !== \"awaiting_answer\" &&\n childToolCall.status !== \"error\" &&\n childToolCall.status !== \"cancelled\")\n if (!isCompleted) return []\n\n const outputTag = getToolOutputTag(childToolCall)\n if (outputTag) {\n const fileName = outputTag.label.replace(/^[^\\s]+\\s+/, \"\")\n return [\n {\n key: `${childToolCall.id}-${fileName}`,\n label: stripFileExtension(fileName),\n kind: \"file\",\n },\n ]\n }\n if (COLLAPSED_SUMMARY_HIDDEN_TOOLS.has(formatToolName(childToolCall.name))) {\n return []\n }\n return [\n {\n key: childToolCall.id,\n label: getToolDisplayLabel(childToolCall),\n kind: \"tool\",\n },\n ]\n }),\n [visibleLoopToolCalls],\n )\n const inlineToolUiBlocks = useMemo(\n () =>\n childMessages.flatMap((message) =>\n (message.blocks ?? []).flatMap((block, index) =>\n block.type === \"tool_ui\" &&\n block.tool_call_id &&\n isUiMeta(block.content) &&\n block.content.target === \"inline\"\n ? [{ key: `${message.entry_id ?? message.timestamp ?? \"message\"}-${block.tool_call_id}-${index}`, ui: block.content }]\n : [],\n ),\n ),\n [childMessages],\n )\n useEffect(() => {\n if (hasAwaitingAnswer) {\n setExpanded(true)\n }\n }, [hasAwaitingAnswer])\n const toggleExpanded = () => setExpanded((value) => !value)\n\n const description = safeParseDescription(toolCall.arguments)\n const status: LoopStatus =\n hasAwaitingAnswer || toolCall.status === \"awaiting_answer\"\n ? \"awaiting_answer\"\n : toolCall.status === \"pending\" || loopEntry?.info.status === \"running\"\n ? \"running\"\n : \"done\"\n const cardStyles = getLoopCardStyles(status)\n return (\n <div\n className={cn(\n \"ml-4 overflow-visible rounded-xl border border-[hsl(var(--border))] border-l-[3px] bg-[hsl(var(--card))]/50\",\n cardStyles.borderClass,\n )}\n >\n {status === \"running\" || status === \"awaiting_answer\" ? (\n <>\n <div\n className={cn(\n \"flex items-center gap-3 px-4 py-3 transition-colors\",\n cardStyles.headerClass,\n )}\n >\n <button\n type=\"button\"\n onClick={toggleExpanded}\n aria-expanded={expanded}\n className=\"flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n >\n <span className=\"min-w-0 flex items-center gap-2\">\n {status === \"awaiting_answer\" ? (\n <MessageSquareMore size={14} className=\"shrink-0 text-amber-500\" />\n ) : (\n <Bot size={14} className=\"shrink-0 text-blue-500\" />\n )}\n <span className=\"truncate text-sm font-medium text-[hsl(var(--foreground))]\">\n {description}\n {status === \"awaiting_answer\" ? \" — 等待回答\" : \"\"}\n </span>\n </span>\n </button>\n {reasoning ? <ThinkingBadge reasoning={reasoning} variant=\"block\" /> : null}\n <Bot\n size={13}\n className=\"shrink-0 text-[hsl(var(--muted-foreground))]/70\"\n aria-label=\"子智能体\"\n />\n <button\n type=\"button\"\n onClick={toggleExpanded}\n aria-expanded={expanded}\n className=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n >\n <ChevronRight\n size={14}\n className={cn(\n \"shrink-0 text-[hsl(var(--muted-foreground))] transition-transform\",\n expanded && \"rotate-90\",\n )}\n />\n </button>\n </div>\n {!expanded ? (\n <div className=\"flex flex-col gap-1 py-2\">\n {visibleLoopToolCalls.length > 0 ? (\n visibleLoopToolCalls.map((childToolCall) => (\n <ToolCallBlock\n key={childToolCall.id}\n toolCall={childToolCall}\n sessionId={sessionId}\n level={2}\n />\n ))\n ) : (\n <div className=\"flex items-center gap-2 px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]\">\n <Loader2 size={12} className=\"shrink-0 animate-spin text-blue-500\" />\n <span>正在启动...</span>\n </div>\n )}\n </div>\n ) : status === \"awaiting_answer\" ? (\n <div className=\"flex flex-col gap-1 py-2\">\n <div className=\"px-4 py-1 text-xs text-[hsl(var(--muted-foreground))]\">\n 请在下方子智能体对话中完成确认\n </div>\n </div>\n ) : null}\n </>\n ) : (\n <>\n <div\n className={cn(\n \"flex items-center gap-3 px-4 py-3 transition-colors\",\n cardStyles.headerClass,\n )}\n >\n <button\n type=\"button\"\n onClick={toggleExpanded}\n aria-expanded={expanded}\n className=\"flex min-w-0 flex-1 items-center gap-2 text-left focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n >\n <span className=\"min-w-0 flex items-center gap-2\">\n <Check size={14} className=\"shrink-0 text-emerald-500\" />\n <span className=\"truncate text-sm font-medium text-[hsl(var(--foreground))]\">\n {description}\n </span>\n </span>\n </button>\n {reasoning ? <ThinkingBadge reasoning={reasoning} variant=\"block\" /> : null}\n <Bot\n size={13}\n className=\"shrink-0 text-[hsl(var(--muted-foreground))]/70\"\n aria-label=\"子智能体\"\n />\n <button\n type=\"button\"\n onClick={toggleExpanded}\n aria-expanded={expanded}\n className=\"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted))] focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n >\n <ChevronRight\n size={14}\n className={cn(\n \"shrink-0 text-[hsl(var(--muted-foreground))] transition-transform\",\n expanded && \"rotate-90\",\n )}\n />\n </button>\n </div>\n {!expanded ? (\n <>\n <div className=\"flex flex-wrap gap-1.5 px-4 py-2\">\n {completedToolLabels.length > 0 ? (\n completedToolLabels.map((item) =>\n item.kind === \"file\" ? (\n <span\n key={item.key}\n className=\"inline-flex min-w-0 items-center gap-1 rounded-md border px-2 py-0.5 text-xs font-semibold dark:border-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-300\"\n style={{\n backgroundColor: \"#DCFCE7\",\n borderColor: \"#15803D\",\n color: \"#14532D\",\n }}\n title={item.label}\n >\n <FileText size={12} className=\"shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">{item.label}</span>\n </span>\n ) : (\n <span\n key={item.key}\n className=\"inline-flex items-center rounded-md border px-2 py-0.5 text-xs font-semibold dark:border-blue-300 dark:bg-blue-400/10 dark:text-blue-300\"\n style={{\n backgroundColor: \"#DBEAFE\",\n borderColor: \"#1D4ED8\",\n color: \"#1D4ED8\",\n }}\n >\n {item.label}\n </span>\n ),\n )\n ) : (\n <span className=\"text-xs text-[hsl(var(--muted-foreground))]\">暂无工具调用</span>\n )}\n </div>\n {inlineToolUiBlocks.length > 0 ? (\n <div className=\"flex flex-col gap-2 px-4 pb-3\">\n {inlineToolUiBlocks.map((block) => (\n <ResourceIframe key={block.key} ui={block.ui} sessionId={sessionId} />\n ))}\n </div>\n ) : null}\n </>\n ) : null}\n </>\n )}\n {expanded && (\n <div className=\"border-t border-[hsl(var(--border))] py-2\">\n {childMessages.length > 0 ? (\n <div className=\"flex flex-col gap-3 px-3\">\n {childMessages.map((message, index) =>\n message.role === \"assistant\" ? (\n <ExpandedChildAssistantMessage\n key={message.entry_id ?? `${message.timestamp ?? \"child\"}-${index}`}\n message={message}\n sessionId={sessionId}\n isStreaming={message.status === \"streaming\"}\n />\n ) : message.role === \"user\" ? (\n <ExpandedChildUserMessage\n key={message.entry_id ?? `${message.timestamp ?? \"user\"}-${index}`}\n message={message as UserChatMessage}\n />\n ) : message.role === \"error\" ? (\n <div\n key={message.entry_id ?? `${message.timestamp ?? \"error\"}-${index}`}\n className=\"border-l-[2px] border-l-red-500 px-3 py-2 text-[11px] text-red-200\"\n >\n {typeof message.content === \"string\" ? message.content : \"子智能体执行出错\"}\n </div>\n ) : null,\n )}\n </div>\n ) : status === \"running\" ? (\n <div className=\"px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]\">\n <Loader2 size={12} className=\"mr-1.5 inline animate-spin\" />\n 正在启动...\n </div>\n ) : toolCall.result ? (\n <pre className=\"max-h-[400px] overflow-auto px-3 py-2 whitespace-pre-wrap text-[11px] text-[hsl(var(--muted-foreground))]\">\n {typeof toolCall.result === \"string\"\n ? toolCall.result\n : JSON.stringify(toolCall.result, null, 2)}\n </pre>\n ) : null}\n </div>\n )}\n </div>\n )\n}\n\nfunction ExpandedChildUserMessage({ message }: { message: UserChatMessage }) {\n return (\n <div className=\"pl-8\">\n <UserMessageBubble message={message} />\n </div>\n )\n}\n\nfunction ExpandedChildAssistantMessage({\n message,\n sessionId,\n isStreaming,\n}: {\n message: ChatMessage\n sessionId: string\n isStreaming: boolean\n}) {\n const text =\n typeof message.content === \"string\"\n ? message.content.trim()\n : message.content\n .filter((part) => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\")\n .trim()\n const toolCalls = message.tool_calls ?? []\n const hasToolCalls = toolCalls.length > 0\n const firstToolCallId = toolCalls[0]?.id\n const toolReasoning = !isStreaming && !text && hasToolCalls ? message.reasoning : undefined\n const standaloneReasoning = !isStreaming && !text && !hasToolCalls ? message.reasoning : undefined\n\n return (\n <div className=\"flex flex-col gap-2\">\n {message.reasoning && isStreaming && (\n <Reasoning isStreaming={isStreaming}>\n <ReasoningTrigger />\n <ReasoningContent>{message.reasoning}</ReasoningContent>\n </Reasoning>\n )}\n {text ? (\n <ChildText\n text={text}\n isStreaming={isStreaming}\n sessionId={sessionId}\n reasoning={!isStreaming ? message.reasoning : undefined}\n />\n ) : null}\n {!text && isStreaming && (\n <span className=\"pl-8 text-[12px] text-[hsl(var(--muted-foreground))]\">正在生成...</span>\n )}\n {standaloneReasoning ? (\n <div className=\"pl-8\">\n <ThinkingBadge reasoning={standaloneReasoning} variant=\"block\" />\n </div>\n ) : null}\n {hasToolCalls && (\n <div className=\"flex flex-col gap-2\">\n {toolCalls.map((toolCall, index) =>\n formatToolName(toolCall.name) === \"Agent\" ? (\n <AgentLoopBlock\n key={toolCall.id}\n toolCall={toolCall}\n sessionId={sessionId}\n reasoning={toolCall.id === firstToolCallId ? toolReasoning : undefined}\n />\n ) : (\n <ToolCallBlock\n key={toolCall.id}\n toolCall={toolCall}\n sessionId={sessionId}\n level={2}\n turnBlocks={message.blocks}\n reasoning={index === 0 ? toolReasoning : undefined}\n />\n ),\n )}\n </div>\n )}\n {message.blocks?.some((block) => block.type === \"tool_ui\") ? (\n <div className=\"flex flex-col gap-2\">\n {message.blocks.map((block, index) =>\n block.type === \"tool_ui\" &&\n block.tool_call_id &&\n isUiMeta(block.content) &&\n block.content.target === \"inline\" ? (\n <div key={`${block.tool_call_id}-${index}`} className=\"ml-4\">\n <ResourceIframe ui={block.content} sessionId={sessionId} />\n </div>\n ) : null,\n )}\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction ChildText({\n text,\n isStreaming,\n sessionId,\n reasoning,\n}: { text: string; isStreaming: boolean; sessionId: string; reasoning?: string }) {\n return (\n <div className=\"pl-8 text-[12px] leading-6 text-[hsl(var(--foreground))]\">\n <MarkdownContent\n mode=\"streaming\"\n sessionId={sessionId}\n className=\"prose prose-sm prose-invert inline max-w-none [&_li>p]:inline [&_p]:mb-2 [&_p:last-child]:mb-0 [&_p:last-child]:inline\"\n controls={{ code: true }}\n >\n {text}\n </MarkdownContent>\n {isStreaming && (\n <span className=\"ml-0.5 inline-block h-[1em] w-[3px] animate-pulse rounded-sm bg-current opacity-60\" />\n )}\n {reasoning ? <ThinkingBadge reasoning={reasoning} /> : null}\n </div>\n )\n}\n\nfunction getLoopCardStyles(status: LoopStatus) {\n if (status === \"running\") {\n return {\n borderClass: \"border-l-blue-500\",\n headerClass: \"bg-blue-500/5\",\n iconClass: \"text-blue-500\",\n }\n }\n\n if (status === \"awaiting_answer\") {\n return {\n borderClass: \"border-l-amber-500\",\n headerClass: \"bg-amber-500/5\",\n iconClass: \"text-amber-500\",\n }\n }\n\n if (status === \"cancelled\") {\n return {\n borderClass: \"border-l-amber-500\",\n headerClass: \"bg-amber-500/5\",\n iconClass: \"text-amber-500\",\n }\n }\n\n if (status === \"error\") {\n return {\n borderClass: \"border-l-red-500\",\n headerClass: \"bg-red-500/5\",\n iconClass: \"text-red-500\",\n }\n }\n\n return {\n borderClass: \"border-l-[hsl(var(--primary))]\",\n headerClass: \"bg-[hsl(var(--primary)/0.05)]\",\n iconClass: \"text-[hsl(var(--primary))]\",\n }\n}\n","import { useEffect, useEffectEvent, useRef, useState } from \"react\"\nimport { registerBridgeIframe, tapBridgeEvent } from \"../../devtools/bridge-devtools/tap\"\nimport { resourceBridgeDispatch } from \"../../lib/resource-bridge\"\nimport type { UiMeta } from \"../../lib/ui-meta\"\nimport { useChatStore } from \"../../stores/chat-store\"\nimport { useSessionStore } from \"../../stores/session-store\"\nimport { resolveEffectiveTheme, useUiStore } from \"../../stores/ui-store\"\n\nfunction isResourceBridgeMessage(\n value: unknown,\n): value is { __resourceBridge: true; action: string; payload?: unknown } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as { __resourceBridge?: unknown }).__resourceBridge === true &&\n typeof (value as { action?: unknown }).action === \"string\"\n )\n}\n\n// inline target 的 height 上下限,避免恶意/失误内容把 iframe 撑爆或缩没\nconst INLINE_HEIGHT_MIN = 80\nconst INLINE_HEIGHT_MAX = 6000\nconst INLINE_HEIGHT_PADDING = 8\n\nexport function ResourceIframe({ ui, sessionId }: { ui: UiMeta; sessionId: string }) {\n const iframeRef = useRef<HTMLIFrameElement | null>(null)\n const iframeKeyRef = useRef<string>(\n `iframe-${Math.random().toString(36).slice(2, 10)}`,\n )\n const activeSessionId = useSessionStore((state) => state.activeSessionId)\n const isStreaming = useChatStore((state) => state.isStreaming[sessionId] ?? false)\n const theme = useUiStore((state) => state.theme)\n const resourceUri = ui.resourceUri ?? ui.resourceURI\n const iframeLabel = ui.title ?? resourceUri ?? \"工具界面\"\n // 由 iframe 内容自报的高度(resize 消息)。null 表示沿用工具声明的 ui.height。\n const [autoHeight, setAutoHeight] = useState<number | null>(null)\n\n // 工具更换 / 切换会话时重置自报高度(依赖列举的内容变化即触发重置)\n // biome-ignore lint/correctness/useExhaustiveDependencies: 此处依赖只用于触发重置,body 内无需引用\n useEffect(() => {\n setAutoHeight(null)\n }, [ui.resourceHTML, resourceUri])\n\n const effectiveTheme =\n theme === \"system\"\n ? document.documentElement.getAttribute(\"data-theme\") === \"light\" ||\n document.documentElement.getAttribute(\"data-theme\") === \"dark\"\n ? (document.documentElement.getAttribute(\"data-theme\") as \"light\" | \"dark\")\n : resolveEffectiveTheme(theme)\n : theme\n\n const handleMessage = useEffectEvent((event: MessageEvent) => {\n const iframeWindow = iframeRef.current?.contentWindow\n if (!iframeWindow || event.source !== iframeWindow) {\n return\n }\n\n if (!isResourceBridgeMessage(event.data)) {\n return\n }\n\n tapBridgeEvent({\n side: \"host\",\n direction: \"iframe-to-host\",\n action: event.data.action,\n payload: event.data.payload,\n iframeKey: iframeKeyRef.current,\n iframeLabel,\n })\n\n // inline target 下,iframe 内容可通过 resize 消息上报真实高度,由 host 实时贴合\n if (event.data.action === \"resize\" && ui.target !== \"preview\") {\n const payload = event.data.payload\n const rawHeight =\n payload && typeof payload === \"object\"\n ? (payload as { height?: unknown }).height\n : undefined\n if (typeof rawHeight === \"number\" && Number.isFinite(rawHeight) && rawHeight > 0) {\n const clamped = Math.min(\n Math.max(Math.ceil(rawHeight) + INLINE_HEIGHT_PADDING, INLINE_HEIGHT_MIN),\n INLINE_HEIGHT_MAX,\n )\n setAutoHeight((prev) => (prev === clamped ? prev : clamped))\n }\n return\n }\n\n resourceBridgeDispatch({\n sessionId,\n activeSessionId,\n isStreaming,\n action: event.data.action,\n payload: event.data.payload,\n })\n })\n\n useEffect(() => {\n const listener = (event: MessageEvent) => {\n handleMessage(event)\n }\n window.addEventListener(\"message\", listener)\n return () => {\n window.removeEventListener(\"message\", listener)\n }\n }, [handleMessage])\n\n const postTheme = useEffectEvent((themeValue: \"light\" | \"dark\") => {\n const iframeWindow = iframeRef.current?.contentWindow\n if (!iframeWindow) {\n return\n }\n iframeWindow.postMessage(\n {\n __resourceBridge: true,\n direction: \"host-to-iframe\",\n event: \"theme\",\n payload: { theme: themeValue },\n },\n \"*\",\n )\n tapBridgeEvent({\n side: \"host\",\n direction: \"host-to-iframe\",\n action: \"theme\",\n payload: { theme: themeValue },\n iframeKey: iframeKeyRef.current,\n iframeLabel,\n })\n })\n\n useEffect(() => {\n const key = iframeKeyRef.current\n return registerBridgeIframe({\n key,\n label: iframeLabel,\n getContentWindow: () => iframeRef.current?.contentWindow ?? null,\n })\n }, [iframeLabel])\n\n useEffect(() => {\n postTheme(effectiveTheme)\n }, [effectiveTheme, postTheme])\n\n if (!ui.resourceHTML && !resourceUri) {\n return null\n }\n\n const inlineHeight = autoHeight ?? ui.height\n const sandbox = resourceUri ? \"allow-scripts allow-same-origin\" : \"allow-scripts\"\n\n return (\n <iframe\n ref={iframeRef}\n title={ui.title ?? \"工具界面\"}\n src={resourceUri}\n srcDoc={ui.resourceHTML}\n sandbox={sandbox}\n loading=\"lazy\"\n scrolling={ui.target === \"preview\" ? undefined : \"no\"}\n className=\"w-full rounded-xl border border-[hsl(var(--border))] bg-white\"\n referrerPolicy=\"no-referrer\"\n style={{ height: ui.target === \"preview\" ? \"100%\" : inlineHeight }}\n onLoad={() => {\n postTheme(effectiveTheme)\n }}\n />\n )\n}\n","import { Check, ChevronRight, Loader2, MessageSquareMore, PanelRightOpen, X } from \"lucide-react\"\nimport { useMemo, useState } from \"react\"\nimport { resolveSessionFilePreviewTarget } from \"../../lib/session-file-preview\"\nimport { buildToolPreviewKey } from \"../../lib/tool-preview\"\nimport { isUiMeta } from \"../../lib/ui-meta\"\nimport { cn } from \"../../lib/utils\"\nimport type { ToolCallInfo } from \"../../schemas/message\"\nimport type { ContentBlock } from \"../../schemas/projection\"\nimport { useAnswerCallbackStore } from \"../../stores/answer-callback-store\"\nimport { useChatStore } from \"../../stores/chat-store\"\nimport { useSessionStore } from \"../../stores/session-store\"\nimport { useUiStore } from \"../../stores/ui-store\"\nimport {\n ThinkingBadge,\n} from \"../ai-elements/reasoning\"\nimport {\n AskUserQuestionBlock,\n type AskUserAnswerData,\n parseAskUserQuestion,\n} from \"./AskUserQuestionBlock\"\nimport {\n extractToolFilePath,\n formatToolName,\n getToolDisplayLabel,\n getToolStatusLabel,\n getToolTone,\n} from \"./display-utils\"\nimport { getRenderer } from \"./tool-renderers/registry\"\n\nfunction FilePathLink({ filePath, sessionId }: { filePath: string; sessionId?: string }) {\n const activeSessionId = useSessionStore((s) => s.activeSessionId)\n const pushArtifact = useUiStore((s) => s.pushArtifact)\n const resolvedSessionId = sessionId ?? activeSessionId\n\n const fileName = filePath.split(\"/\").pop() ?? filePath\n\n const handleClick = async () => {\n if (!resolvedSessionId) return\n try {\n const target = await resolveSessionFilePreviewTarget(\n resolvedSessionId,\n filePath,\n fileName,\n )\n pushArtifact(target)\n } catch {\n // Silently fail -- file may not exist in sandbox\n }\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n className=\"flex min-w-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer font-mono\"\n title={`预览 ${filePath}`}\n >\n <span className=\"truncate\">{fileName}</span>\n </button>\n )\n}\n\ninterface Props {\n toolCall: ToolCallInfo\n onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void\n answered?: boolean\n answerData?: AskUserAnswerData\n sessionId?: string\n sessionStatus?: string\n level?: 1 | 2\n turnBlocks?: ContentBlock[]\n reasoning?: string\n}\n\nexport function ToolCallBlock({\n toolCall,\n onAnswer,\n answered,\n answerData,\n sessionId: providedSessionId,\n sessionStatus,\n level = 1,\n turnBlocks,\n reasoning,\n}: Props) {\n const [expanded, setExpanded] = useState(false)\n const activeSessionId = useSessionStore((s) => s.activeSessionId)\n const sessions = useSessionStore((s) => s.sessions)\n const pushArtifact = useUiStore((s) => s.pushArtifact)\n const resolvedSessionId = providedSessionId ?? activeSessionId ?? undefined\n const storedAnswerData = useChatStore((s) =>\n resolvedSessionId ? s.askAnswers[resolvedSessionId]?.[toolCall.id] : undefined,\n )\n const answerCallback = useAnswerCallbackStore((s) =>\n resolvedSessionId ? s.callbacks[resolvedSessionId] : undefined,\n )\n const normalizedName = formatToolName(toolCall.name)\n const resolvedSessionStatus =\n sessionStatus ??\n sessions.find((session) => session.id === resolvedSessionId)?.status\n const resolvedAnswerData = answerData ?? storedAnswerData\n const resolvedAnswered =\n answered ?? (!!resolvedAnswerData && resolvedSessionStatus !== \"waiting_for_input\")\n const resolvedOnAnswer = onAnswer ?? answerCallback\n const uiMeta = useMemo(() => {\n const block = turnBlocks?.find(\n (item) => item.type === \"tool_ui\" && item.tool_call_id === toolCall.id && isUiMeta(item.content),\n )\n return block && isUiMeta(block.content) ? block.content : null\n }, [toolCall.id, turnBlocks])\n\n // Special rendering for AskUserQuestion\n if (normalizedName === \"AskUserQuestion\") {\n const askData =\n parseAskUserQuestion(typeof toolCall.result === \"string\" ? toolCall.result : null) ??\n parseAskUserQuestion(buildAskUserPayload(toolCall.arguments))\n const canAnswer =\n toolCall.status === \"awaiting_answer\" && Boolean(resolvedOnAnswer) && Boolean(resolvedSessionStatus)\n const shouldRenderQuestion = Boolean(askData) && (canAnswer || resolvedAnswered || toolCall.status === \"done\")\n if (askData && shouldRenderQuestion) {\n const questionBlock = (\n <AskUserQuestionBlock\n data={askData}\n answered={resolvedAnswered || toolCall.status === \"done\"}\n toolCallId={toolCall.id}\n sessionStatus={resolvedSessionStatus ?? \"\"}\n answerData={resolvedAnswerData}\n onAnswer={canAnswer ? resolvedOnAnswer : undefined}\n />\n )\n if (!reasoning) {\n return questionBlock\n }\n return (\n <div className=\"flex flex-col gap-1\">\n {questionBlock}\n <div className=\"ml-4\">\n <ThinkingBadge reasoning={reasoning} variant=\"block\" />\n </div>\n </div>\n )\n }\n }\n\n const filePath = extractToolFilePath(toolCall)\n const loadedSkillName = normalizedName === \"LoadSkillTools\" ? extractLoadedSkillName(toolCall) : null\n const tone = getToolTone(toolCall.status)\n const displayName = getToolDisplayLabel(toolCall)\n const Renderer = getRenderer(normalizedName)\n const borderWidthClass = level === 2 ? \"border-l-[2px]\" : \"border-l-[3px]\"\n const indentClass = level === 2 ? \"ml-3\" : \"ml-4\"\n const toneClass =\n tone === \"red\"\n ? \"border-l-[hsl(var(--muted-foreground)/0.5)]\"\n : tone === \"amber\"\n ? \"border-l-amber-400\"\n : tone === \"blue\"\n ? \"border-l-blue-500\"\n : \"border-l-[hsl(var(--primary))]\"\n\n const statusIcon =\n toolCall.status === \"pending\" ? (\n <Loader2 size={11} className=\"animate-spin\" />\n ) : toolCall.status === \"awaiting_answer\" ? (\n <MessageSquareMore size={11} />\n ) : toolCall.status === \"cancelled\" || toolCall.status === \"error\" ? (\n <X size={11} />\n ) : (\n <Check size={11} />\n )\n\n const statusTextClass =\n tone === \"red\"\n ? \"text-[hsl(var(--muted-foreground))]\"\n : tone === \"amber\"\n ? \"text-amber-300\"\n : tone === \"blue\"\n ? \"text-blue-300\"\n : \"text-[hsl(var(--primary))]\"\n\n return (\n <div className={cn(indentClass, \"text-xs\")}>\n <div className={cn(borderWidthClass, toneClass, \"flex items-center gap-2 px-3 py-2\")}>\n <button\n type=\"button\"\n onClick={() => setExpanded(!expanded)}\n className=\"flex min-w-0 flex-1 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none\"\n aria-expanded={expanded}\n >\n <ChevronRight\n size={11}\n className={cn(\n \"shrink-0 text-[hsl(var(--muted-foreground))] transition-transform\",\n expanded && \"rotate-90\",\n )}\n />\n <span className={cn(\"flex shrink-0 items-center gap-1 text-[10px]\", statusTextClass)}>\n {statusIcon}\n <span>{getToolStatusLabel(toolCall.status)}</span>\n </span>\n <span className=\"min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]\">\n {displayName}\n {toolCall.status === \"error\" ? \"(待重试)\" : \"\"}\n </span>\n </button>\n {filePath && (\n <span className=\"flex min-w-0 max-w-[50%] text-[hsl(var(--muted-foreground))]\">\n <FilePathLink filePath={filePath} sessionId={resolvedSessionId} />\n </span>\n )}\n {loadedSkillName ? (\n <span\n className=\"min-w-0 max-w-[50%] shrink truncate text-[hsl(var(--foreground))]\"\n title={loadedSkillName}\n >\n {loadedSkillName}\n </span>\n ) : null}\n {reasoning ? <ThinkingBadge reasoning={reasoning} variant=\"block\" /> : null}\n {typeof toolCall.duration_ms === \"number\" && toolCall.duration_ms > 0 && (\n <span className=\"shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {formatToolDuration(toolCall.duration_ms)}\n </span>\n )}\n {uiMeta?.target === \"preview\" && resolvedSessionId && !isInternalStatusPreview(uiMeta) ? (\n <button\n type=\"button\"\n onClick={() => {\n const type = uiMeta.resourceHTML ? \"resource-html\" : \"resource-uri\"\n const content = uiMeta.resourceHTML ?? uiMeta.resourceUri ?? uiMeta.resourceURI ?? \"\"\n pushArtifact({\n type,\n content,\n title: uiMeta.title ?? displayName,\n key: buildToolPreviewKey(content, type, toolCall.id),\n bridgeSessionId: resolvedSessionId,\n })\n }}\n className=\"inline-flex shrink-0 items-center gap-1 text-blue-400 hover:text-blue-300 hover:underline cursor-pointer\"\n title={`打开 ${uiMeta.title ?? displayName}`}\n >\n <PanelRightOpen size={11} />\n <span>{uiMeta.title ?? displayName}</span>\n </button>\n ) : null}\n </div>\n {expanded && (\n <div className=\"ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3\">\n {Renderer ? (\n <Renderer toolCall={toolCall} sessionId={resolvedSessionId} />\n ) : (\n <>\n <div className=\"mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]\">\n 参数\n </div>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]\">\n {formatArgs(toolCall.arguments)}\n </pre>\n {toolCall.result != null && (\n <>\n <div className=\"mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]\">\n 结果\n </div>\n <pre\n className={cn(\n \"max-h-[400px] overflow-auto whitespace-pre-wrap rounded-md p-2 font-mono text-[11px]\",\n \"bg-[hsl(var(--muted))] text-[hsl(var(--foreground))]\",\n )}\n >\n {typeof toolCall.result === \"string\"\n ? toolCall.result\n : JSON.stringify(toolCall.result, null, 2)}\n </pre>\n </>\n )}\n </>\n )}\n </div>\n )}\n </div>\n )\n}\n\nfunction extractLoadedSkillName(toolCall: ToolCallInfo): string | null {\n const args = parseToolArguments(toolCall.arguments)\n const skillId = typeof args?.skill_id === \"string\" ? args.skill_id.trim() : \"\"\n if (skillId) return skillId\n\n const result = parseToolResult(toolCall.result)\n if (isRecord(result) && typeof result.skill_id === \"string\") {\n const resultSkillId = result.skill_id.trim()\n if (resultSkillId) return resultSkillId\n }\n return null\n}\n\nfunction parseToolArguments(value: string | null | undefined): Record<string, unknown> | null {\n if (!value) return null\n try {\n const parsed = JSON.parse(value)\n return isRecord(parsed) ? parsed : null\n } catch {\n return null\n }\n}\n\nfunction parseToolResult(value: unknown): unknown {\n if (typeof value !== \"string\") return value\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isInternalStatusPreview(uiMeta: { title?: string | null } | null): boolean {\n return uiMeta?.title?.trim() === \"阶段进度\"\n}\n\nfunction formatToolDuration(ms: number): string {\n if (ms < 1000) return `${Math.round(ms)}ms`\n const seconds = ms / 1000\n if (seconds < 60) return `${seconds.toFixed(1)}s`\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = Math.round(seconds % 60)\n return remainingSeconds > 0 ? `${minutes}m${remainingSeconds}s` : `${minutes}m`\n}\n\nfunction formatArgs(args: string): string {\n try {\n return JSON.stringify(JSON.parse(args), null, 2)\n } catch {\n return args\n }\n}\n\nfunction buildAskUserPayload(argumentsJson: string): string | null {\n try {\n const parsed = JSON.parse(argumentsJson)\n if (parsed && typeof parsed === \"object\" && Array.isArray((parsed as { questions?: unknown }).questions)) {\n return JSON.stringify({ questions: (parsed as { questions: unknown[] }).questions })\n }\n } catch {\n return null\n }\n return null\n}\n","import { apiFetchResponse, getAuthedUrl } from \"../api/client\"\nimport type { PreviewTarget } from \"../stores/ui-store\"\n\nconst IMAGE_EXTS = new Set([\"png\", \"jpg\", \"jpeg\", \"gif\", \"svg\", \"webp\", \"ico\", \"bmp\"])\nconst DOCX_EXTS = new Set([\"docx\", \"doc\"])\nconst EXCEL_EXTS = new Set([\"xlsx\", \"xls\", \"xlsm\", \"xlsb\"])\nconst PPT_EXTS = new Set([\"pptx\", \"ppt\"])\nconst CSV_EXTS = new Set([\"csv\"])\nconst MARKDOWN_EXTS = new Set([\"md\", \"markdown\"])\nconst HTML_EXTS = new Set([\"html\", \"htm\"])\n\nfunction getExt(fileName: string): string {\n return fileName.split(\".\").pop()?.toLowerCase() ?? \"\"\n}\n\nfunction getDisplayFileName(filePath: string, fileName?: string): string {\n return fileName?.trim() || filePath.split(\"/\").pop() || filePath\n}\n\nfunction getSessionFilePath(sessionId: string, filePath: string): string {\n return `/api/sessions/${sessionId}/files/${encodeURIComponent(filePath)}`\n}\n\nfunction getSessionFileDownloadUrl(sessionId: string, filePath: string): string {\n return getAuthedUrl(getSessionFilePath(sessionId, filePath))\n}\n\n/**\n * 后端把可解码为 UTF-8 的文件返回为 text/plain,二进制文件返回各自的 MIME。\n * 只有文本类内容才能安全地整体读进内存渲染——其余一律不能读 body。\n */\nfunction isTextualContentType(contentType: string): boolean {\n return (\n contentType.startsWith(\"text/\") ||\n contentType.includes(\"json\") ||\n contentType.includes(\"xml\") ||\n contentType.includes(\"yaml\") ||\n contentType.includes(\"javascript\")\n )\n}\n\nexport function buildSessionBinaryPreviewTarget(\n sessionId: string,\n filePath: string,\n fileName?: string,\n): PreviewTarget | null {\n const resolvedFileName = getDisplayFileName(filePath, fileName)\n const ext = getExt(resolvedFileName)\n const filePathUrl = getSessionFilePath(sessionId, filePath)\n const downloadUrl = getSessionFileDownloadUrl(sessionId, filePath)\n\n if (IMAGE_EXTS.has(ext)) {\n return { type: \"image\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (ext === \"pdf\") {\n return { type: \"pdf\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (DOCX_EXTS.has(ext)) {\n return { type: \"docx\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (EXCEL_EXTS.has(ext)) {\n return { type: \"excel\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (PPT_EXTS.has(ext)) {\n return {\n type: \"ppt\",\n content: filePathUrl,\n sourceUrl: downloadUrl,\n title: resolvedFileName,\n key: filePath,\n }\n }\n\n return null\n}\n\nexport async function resolveSessionFilePreviewTarget(\n sessionId: string,\n filePath: string,\n fileName?: string,\n): Promise<PreviewTarget> {\n const resolvedFileName = getDisplayFileName(filePath, fileName)\n const binaryTarget = buildSessionBinaryPreviewTarget(sessionId, filePath, resolvedFileName)\n if (binaryTarget) {\n return binaryTarget\n }\n\n const downloadUrl = getSessionFileDownloadUrl(sessionId, filePath)\n\n // 其余文件按后端返回的 Content-Type 分派,而不是猜扩展名:\n // 视频/音频/压缩包等二进制文件绝不能读 body(整体读进内存会卡死页面),\n // 改为把下载 URL 交给原生 <video>/<audio> 流式播放,或回退为下载。\n const res = await apiFetchResponse(getSessionFilePath(sessionId, filePath))\n const contentType = (res.headers.get(\"content-type\") ?? \"\").toLowerCase()\n\n if (contentType.startsWith(\"video/\")) {\n void res.body?.cancel()\n return { type: \"video\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (contentType.startsWith(\"audio/\")) {\n void res.body?.cancel()\n return { type: \"audio\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n if (!isTextualContentType(contentType)) {\n void res.body?.cancel()\n return { type: \"download\", content: downloadUrl, title: resolvedFileName, key: filePath }\n }\n\n const content = await res.text()\n const ext = getExt(resolvedFileName)\n const type: PreviewTarget[\"type\"] = MARKDOWN_EXTS.has(ext)\n ? \"markdown\"\n : CSV_EXTS.has(ext)\n ? \"csv\"\n : HTML_EXTS.has(ext)\n ? \"html\"\n : \"file\"\n\n return {\n type,\n content,\n title: resolvedFileName,\n key: filePath,\n }\n}\n","import { useHighlightedCodeHtml } from \"../../../lib/code-highlight\"\nimport { cn } from \"../../../lib/utils\"\n\nconst EXT_TO_LANG: Record<string, string> = {\n \".bash\": \"bash\",\n \".css\": \"css\",\n \".go\": \"go\",\n \".htm\": \"html\",\n \".html\": \"html\",\n \".js\": \"javascript\",\n \".json\": \"json\",\n \".jsx\": \"jsx\",\n \".md\": \"markdown\",\n \".py\": \"python\",\n \".rs\": \"rust\",\n \".scss\": \"css\",\n \".sh\": \"bash\",\n \".ts\": \"typescript\",\n \".tsx\": \"tsx\",\n \".yaml\": \"yaml\",\n \".yml\": \"yaml\",\n \".zsh\": \"bash\",\n}\n\n/**\n * 从工具结果中提取纯文本。如果 result 是多模态 list 则提取 text parts;\n * 如果是 string 则原样返回。\n */\nexport function getResultText(result: unknown): string | null {\n if (typeof result === \"string\") return result\n if (Array.isArray(result)) {\n const texts = result\n .filter(\n (p): p is { type: \"text\"; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\" && typeof p.text === \"string\",\n )\n .map((p) => p.text)\n return texts.length > 0 ? texts.join(\"\\n\") : null\n }\n return result != null ? String(result) : null\n}\n\n/**\n * 从工具结果中提取图片 URL 列表(data:image/... base64 或 http URL)。\n */\nexport function getResultImageUrls(result: unknown): string[] {\n if (!Array.isArray(result)) return []\n return result\n .filter(\n (p): p is { type: \"image_url\"; image_url: { url: string } } =>\n typeof p === \"object\" &&\n p !== null &&\n p.type === \"image_url\" &&\n typeof p.image_url?.url === \"string\",\n )\n .map((p) => p.image_url.url)\n}\n\nexport function parseJsonValue(value?: string | null): unknown {\n if (!value) return null\n try {\n return JSON.parse(value)\n } catch {\n return null\n }\n}\n\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value)\n}\n\nexport function getStringValue(\n data: Record<string, unknown> | null,\n key: string,\n): string | null {\n const value = data?.[key]\n return typeof value === \"string\" && value.trim() ? value.trim() : null\n}\n\nexport function getNumberValue(\n data: Record<string, unknown> | null,\n key: string,\n): number | null {\n const value = data?.[key]\n return typeof value === \"number\" && Number.isFinite(value) ? value : null\n}\n\nexport function getBooleanValue(\n data: Record<string, unknown> | null,\n key: string,\n): boolean {\n return data?.[key] === true\n}\n\nexport function extractErrorMessage(value?: unknown): string | null {\n const text = typeof value === \"string\" ? value : getResultText(value)\n if (!text?.trim()) return null\n const parsed = parseJsonValue(text)\n if (!isPlainObject(parsed)) return null\n return typeof parsed.error === \"string\" && parsed.error.trim() ? parsed.error.trim() : null\n}\n\nexport function getFileName(filePath?: string | null): string {\n if (!filePath) return \"未命名文件\"\n return filePath.split(\"/\").pop() ?? filePath\n}\n\nexport function getCodeLanguage(filePath?: string | null): string | null {\n if (!filePath) return null\n const dotIndex = filePath.lastIndexOf(\".\")\n if (dotIndex < 0) return null\n return EXT_TO_LANG[filePath.slice(dotIndex).toLowerCase()] ?? null\n}\n\nexport function formatBytes(size?: number | null): string | null {\n if (typeof size !== \"number\" || !Number.isFinite(size) || size < 0) return null\n if (size < 1024) return `${size} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`\n return `${(size / (1024 * 1024)).toFixed(1)} MB`\n}\n\ninterface CodePreviewProps {\n content: string\n filePath?: string | null\n emptyLabel?: string\n className?: string\n}\n\nexport function CodePreview({\n content,\n filePath,\n emptyLabel = \"(暂无内容)\",\n className,\n}: CodePreviewProps) {\n const { highlightedHtml } = useHighlightedCodeHtml(content, getCodeLanguage(filePath))\n\n if (!content.trim()) {\n return (\n <pre\n className={cn(\n \"overflow-auto rounded-lg border border-[hsl(var(--border))]\",\n \"bg-[hsl(var(--muted))]/35 p-3 font-mono text-[11px] text-[hsl(var(--muted-foreground))]\",\n className,\n )}\n >\n <code>{emptyLabel}</code>\n </pre>\n )\n }\n\n return (\n <pre\n className={cn(\n \"overflow-auto rounded-lg border border-[hsl(var(--border))]\",\n \"bg-[hsl(var(--muted))]/35 p-3 text-[11px]\",\n className,\n )}\n >\n {highlightedHtml ? (\n <code\n className=\"font-mono\"\n // biome-ignore lint/security/noDangerouslySetInnerHtml: syntax highlighting output is generated locally\n dangerouslySetInnerHTML={{ __html: highlightedHtml }}\n />\n ) : (\n <code className=\"whitespace-pre-wrap break-words font-mono text-[hsl(var(--foreground))]\">\n {content}\n </code>\n )}\n </pre>\n )\n}\n","import { cn } from \"../../../lib/utils\"\nimport { formatToolName } from \"../display-utils\"\nimport type { ToolRendererProps } from \"./registry\"\nimport {\n extractErrorMessage,\n getBooleanValue,\n getNumberValue,\n getResultText,\n getStringValue,\n isPlainObject,\n parseJsonValue,\n} from \"./shared\"\n\nfunction pickOutputField(data: Record<string, unknown> | null): string | null {\n if (!data) return null\n for (const key of [\"output\", \"stdout\", \"stderr\"] as const) {\n const value = data[key]\n if (typeof value === \"string\") return value\n }\n return null\n}\n\nfunction MetaPill({ label }: { label: string }) {\n return (\n <span className=\"rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] text-secondary-foreground\">\n {label}\n </span>\n )\n}\n\nexport function BashRenderer({ toolCall }: ToolRendererProps) {\n const argsValue = parseJsonValue(toolCall.arguments)\n const rawText = getResultText(toolCall.result)\n const resultStr =\n typeof rawText === \"string\" && rawText.trim().length > 0 ? rawText : null\n const resultValue = parseJsonValue(resultStr)\n const args = isPlainObject(argsValue) ? argsValue : null\n const result = isPlainObject(resultValue) ? resultValue : null\n const normalizedName = formatToolName(toolCall.name)\n\n const command = getStringValue(result, \"command\") ?? getStringValue(args, \"command\") ?? \"\"\n const description =\n getStringValue(args, \"description\") ?? getStringValue(result, \"description\") ?? \"\"\n const cwd = getStringValue(result, \"cwd\") ?? getStringValue(args, \"cwd\")\n const taskId = getStringValue(result, \"task_id\")\n const exitCode = getNumberValue(result, \"exit_code\")\n const timedOut = getBooleanValue(result, \"timed_out\")\n const truncated = getBooleanValue(result, \"truncated\")\n const cwdResetNote = getStringValue(result, \"cwd_reset_note\")\n const errorMessage =\n extractErrorMessage(toolCall.result) ??\n (toolCall.status === \"error\" ? resultStr?.trim() ?? null : null)\n const structuredOutput = pickOutputField(result)\n const rawFallbackOutput =\n result === null && typeof resultStr === \"string\" && resultStr.trim().length > 0\n ? resultStr\n : null\n const output =\n structuredOutput !== null\n ? structuredOutput\n : errorMessage ?? rawFallbackOutput ?? (normalizedName === \"BgBash\" ? \"\" : null)\n const hasFailure =\n toolCall.status === \"error\" || timedOut || (exitCode !== null && exitCode !== 0)\n\n return (\n <div className=\"space-y-3\">\n {(description || cwd) && (\n <div className=\"flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]\">\n {description ? <span>{description}</span> : null}\n {cwd ? (\n <span className=\"rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono\">\n {cwd}\n </span>\n ) : null}\n </div>\n )}\n\n <div className=\"overflow-hidden rounded-lg border border-border bg-card\">\n <div className=\"border-b border-border px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-muted-foreground\">\n 命令\n </div>\n <pre className=\"overflow-x-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground\">\n <code>{`$ ${command || \"(未提供命令)\"}`}</code>\n </pre>\n </div>\n\n <div\n className={cn(\n \"overflow-hidden rounded-lg border bg-muted/50\",\n hasFailure ? \"border-red-500/50\" : \"border-border\",\n )}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2 border-b border-border px-3 py-2\">\n <div className=\"text-[10px] uppercase tracking-[0.16em] text-muted-foreground\">输出</div>\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {taskId ? <MetaPill label={`任务 ${taskId}`} /> : null}\n {exitCode !== null ? <MetaPill label={`退出码 ${exitCode}`} /> : null}\n {timedOut ? <MetaPill label=\"已超时\" /> : null}\n {truncated ? <MetaPill label=\"输出已截断\" /> : null}\n {normalizedName === \"BgBash\" && !taskId ? <MetaPill label=\"后台任务\" /> : null}\n </div>\n </div>\n <pre className=\"max-h-[280px] overflow-auto px-3 py-3 font-mono text-[11px] leading-5 text-foreground\">\n <code className=\"whitespace-pre-wrap break-words\">\n {output !== null && output.trim().length > 0\n ? output\n : normalizedName === \"BgBash\"\n ? \"任务已进入后台执行,输出会在后台任务面板中继续更新。\"\n : output !== null && output.trim().length === 0 && hasFailure\n ? \"命令已结束,但未捕获到终端输出(请查看退出码)。\"\n : \"命令未返回输出。\"}\n </code>\n </pre>\n </div>\n\n {cwdResetNote ? (\n <div className=\"rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]\">\n {cwdResetNote}\n </div>\n ) : null}\n </div>\n )\n}\n","import { cn } from \"../../../lib/utils\"\nimport { extractToolFilePath, formatToolName } from \"../display-utils\"\nimport type { ToolRendererProps } from \"./registry\"\nimport {\n extractErrorMessage,\n getFileName,\n getStringValue,\n isPlainObject,\n parseJsonValue,\n} from \"./shared\"\n\ninterface DiffLine {\n type: \"added\" | \"removed\" | \"unchanged\"\n value: string\n oldLine: number | null\n newLine: number | null\n}\n\nconst MAX_DIFF_LINES = 200\n\nfunction computeDiff(oldText: string, newText: string): DiffLine[] {\n const oldLines = oldText.split(\"\\n\")\n const newLines = newText.split(\"\\n\")\n\n if (oldLines.length > MAX_DIFF_LINES || newLines.length > MAX_DIFF_LINES) {\n return [\n ...oldLines.slice(0, MAX_DIFF_LINES).map((line, i) => ({\n type: \"removed\" as const,\n value: line,\n oldLine: i + 1,\n newLine: null,\n })),\n ...newLines.slice(0, MAX_DIFF_LINES).map((line, i) => ({\n type: \"added\" as const,\n value: line,\n oldLine: null,\n newLine: i + 1,\n })),\n ]\n }\n\n const rows = oldLines.length\n const cols = newLines.length\n const lcs: number[][] = Array.from({ length: rows + 1 }, () => Array(cols + 1).fill(0))\n\n for (let row = 1; row <= rows; row += 1) {\n for (let col = 1; col <= cols; col += 1) {\n lcs[row][col] =\n oldLines[row - 1] === newLines[col - 1]\n ? lcs[row - 1][col - 1] + 1\n : Math.max(lcs[row - 1][col], lcs[row][col - 1])\n }\n }\n\n const diff: Array<Omit<DiffLine, \"oldLine\" | \"newLine\">> = []\n let row = rows\n let col = cols\n\n while (row > 0 || col > 0) {\n if (row > 0 && col > 0 && oldLines[row - 1] === newLines[col - 1]) {\n diff.push({ type: \"unchanged\", value: oldLines[row - 1] })\n row -= 1\n col -= 1\n continue\n }\n\n if (col > 0 && (row === 0 || lcs[row][col - 1] >= lcs[row - 1][col])) {\n diff.push({ type: \"added\", value: newLines[col - 1] })\n col -= 1\n continue\n }\n\n if (row > 0) {\n diff.push({ type: \"removed\", value: oldLines[row - 1] })\n row -= 1\n }\n }\n\n const numbered: DiffLine[] = []\n let oldLine = 0\n let newLine = 0\n\n for (const line of diff.reverse()) {\n if (line.type === \"unchanged\") {\n oldLine += 1\n newLine += 1\n numbered.push({ ...line, oldLine, newLine })\n continue\n }\n\n if (line.type === \"removed\") {\n oldLine += 1\n numbered.push({ ...line, oldLine, newLine: null })\n continue\n }\n\n newLine += 1\n numbered.push({ ...line, oldLine: null, newLine })\n }\n\n return numbered\n}\n\nfunction buildWritePreview(content: string): DiffLine[] {\n return content.split(\"\\n\").map((line, index) => ({\n type: \"added\",\n value: line,\n oldLine: null,\n newLine: index + 1,\n }))\n}\n\nfunction extractChecksum(result?: unknown): string | null {\n const text = typeof result === \"string\" ? result : null\n const match = text?.match(/\\[checksum:\\s*([^\\]]+)\\]/)\n return match?.[1]?.trim() ?? null\n}\n\nexport function FileEditRenderer({ toolCall }: ToolRendererProps) {\n const argsValue = parseJsonValue(toolCall.arguments)\n const args = isPlainObject(argsValue) ? argsValue : null\n const normalizedName = formatToolName(toolCall.name)\n const filePath = extractToolFilePath(toolCall)\n const fileName = getFileName(filePath)\n const errorMessage = extractErrorMessage(toolCall.result)\n const checksum = extractChecksum(toolCall.result)\n\n const writeContent = getStringValue(args, \"content\") ?? \"\"\n const oldString = getStringValue(args, \"old_string\") ?? \"\"\n const newString = getStringValue(args, \"new_string\") ?? \"\"\n const diffLines =\n normalizedName === \"Write\" ? buildWritePreview(writeContent) : computeDiff(oldString, newString)\n const resultStr = typeof toolCall.result === \"string\" ? toolCall.result : null\n const summaryText = resultStr?.trim() && !errorMessage ? resultStr.trim() : null\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]\">\n {normalizedName === \"Write\" ? \"写入文件\" : \"编辑文件\"}\n </div>\n <div className=\"truncate font-mono text-[11px] text-[hsl(var(--foreground))]\">\n {filePath ?? fileName}\n </div>\n </div>\n {checksum ? (\n <span className=\"rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {checksum}\n </span>\n ) : null}\n </div>\n\n {errorMessage ? (\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300\">\n {errorMessage}\n </div>\n ) : null}\n\n <div className=\"overflow-hidden rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20\">\n <div className=\"border-b border-[hsl(var(--border))] px-3 py-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]\">\n {normalizedName === \"Write\" ? \"内容预览\" : \"变更预览\"}\n </div>\n <pre className=\"max-h-[320px] overflow-auto p-0 font-mono text-[11px] leading-5\">\n {diffLines.length > 0 ? (\n diffLines.map((line, index) => {\n const prefix =\n line.type === \"added\" ? \"+ \" : line.type === \"removed\" ? \"- \" : \" \"\n\n return (\n <div\n key={`${line.type}-${line.oldLine}-${line.newLine}-${index}`}\n className={cn(\n \"grid grid-cols-[3rem_3rem_minmax(0,1fr)] gap-0 px-3\",\n line.type === \"added\" && \"bg-emerald-500/10 text-emerald-200\",\n line.type === \"removed\" && \"bg-red-500/10 text-red-200\",\n line.type === \"unchanged\" && \"text-[hsl(var(--foreground))]\",\n )}\n >\n <span className=\"select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]\">\n {line.oldLine ?? \"\"}\n </span>\n <span className=\"select-none py-0.5 text-right text-[10px] text-[hsl(var(--muted-foreground))]\">\n {line.newLine ?? \"\"}\n </span>\n <span className=\"min-w-0 whitespace-pre-wrap break-words py-0.5\">\n {prefix}\n {line.value}\n </span>\n </div>\n )\n })\n ) : (\n <div className=\"px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]\">\n 未检测到可预览的变更。\n </div>\n )}\n </pre>\n </div>\n\n {summaryText ? (\n <div className=\"rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]\">\n {summaryText}\n </div>\n ) : null}\n </div>\n )\n}\n","import { useState } from \"react\"\nimport { ImageLightbox } from \"../ImageLightbox\"\nimport { extractToolFilePath } from \"../display-utils\"\nimport type { ToolRendererProps } from \"./registry\"\nimport {\n CodePreview,\n extractErrorMessage,\n getFileName,\n getNumberValue,\n getResultImageUrls,\n getResultText,\n isPlainObject,\n parseJsonValue,\n} from \"./shared\"\n\nconst NUMBERED_LINE_RE = /^(\\s*\\d+)\\t([\\s\\S]*)$/\n\nfunction parseReadResult(result?: string | null) {\n if (!result) {\n return {\n checksum: null,\n content: \"\",\n endLine: null,\n note: null,\n startLine: null,\n }\n }\n\n let body = result.trimEnd()\n const checksumMatch = body.match(/\\n\\n\\[checksum:\\s*([^\\]]+)\\]\\s*$/)\n const checksum = checksumMatch?.[1]?.trim() ?? null\n\n if (checksumMatch?.index !== undefined) {\n body = body.slice(0, checksumMatch.index).trimEnd()\n }\n\n const noteMatch = body.match(/\\n\\n(文件共[\\s\\S]*?)\\s*$/)\n const note = noteMatch?.[0]?.trim() ?? null\n\n if (noteMatch?.index !== undefined) {\n body = body.slice(0, noteMatch.index).trimEnd()\n }\n\n const numberedLines = body\n .split(\"\\n\")\n .map((line) => {\n const match = line.match(NUMBERED_LINE_RE)\n if (!match) return null\n return {\n number: Number(match[1].trim()),\n text: match[2],\n }\n })\n .filter((line): line is { number: number; text: string } => Boolean(line))\n\n return {\n checksum,\n content: numberedLines.length > 0 ? numberedLines.map((line) => line.text).join(\"\\n\") : body,\n endLine: numberedLines.length > 0 ? numberedLines[numberedLines.length - 1].number : null,\n note,\n startLine: numberedLines.length > 0 ? numberedLines[0].number : null,\n }\n}\n\nfunction formatLineRange(startLine: number | null, endLine: number | null): string | null {\n if (startLine === null || endLine === null) return null\n return startLine === endLine ? `第 ${startLine} 行` : `第 ${startLine}-${endLine} 行`\n}\n\nexport function FileReadRenderer({ toolCall }: ToolRendererProps) {\n const [lightboxIndex, setLightboxIndex] = useState<number | null>(null)\n\n const argsValue = parseJsonValue(toolCall.arguments)\n const args = isPlainObject(argsValue) ? argsValue : null\n const filePath = extractToolFilePath(toolCall)\n const fileName = getFileName(filePath)\n\n // 提取文本和图片\n const resultText = getResultText(toolCall.result)\n const imageUrls = getResultImageUrls(toolCall.result)\n const isImageResult = imageUrls.length > 0\n\n const errorMessage = extractErrorMessage(resultText)\n const { checksum, content, note, startLine, endLine } = parseReadResult(resultText)\n const fallbackStart = getNumberValue(args, \"offset\") ?? 1\n const lineCount = content ? content.split(\"\\n\").length : 0\n const resolvedStartLine = startLine ?? (lineCount > 0 ? fallbackStart : null)\n const resolvedEndLine =\n endLine ?? (resolvedStartLine !== null && lineCount > 0 ? resolvedStartLine + lineCount - 1 : null)\n const lineRange = formatLineRange(resolvedStartLine, resolvedEndLine)\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"truncate font-mono text-[11px] text-[hsl(var(--foreground))]\">\n {fileName}\n </div>\n {filePath ? (\n <div className=\"truncate text-[10px] text-[hsl(var(--muted-foreground))]\">\n {filePath}\n </div>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center justify-end gap-1.5\">\n {lineRange ? (\n <span className=\"rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\">\n {lineRange}\n </span>\n ) : null}\n {checksum ? (\n <span className=\"rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted))] px-2 py-0.5 font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {checksum}\n </span>\n ) : null}\n </div>\n </div>\n\n {errorMessage ? (\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300\">\n {errorMessage}\n </div>\n ) : null}\n\n {isImageResult ? (\n <div className=\"grid gap-2\">\n {imageUrls.map((url, idx) => (\n <button\n type=\"button\"\n key={url.slice(0, 64)}\n onClick={() => setLightboxIndex(idx)}\n className=\"cursor-zoom-in\"\n title=\"查看大图\"\n >\n <img\n src={url}\n alt={fileName}\n className=\"max-h-64 rounded-lg border border-[hsl(var(--border))] object-contain\"\n />\n </button>\n ))}\n <ImageLightbox\n open={lightboxIndex != null}\n onOpenChange={(open) => {\n if (!open) setLightboxIndex(null)\n }}\n images={imageUrls.map((url) => ({ src: url, alt: fileName }))}\n initialIndex={lightboxIndex ?? 0}\n />\n {content ? (\n <div className=\"text-[11px] text-[hsl(var(--muted-foreground))]\">{content}</div>\n ) : null}\n </div>\n ) : !errorMessage ? (\n <CodePreview content={content} filePath={filePath} className=\"max-h-[360px]\" />\n ) : null}\n\n {note ? (\n <div className=\"rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/35 px-3 py-2 text-[11px] text-[hsl(var(--muted-foreground))]\">\n {note}\n </div>\n ) : null}\n </div>\n )\n}\n","import { ChevronLeft, ChevronRight, Download, ExternalLink, Minus, Plus, RotateCcw, X } from \"lucide-react\"\nimport { useCallback, useEffect, useRef, useState } from \"react\"\nimport { createPortal } from \"react-dom\"\n\ninterface ImageLightboxProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n images: { src: string; alt: string }[]\n initialIndex?: number\n}\n\nexport function ImageLightbox({ open, onOpenChange, images, initialIndex = 0 }: ImageLightboxProps) {\n const [currentIndex, setCurrentIndex] = useState(initialIndex)\n const [scale, setScale] = useState(1)\n const [translate, setTranslate] = useState({ x: 0, y: 0 })\n const dragging = useRef(false)\n const dragStart = useRef({ x: 0, y: 0 })\n const translateStart = useRef({ x: 0, y: 0 })\n const imgRef = useRef<HTMLImageElement>(null)\n\n const reset = useCallback(() => {\n setScale(1)\n setTranslate({ x: 0, y: 0 })\n }, [])\n\n const close = useCallback(() => {\n reset()\n onOpenChange(false)\n }, [onOpenChange, reset])\n\n const zoomIn = useCallback(() => setScale((s) => Math.min(s + 0.5, 5)), [])\n const zoomOut = useCallback(() => setScale((s) => Math.max(s - 0.5, 0.5)), [])\n\n const goPrev = useCallback(() => {\n setCurrentIndex((i) => Math.max(0, i - 1))\n reset()\n }, [reset])\n\n const goNext = useCallback(() => {\n setCurrentIndex((i) => Math.min(images.length - 1, i + 1))\n reset()\n }, [images.length, reset])\n\n // Reset state only on closed→open transition\n const prevOpenRef = useRef(false)\n useEffect(() => {\n if (open && !prevOpenRef.current) {\n setCurrentIndex(initialIndex)\n reset()\n }\n prevOpenRef.current = open\n }, [open, initialIndex, reset])\n\n // Keyboard: ESC to close, arrow keys to navigate\n useEffect(() => {\n if (!open) return\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") close()\n if (images.length > 1) {\n if (e.key === \"ArrowLeft\") goPrev()\n if (e.key === \"ArrowRight\") goNext()\n }\n }\n document.addEventListener(\"keydown\", handleKey)\n return () => document.removeEventListener(\"keydown\", handleKey)\n }, [open, close, goPrev, goNext, images.length])\n\n // Prevent body scroll when open\n useEffect(() => {\n if (!open) return\n const prev = document.body.style.overflow\n document.body.style.overflow = \"hidden\"\n return () => {\n document.body.style.overflow = prev\n }\n }, [open])\n\n const handleWheel = useCallback((e: React.WheelEvent) => {\n e.preventDefault()\n setScale((s) => {\n const delta = e.deltaY > 0 ? -0.2 : 0.2\n return Math.min(Math.max(s + delta, 0.5), 5)\n })\n }, [])\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n if (scale <= 1) return\n e.preventDefault()\n dragging.current = true\n dragStart.current = { x: e.clientX, y: e.clientY }\n translateStart.current = { ...translate }\n },\n [scale, translate],\n )\n\n const handleMouseMove = useCallback((e: React.MouseEvent) => {\n if (!dragging.current) return\n setTranslate({\n x: translateStart.current.x + e.clientX - dragStart.current.x,\n y: translateStart.current.y + e.clientY - dragStart.current.y,\n })\n }, [])\n\n const handleMouseUp = useCallback(() => {\n dragging.current = false\n }, [])\n\n const handleDoubleClick = useCallback(() => {\n reset()\n }, [reset])\n\n // Close when clicking outside the image (on the padding area)\n const handleAreaClick = useCallback(\n (e: React.MouseEvent) => {\n if (imgRef.current && !imgRef.current.contains(e.target as Node)) {\n close()\n }\n },\n [close],\n )\n\n const handleDownload = useCallback(() => {\n const img = images[currentIndex] ?? images[0]\n if (!img?.src) return\n const a = document.createElement(\"a\")\n a.href = img.src\n a.download = img.alt || \"image.png\"\n a.click()\n }, [images, currentIndex])\n\n const handleOpenInNewTab = useCallback(() => {\n const img = images[currentIndex] ?? images[0]\n if (!img?.src) return\n window.open(img.src, \"_blank\")\n }, [images, currentIndex])\n\n if (!open) return null\n\n // Show loading state when open but images not yet ready\n if (images.length === 0) {\n return createPortal(\n // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/80\"\n onClick={close}\n >\n <button\n type=\"button\"\n onClick={close}\n className=\"absolute right-4 top-4 z-10 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white\"\n >\n <X size={20} />\n </button>\n <span className=\"text-sm text-white/60\">加载中...</span>\n </div>,\n document.body,\n )\n }\n\n const current = images[currentIndex] ?? images[0]\n const showNav = images.length > 1\n\n return createPortal(\n // biome-ignore lint/a11y/useKeyWithClickEvents: ESC handler is registered via useEffect\n <div className=\"fixed inset-0 z-50 bg-black/80\" onClick={handleAreaClick}>\n {/* Top-right actions — stopPropagation prevents handleAreaClick from closing the lightbox */}\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: only used to stop event propagation */}\n <div\n className=\"absolute right-4 top-4 z-10 flex items-center gap-1.5\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n onClick={handleDownload}\n title=\"下载图片\"\n className=\"rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white\"\n >\n <Download size={18} />\n </button>\n <button\n type=\"button\"\n onClick={handleOpenInNewTab}\n title=\"新标签页打开\"\n className=\"rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white\"\n >\n <ExternalLink size={18} />\n </button>\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white\"\n >\n <X size={20} />\n </button>\n </div>\n\n {/* Prev arrow */}\n {showNav && currentIndex > 0 && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n goPrev()\n }}\n className=\"absolute left-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white\"\n >\n <ChevronLeft size={24} />\n </button>\n )}\n\n {/* Next arrow */}\n {showNav && currentIndex < images.length - 1 && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n goNext()\n }}\n className=\"absolute right-4 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/50 p-2 text-white/80 transition-colors hover:bg-black/70 hover:text-white\"\n >\n <ChevronRight size={24} />\n </button>\n )}\n\n {/* Zoom controls + image counter */}\n <div className=\"absolute bottom-6 left-1/2 z-10 flex -translate-x-1/2 items-center gap-1 rounded-full bg-black/50 px-2 py-1\">\n <button\n type=\"button\"\n onClick={zoomOut}\n className=\"rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white\"\n >\n <Minus size={16} />\n </button>\n <span className=\"min-w-[3rem] text-center text-xs text-white/80\">\n {Math.round(scale * 100)}%\n </span>\n <button\n type=\"button\"\n onClick={zoomIn}\n className=\"rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white\"\n >\n <Plus size={16} />\n </button>\n <button\n type=\"button\"\n onClick={reset}\n className=\"rounded-full p-1.5 text-white/80 transition-colors hover:bg-white/10 hover:text-white\"\n >\n <RotateCcw size={16} />\n </button>\n {showNav && (\n <>\n <div className=\"mx-1 h-4 w-px bg-white/20\" />\n <span className=\"min-w-[3rem] text-center text-xs text-white/80\">\n {currentIndex + 1} / {images.length}\n </span>\n </>\n )}\n </div>\n\n {/* Image area */}\n <div\n className=\"flex h-full w-full items-center justify-center overflow-hidden p-12\"\n style={{ cursor: scale > 1 ? \"grab\" : \"default\" }}\n onWheel={handleWheel}\n onMouseDown={handleMouseDown}\n onMouseMove={handleMouseMove}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseUp}\n onDoubleClick={handleDoubleClick}\n >\n <img\n ref={imgRef}\n src={current.src}\n alt={current.alt}\n draggable={false}\n className=\"max-h-full max-w-full select-none object-contain\"\n style={{\n transform: `scale(${scale}) translate(${translate.x / scale}px, ${translate.y / scale}px)`,\n transition: dragging.current ? \"none\" : \"transform 0.2s ease\",\n }}\n />\n </div>\n </div>,\n document.body,\n )\n}\n","import { ExternalLink, FileText, Folder, Globe2 } from \"lucide-react\"\nimport { cn } from \"../../../lib/utils\"\nimport { formatToolName } from \"../display-utils\"\nimport type { ToolRendererProps } from \"./registry\"\nimport {\n extractErrorMessage,\n formatBytes,\n getResultText,\n getStringValue,\n isPlainObject,\n parseJsonValue,\n} from \"./shared\"\n\ninterface DirectoryItem {\n isDir: boolean\n name: string\n size: number | null\n}\n\ninterface GrepMatch {\n line: string\n lineNumber: number | null\n path: string\n}\n\ninterface SearchResultItem {\n description: string | null\n title: string | null\n url: string | null\n}\n\nfunction toRecordArray(value: unknown): Record<string, unknown>[] {\n return Array.isArray(value) ? value.filter(isPlainObject) : []\n}\n\nfunction parseDirectoryItems(result?: string | null): DirectoryItem[] {\n const value = parseJsonValue(result)\n\n if (!Array.isArray(value)) {\n return []\n }\n\n return value\n .map((item) => {\n if (typeof item === \"string\") {\n return {\n isDir: item.endsWith(\"/\"),\n name: item,\n size: null,\n }\n }\n\n if (!isPlainObject(item)) {\n return null\n }\n\n return {\n isDir: item.is_dir === true,\n name: typeof item.name === \"string\" ? item.name : \"未命名\",\n size: typeof item.size === \"number\" ? item.size : null,\n }\n })\n .filter((item): item is DirectoryItem => Boolean(item))\n}\n\nfunction parseGrepResult(result?: string | null): {\n matches: GrepMatch[]\n searchPath: string | null\n} {\n if (!result?.trim()) {\n return { matches: [], searchPath: null }\n }\n\n const [header, ...rest] = result.split(\"\\n\")\n const searchPath = header.startsWith(\"搜索路径:\") ? header.replace(\"搜索路径:\", \"\").trim() : null\n const matches = toRecordArray(parseJsonValue(rest.join(\"\\n\"))).map((item) => ({\n line: typeof item.line === \"string\" ? item.line : \"\",\n lineNumber: typeof item.line_number === \"number\" ? item.line_number : null,\n path: typeof item.path === \"string\" ? item.path : \"未知路径\",\n }))\n\n return { matches, searchPath }\n}\n\nfunction parseWebResults(result?: string | null): SearchResultItem[] {\n return toRecordArray(parseJsonValue(result)).map((item) => ({\n description: typeof item.description === \"string\" ? item.description : null,\n title: typeof item.title === \"string\" ? item.title : null,\n url: typeof item.url === \"string\" ? item.url : null,\n }))\n}\n\nfunction parseWebFetchResult(result?: string | null): {\n results: SearchResultItem[]\n summary: string | null\n} {\n const value = parseJsonValue(result)\n if (!isPlainObject(value)) {\n return { results: [], summary: null }\n }\n\n return {\n results: toRecordArray(value.results).map((item) => ({\n description: typeof item.description === \"string\" ? item.description : null,\n title: typeof item.title === \"string\" ? item.title : null,\n url: typeof item.url === \"string\" ? item.url : null,\n })),\n summary: typeof value.summary === \"string\" && value.summary.trim() ? value.summary.trim() : null,\n }\n}\n\nfunction renderEmptyState(label: string) {\n return (\n <div className=\"rounded-lg border border-dashed border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-4 text-[11px] text-[hsl(var(--muted-foreground))]\">\n {label}\n </div>\n )\n}\n\nexport function SearchRenderer({ toolCall }: ToolRendererProps) {\n const normalizedName = formatToolName(toolCall.name)\n const argsValue = parseJsonValue(toolCall.arguments)\n const args = isPlainObject(argsValue) ? argsValue : null\n const resultStr = getResultText(toolCall.result)\n const errorMessage = extractErrorMessage(resultStr)\n\n if (errorMessage) {\n return (\n <div className=\"rounded-lg border border-red-500/30 bg-red-500/8 px-3 py-2 text-[11px] text-red-300\">\n {errorMessage}\n </div>\n )\n }\n\n if (normalizedName === \"Ls\" || normalizedName === \"Glob\") {\n const items = parseDirectoryItems(resultStr)\n const path = getStringValue(args, \"path\")\n\n return (\n <div className=\"space-y-3\">\n {path ? (\n <div className=\"text-[11px] text-[hsl(var(--muted-foreground))]\">目录:{path}</div>\n ) : null}\n {items.length > 0 ? (\n <div className=\"grid gap-2\">\n {items.map((item) => (\n <div\n key={`${item.name}-${item.size}-${item.isDir}`}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2\"\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n {item.isDir ? (\n <Folder size={14} className=\"shrink-0 text-blue-300\" />\n ) : (\n <FileText size={14} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" />\n )}\n <span className=\"truncate font-mono text-[11px] text-[hsl(var(--foreground))]\">\n {item.name}\n </span>\n </div>\n <span className=\"shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]\">\n {item.isDir ? \"目录\" : formatBytes(item.size) ?? \"文件\"}\n </span>\n </div>\n ))}\n </div>\n ) : (\n renderEmptyState(\"没有可展示的文件结果。\")\n )}\n </div>\n )\n }\n\n if (normalizedName === \"Grep\") {\n const { matches, searchPath } = parseGrepResult(resultStr)\n const pattern = getStringValue(args, \"pattern\")\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center gap-2 text-[11px] text-[hsl(var(--muted-foreground))]\">\n {pattern ? (\n <span className=\"rounded-full bg-[hsl(var(--muted))] px-2 py-0.5 font-mono\">\n {pattern}\n </span>\n ) : null}\n {searchPath ? <span>范围:{searchPath}</span> : null}\n </div>\n {matches.length > 0 ? (\n <div className=\"grid gap-2\">\n {matches.map((match) => (\n <div\n key={`${match.path}-${match.lineNumber}-${match.line}`}\n className=\"rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-2\"\n >\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"truncate font-mono text-[11px] text-[hsl(var(--foreground))]\">\n {match.path}\n </span>\n {match.lineNumber !== null ? (\n <span className=\"shrink-0 text-[10px] text-[hsl(var(--muted-foreground))]\">\n 第 {match.lineNumber} 行\n </span>\n ) : null}\n </div>\n <pre className=\"mt-2 overflow-x-auto whitespace-pre-wrap font-mono text-[11px] text-[hsl(var(--muted-foreground))]\">\n <code>{match.line}</code>\n </pre>\n </div>\n ))}\n </div>\n ) : (\n renderEmptyState(\"没有找到匹配结果。\")\n )}\n </div>\n )\n }\n\n const { results, summary } =\n normalizedName === \"WebFetch\"\n ? parseWebFetchResult(resultStr)\n : { results: parseWebResults(resultStr), summary: null }\n const query = getStringValue(args, \"query\")\n\n return (\n <div className=\"space-y-3\">\n {query ? (\n <div className=\"text-[11px] text-[hsl(var(--muted-foreground))]\">查询:{query}</div>\n ) : null}\n\n {summary ? (\n <div className=\"rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3\">\n <div className=\"mb-2 text-[10px] uppercase tracking-[0.16em] text-[hsl(var(--muted-foreground))]\">\n 摘要\n </div>\n <p className=\"whitespace-pre-wrap text-[11px] leading-5 text-[hsl(var(--foreground))]\">\n {summary}\n </p>\n </div>\n ) : null}\n\n {results.length > 0 ? (\n <div className=\"grid gap-2\">\n {results.map((item, index) => (\n <a\n key={`${item.url ?? item.title ?? \"result\"}-${index}`}\n href={item.url ?? undefined}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(\n \"rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted))]/20 px-3 py-3 transition-colors\",\n item.url && \"hover:border-[hsl(var(--ring))] hover:bg-[hsl(var(--muted))]/35\",\n )}\n >\n <div className=\"flex items-start gap-3\">\n <Globe2 size={15} className=\"mt-0.5 shrink-0 text-blue-300\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-3\">\n <span className=\"line-clamp-2 text-[11px] font-medium text-[hsl(var(--foreground))]\">\n {item.title ?? item.url ?? \"未命名结果\"}\n </span>\n {item.url ? (\n <ExternalLink\n size={12}\n className=\"mt-0.5 shrink-0 text-[hsl(var(--muted-foreground))]\"\n />\n ) : null}\n </div>\n {item.url ? (\n <div className=\"mt-1 truncate font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {item.url}\n </div>\n ) : null}\n {item.description ? (\n <p className=\"mt-2 line-clamp-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]\">\n {item.description}\n </p>\n ) : null}\n </div>\n </div>\n </a>\n ))}\n </div>\n ) : (\n renderEmptyState(\"没有可展示的搜索结果。\")\n )}\n </div>\n )\n}\n","import type { ComponentType } from \"react\"\nimport type { ToolCallInfo } from \"../../../schemas/message\"\nimport { formatToolName } from \"../display-utils\"\nimport { BashRenderer } from \"./BashRenderer\"\nimport { FileEditRenderer } from \"./FileEditRenderer\"\nimport { FileReadRenderer } from \"./FileReadRenderer\"\nimport { SearchRenderer } from \"./SearchRenderer\"\n\nexport interface ToolRendererProps {\n toolCall: ToolCallInfo\n sessionId?: string\n}\n\ntype ToolRenderer = ComponentType<ToolRendererProps>\n\nconst RENDERERS = new Map<string, ToolRenderer>([\n [\"Bash\", BashRenderer],\n [\"BgBash\", BashRenderer],\n [\"Edit\", FileEditRenderer],\n [\"Grep\", SearchRenderer],\n [\"Glob\", SearchRenderer],\n [\"Ls\", SearchRenderer],\n [\"Read\", FileReadRenderer],\n [\"WebFetch\", SearchRenderer],\n [\"WebSearch\", SearchRenderer],\n [\"Write\", FileEditRenderer],\n])\n\nexport function getRenderer(toolName: string): ToolRenderer | null {\n return RENDERERS.get(formatToolName(toolName)) ?? null\n}\n","import { useState } from \"react\"\nimport { getAuthedUrl } from \"../../api/client\"\nimport { extractTextAttachments, getFileParts, getImageParts, getTextContent } from \"../../lib/chat\"\nimport { dispatchPreview, isImageFilename } from \"../../lib/preview-dispatch\"\nimport { parseWhatIfPrompt } from \"../../lib/whatif-prompt\"\nimport type { ChatMessage } from \"../../schemas/message\"\nimport { useSessionStore } from \"../../stores/session-store\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\nimport { AttachmentPreviewDialog } from \"./AttachmentPreviewDialog\"\nimport { ImageLightbox } from \"./ImageLightbox\"\nimport { MessageContextPills } from \"./MessageContextPills\"\nimport { MessageFileAttachmentList } from \"./MessageFileAttachmentList\"\nimport { MessageActions } from \"./MessageActions\"\nimport { TextAttachmentPills } from \"./TextAttachmentPills\"\nimport { WhatIfUserBubble } from \"./WhatIfUserBubble\"\n\nexport type UserChatMessage = ChatMessage & { role: \"user\" }\nexport type ErrorChatMessage = ChatMessage & { role: \"error\" }\n\nexport function isUserMessage(message: ChatMessage): message is UserChatMessage {\n return message.role === \"user\"\n}\n\nexport function isErrorMessage(message: ChatMessage): message is ErrorChatMessage {\n return message.role === \"error\"\n}\n\ninterface UserMessageProps {\n message: UserChatMessage\n}\n\n/**\n * 把内联图片判定统一到 preview-dispatch 的 IMAGE_EXTS(R6 / PR7 fix):\n * 避免\"规则 A 判定非图片 → 落到 pill → 规则 B 判定是图片 → handleTextAttachmentPreview\n * 早返回\"的死胡同,让 svg/heic/apng/avif 这类扩展名也有明确的预览入口。\n * name 先于 uploadedPath:服务端重命名后的路径可能丢掉扩展名,而用户上传时的\n * 原文件名是权威源。\n */\nfunction isImageTextAttachment(name: string, uploadedPath?: string): boolean {\n return isImageFilename(name) || isImageFilename(uploadedPath ?? \"\")\n}\n\nfunction buildSessionFileUrl(sessionId: string, filePath: string): string {\n return getAuthedUrl(\n `/api/sessions/${encodeURIComponent(sessionId)}/files/${encodeURIComponent(filePath)}`,\n )\n}\n\nexport function UserMessageBubble({ message }: UserMessageProps) {\n const activeSessionId = useSessionStore((state) => state.activeSessionId)\n const _textContent = getTextContent(message.content)\n const fileParts = getFileParts(message.content)\n const imageParts = getImageParts(message.content)\n const {\n cleanText,\n attachments: textAttachments,\n contexts: textContexts,\n } = extractTextAttachments(message.content)\n const trimmedClean = cleanText.trim()\n\n // what-if 重跑 prompt:压成小徽章 + 步骤跳转 chip + 用户真正输入气泡。\n // 只有在没有附件/图片时走这条快路——有附件说明是混合消息,保留完整渲染。\n const whatifParsed =\n trimmedClean &&\n imageParts.length === 0 &&\n fileParts.length === 0 &&\n textAttachments.length === 0\n ? parseWhatIfPrompt(cleanText)\n : null\n if (whatifParsed) {\n return (\n <div className=\"flex justify-end\">\n <div className=\"group flex max-w-[72%] flex-col items-end gap-2\">\n <WhatIfUserBubble parsed={whatifParsed} />\n {whatifParsed.userText && (\n <MessageActions\n content={whatifParsed.userText}\n className=\"opacity-0 transition-opacity group-hover:opacity-100\"\n />\n )}\n </div>\n </div>\n )\n }\n // uploadedPath 缺失兜底:历史消息里有些用户上传的附件没有回写 path\n // (早期上传链路 bug),但文件实际上已经落到 session workspace 根目录,\n // 用文件名当路径即可。图片判定靠文件名扩展名,比扫 uploadedPath 更稳。\n const imageTextAttachments = activeSessionId\n ? textAttachments\n .flatMap((attachment) => {\n if (!isImageTextAttachment(attachment.name, attachment.uploadedPath)) {\n return []\n }\n const pathForUrl = attachment.uploadedPath ?? attachment.name\n return [\n {\n ...attachment,\n url: buildSessionFileUrl(activeSessionId, pathForUrl),\n },\n ]\n })\n : []\n const nonImageTextAttachments = textAttachments.filter(\n (attachment) => !isImageTextAttachment(attachment.name, attachment.uploadedPath),\n )\n\n // R6:把两批图片合并成 lightbox 能直接消费的列表,点击任一图片在原位置\n // 打开 lightbox 并定位到对应 index。组合顺序必须和下面渲染的 DOM 一致,\n // 否则 index 会错位。\n const lightboxImages = [\n ...imageParts.map((part) => ({\n src: part.image_url.url,\n alt: \"用户上传的图片\",\n })),\n ...imageTextAttachments.map((attachment) => ({\n src: attachment.url,\n alt: attachment.name || \"用户上传的图片\",\n })),\n ]\n const [lightboxIndex, setLightboxIndex] = useState<number | null>(null)\n\n // R6:文本/未知附件预览 state\n const [preview, setPreview] = useState<{\n filename: string\n url: string\n mode: \"markdown\" | \"text\" | \"default\"\n } | null>(null)\n const handleTextAttachmentPreview = (\n attachment: { name: string; uploadedPath?: string },\n ) => {\n if (!activeSessionId) return\n // uploadedPath 缺失兜底:历史会话里 [附件: xxx] 行没有附带\"已上传到工作区路径\"\n // 后缀时,前端的 extractTextAttachments 拿不到 uploadedPath。但文件实际落在\n // session workspace 根目录,用原文件名当路径即可。和图片附件的兜底策略保持一致。\n const pathForUrl = attachment.uploadedPath ?? attachment.name\n const url = buildSessionFileUrl(activeSessionId, pathForUrl)\n const kind = dispatchPreview(attachment.name, url).kind\n // 图片附件正常情况下已经被 isImageTextAttachment 过滤到 imageTextAttachments,\n // 走 inline lightbox;但如果规则将来再次分叉或边缘情况,兜底也把它塞给\n // ImageLightbox(single-image 模式)而不是静默无反应。\n if (kind === \"image\") {\n const existingIdx = lightboxImages.findIndex((img) => img.src === url)\n if (existingIdx >= 0) {\n setLightboxIndex(existingIdx)\n } else {\n // 动态追加一条 image 到 lightbox(临时):由于 lightboxImages 是每次\n // render 重新计算的派生值,这里写 state 不合适——改成把 attachment 的\n // 信息落到 preview state 以 \"default\" mode 显示,让用户至少能下载。\n setPreview({ filename: attachment.name, url, mode: \"default\" })\n }\n return\n }\n const lower = attachment.name.toLowerCase()\n const mode: \"markdown\" | \"text\" | \"default\" =\n kind === \"text\" ? (lower.endsWith(\".md\") ? \"markdown\" : \"text\") : \"default\"\n setPreview({ filename: attachment.name, url, mode })\n }\n\n return (\n <div className=\"flex justify-end\">\n <div className=\"group flex max-w-[72%] flex-col items-end gap-3\">\n {(imageParts.length > 0 || imageTextAttachments.length > 0) && (\n <div className=\"grid gap-2\">\n {imageParts.map((part, idx) => (\n <button\n type=\"button\"\n key={part.image_url.url}\n onClick={() => setLightboxIndex(idx)}\n className=\"cursor-zoom-in\"\n title=\"查看大图\"\n >\n <img\n src={part.image_url.url}\n alt=\"用户上传的图片\"\n className=\"max-h-64 rounded-xl border border-[hsl(var(--user-msg-border))] object-cover\"\n />\n </button>\n ))}\n {imageTextAttachments.map((attachment, idx) => (\n <button\n type=\"button\"\n key={`${attachment.uploadedPath}:${attachment.name}`}\n onClick={() => setLightboxIndex(imageParts.length + idx)}\n className=\"cursor-zoom-in\"\n title=\"查看大图\"\n >\n <img\n src={attachment.url}\n alt={attachment.name || \"用户上传的图片\"}\n className=\"max-h-64 rounded-xl border border-[hsl(var(--user-msg-border))] object-cover\"\n />\n </button>\n ))}\n </div>\n )}\n {lightboxImages.length > 0 && (\n <ImageLightbox\n open={lightboxIndex != null}\n onOpenChange={(open) => {\n if (!open) setLightboxIndex(null)\n }}\n images={lightboxImages}\n initialIndex={lightboxIndex ?? 0}\n />\n )}\n <MessageFileAttachmentList files={fileParts} />\n <TextAttachmentPills\n attachments={nonImageTextAttachments}\n onPreview={handleTextAttachmentPreview}\n />\n {preview && (\n <AttachmentPreviewDialog\n open={preview != null}\n onOpenChange={(open) => {\n if (!open) setPreview(null)\n }}\n filename={preview.filename}\n url={preview.url}\n mode={preview.mode}\n />\n )}\n <MessageContextPills contexts={textContexts} />\n {trimmedClean && (\n <div className=\"rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]\">\n <MarkdownContent\n className=\"prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0\"\n controls={{ code: true }}\n >\n {cleanText}\n </MarkdownContent>\n </div>\n )}\n {trimmedClean && (\n <MessageActions\n content={trimmedClean}\n className=\"opacity-0 transition-opacity group-hover:opacity-100\"\n />\n )}\n </div>\n </div>\n )\n}\n\nexport function ErrorMessageBlock({ message }: { message: ErrorChatMessage }) {\n const text = getTextContent(message.content)\n const looksLikeModelUnavailable = /no source matches this model|404/i.test(text)\n return (\n <div className=\"flex justify-center\">\n <div className=\"max-w-[85%] border-l-[3px] border-[hsl(var(--destructive))] px-4 py-1 text-sm leading-7 text-[hsl(var(--destructive))]\">\n {text}\n {looksLikeModelUnavailable ? (\n <div className=\"mt-1 opacity-80\">模型可能未启动,请稍后重试。</div>\n ) : null}\n </div>\n </div>\n )\n}\n","/**\n * 按文件扩展名决定预览渲染方式(R6)。\n *\n * 为什么按扩展名不按 MIME:当前消息 schema 里 FileContentPart / TextAttachment\n * 都只存 `name` + `uploadedPath`,没有 mime_type(见 design.md §3.6)。\n * 改 schema 面太大,扩展名在实际数据里足够稳定(前端上传时就是文件名)。\n *\n * 动图(.gif/.webp/.apng/.avif)归为 image,因为浏览器 `<img>` 原生播放。\n * video 类扩展名本期不覆盖(见 design.md §3.6 决策:\"只动图,不视频\")。\n */\n\nconst IMAGE_EXTS = [\n // 静态\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".bmp\",\n \".svg\",\n \".heic\",\n // 动图(<img> 原生播放)\n \".gif\",\n \".webp\",\n \".apng\",\n \".avif\",\n] as const\n\nconst TEXT_EXTS = [\".md\", \".json\", \".txt\", \".yaml\", \".yml\"] as const\n\nexport type PreviewKind = \"image\" | \"text\" | \"default\"\n\nexport interface PreviewDescriptor {\n kind: PreviewKind\n filename: string\n url: string\n}\n\nfunction lower(filename: string): string {\n return filename.toLowerCase()\n}\n\nfunction endsWithAny(name: string, exts: readonly string[]): boolean {\n const n = lower(name)\n for (const ext of exts) {\n if (n.endsWith(ext)) return true\n }\n return false\n}\n\n/**\n * 判断扩展名能不能用 `<img>` 预览(含动图)。\n * 独立导出是为了让调用方可以在不走完整 dispatchPreview 的场景(如 UserMessageBubble\n * 已经在 render 时把图片渲染成 <img>,不需要再走 kind 分派)直接查一次。\n */\nexport function isImageFilename(filename: string): boolean {\n return endsWithAny(filename, IMAGE_EXTS)\n}\n\nexport function isTextFilename(filename: string): boolean {\n return endsWithAny(filename, TEXT_EXTS)\n}\n\nexport function dispatchPreview(filename: string, url: string): PreviewDescriptor {\n if (isImageFilename(filename)) return { kind: \"image\", filename, url }\n if (isTextFilename(filename)) return { kind: \"text\", filename, url }\n return { kind: \"default\", filename, url }\n}\n","/**\n * 把 whatif-rerun 后端组装的 prompt 文本解析成可折叠展示的结构。\n *\n * 当前后端格式(`host/orchestrator/whatif_rerun.py::_compose_whatif_prompt`):\n *\n * 以下消息和 step 产物标记为 deprecated_by_rerun,请基于最新用户假设从 step{N} 开始完整重新推演,不要复用旧结论。\n *\n * [引用]\n * [步骤{n} · {label}]\n * {snapshot markdown…(内部允许空行)}\n * [步骤{m} · {label}]\n * {snapshot markdown…}\n *\n * [用户输入]\n * {用户真正输入的文本}\n *\n * Legacy 格式(历史 session 里没有 `[用户输入]` 标签):\n * …最后一条 snapshot 末尾…\n * <空行>\n * {用户真正输入的文本}\n *\n * Legacy 情况下用\"从末尾反向扫描第一段连续空行\"做切分。markdown 末尾段落\n * 被误吃的风险可接受——总比让用户完全看不到自己的输入好。\n */\n\nexport interface WhatIfQuote {\n stepNumber: number | null\n label: string\n snapshot: string\n}\n\nexport interface ParsedWhatIfPrompt {\n fromStep: number | null\n quotes: WhatIfQuote[]\n userText: string\n}\n\nexport interface BuildWhatIfPromptInput {\n fromStep: number\n quotes: Array<{\n stepNumber?: number | null\n label?: string | null\n snapshot?: string | null\n }>\n userText: string\n}\n\nconst HEADER_RE =\n /^以下消息和 step 产物标记为 deprecated_by_rerun,请基于最新用户假设从 step(\\d+) 开始完整重新推演,不要复用旧结论。$/\n\nconst QUOTE_HEADER_RE = /^\\[步骤(\\d+)\\s*·\\s*(.+?)\\]$/\nconst USER_INPUT_TAG = \"[用户输入]\"\n\nexport function buildWhatIfPrompt({\n fromStep,\n quotes,\n userText,\n}: BuildWhatIfPromptInput): string {\n const lines: string[] = [\n `以下消息和 step 产物标记为 deprecated_by_rerun,请基于最新用户假设从 step${fromStep} 开始完整重新推演,不要复用旧结论。`,\n ]\n if (quotes.length > 0) {\n lines.push(\"\")\n lines.push(\"[引用]\")\n for (const quote of quotes) {\n const stepNumber = Number.isFinite(quote.stepNumber) ? quote.stepNumber : null\n const label = quote.label?.trim() || \"卡片\"\n lines.push(`[步骤${stepNumber ?? \"?\"} · ${label}]`)\n lines.push(quote.snapshot ?? \"\")\n }\n }\n if (userText) {\n lines.push(\"\")\n lines.push(USER_INPUT_TAG)\n lines.push(userText)\n }\n return lines.join(\"\\n\")\n}\n\nexport function parseWhatIfPrompt(text: string): ParsedWhatIfPrompt | null {\n const trimmed = text.replace(/\\r\\n/g, \"\\n\").trimEnd()\n const lines = trimmed.split(\"\\n\")\n if (lines.length === 0) return null\n\n const headerMatch = lines[0].match(HEADER_RE)\n if (!headerMatch) return null\n\n const fromStep = Number.parseInt(headerMatch[1], 10)\n\n const userTagIdx = lines.indexOf(USER_INPUT_TAG)\n const hasUserTag = userTagIdx >= 0\n const quoteBlockEndExclusive = hasUserTag ? userTagIdx : lines.length\n\n // 收集 [引用] 段内的所有 quote header 行号\n const quoteHeaderIdxs: number[] = []\n let refBlockFound = false\n for (let i = 1; i < quoteBlockEndExclusive; i++) {\n if (!refBlockFound && lines[i].trim() === \"[引用]\") {\n refBlockFound = true\n continue\n }\n if (refBlockFound && lines[i].match(QUOTE_HEADER_RE)) {\n quoteHeaderIdxs.push(i)\n }\n }\n\n // Legacy 模式下从最后一条 snapshot 的末尾反向找\"第一段连续空行\"作为\n // snapshot / userText 分隔点。有 [用户输入] 标签时不走这条。\n let legacyUserTextStart = -1\n if (!hasUserTag && quoteHeaderIdxs.length > 0) {\n const lastSnapshotStart = quoteHeaderIdxs[quoteHeaderIdxs.length - 1] + 1\n // 从末尾(lines.length - 1)往前扫,找第一段连续空行\n let i = lines.length - 1\n // 跳过末尾可能的空行\n while (i >= lastSnapshotStart && lines[i].trim() === \"\") i -= 1\n // 回扫直到遇到空行\n while (i >= lastSnapshotStart && lines[i].trim() !== \"\") i -= 1\n // i 此时要么 < lastSnapshotStart(没找到空行,说明整个尾部都是一段文本,\n // 保留作为 snapshot 一部分),要么指向空行\n if (i >= lastSnapshotStart) {\n legacyUserTextStart = i + 1\n }\n }\n\n const quotes: WhatIfQuote[] = quoteHeaderIdxs.map((headerIdx, k) => {\n const m = lines[headerIdx].match(QUOTE_HEADER_RE)!\n const isLast = k + 1 >= quoteHeaderIdxs.length\n let endIdxExclusive: number\n if (!isLast) {\n endIdxExclusive = quoteHeaderIdxs[k + 1]\n } else if (legacyUserTextStart >= 0) {\n endIdxExclusive = legacyUserTextStart\n } else {\n endIdxExclusive = quoteBlockEndExclusive\n }\n const snapshotLines = lines.slice(headerIdx + 1, endIdxExclusive)\n while (snapshotLines.length && snapshotLines[snapshotLines.length - 1].trim() === \"\") {\n snapshotLines.pop()\n }\n return {\n stepNumber: Number.parseInt(m[1], 10),\n label: m[2].trim(),\n snapshot: snapshotLines.join(\"\\n\"),\n }\n })\n\n let userText = \"\"\n if (hasUserTag) {\n const rest = lines.slice(userTagIdx + 1)\n while (rest.length > 0 && rest[0].trim() === \"\") rest.shift()\n while (rest.length > 0 && rest[rest.length - 1].trim() === \"\") rest.pop()\n userText = rest.join(\"\\n\")\n } else if (legacyUserTextStart >= 0) {\n const rest = lines.slice(legacyUserTextStart)\n while (rest.length > 0 && rest[0].trim() === \"\") rest.shift()\n while (rest.length > 0 && rest[rest.length - 1].trim() === \"\") rest.pop()\n userText = rest.join(\"\\n\")\n }\n\n return {\n fromStep: Number.isFinite(fromStep) ? fromStep : null,\n quotes,\n userText,\n }\n}\n","import { Download, X } from \"lucide-react\"\nimport { useEffect } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { useQuery } from \"@tanstack/react-query\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\n\n/**\n * R6:用户上传的附件(文本 / 未知类型)预览弹窗。\n *\n * 图片走独立的 ImageLightbox;本组件处理:\n * - .md → markdown 渲染\n * - .json / .txt / .yaml / .yml / 其他文本 → 纯文本等宽展示\n * - 不可在浏览器内渲染的类型 → 下载链接兜底\n *\n * 无 URL 时兜底为只显示文件名 + 下载入口。\n */\n\ninterface Props {\n open: boolean\n onOpenChange: (open: boolean) => void\n filename: string\n /**\n * 由调用方用 `getAuthedUrl()` 构造的完整 URL(baseUrl + 路径 + ?token=…)。\n * 内部 fetch 直接用原串,**不**再走 `apiFetchText` —— 否则会二次拼 baseUrl,\n * 在独立前后端部署时会得到形如 `http://api.xxxhttp://api.xxx/…` 的非法 URL。\n * token 靠 query 字符串携带,因此也不需要再挂 Authorization header。\n */\n url: string | null\n /** text-like 视为\"可文本预览\";其他只显示下载按钮。 */\n mode: \"markdown\" | \"text\" | \"default\"\n}\n\nexport function AttachmentPreviewDialog({ open, onOpenChange, filename, url, mode }: Props) {\n useEffect(() => {\n if (!open) return\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onOpenChange(false)\n }\n window.addEventListener(\"keydown\", handleKey)\n return () => window.removeEventListener(\"keydown\", handleKey)\n }, [open, onOpenChange])\n\n const { data: content, error } = useQuery({\n queryKey: [\"attachment-preview\", url, mode],\n queryFn: async ({ signal }) => {\n if (!url) return null\n const res = await fetch(url, {\n signal,\n credentials: \"include\",\n })\n if (!res.ok) {\n const body = await res.text().catch(() => \"\")\n throw new Error(`加载失败(HTTP ${res.status})${body ? `:${body.slice(0, 200)}` : \"\"}`)\n }\n return res.text()\n },\n enabled: open && url != null && (mode === \"markdown\" || mode === \"text\"),\n staleTime: 60_000,\n })\n\n if (!open) return null\n\n const body = (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4\"\n onClick={() => onOpenChange(false)}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") onOpenChange(false)\n }}\n // biome-ignore lint/a11y/useSemanticElements: 原生 <dialog> 需要 showModal() + 内置 backdrop,本组件用外层 div 充当点击关闭的 backdrop,不走 modal API。\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"attachment-preview-title\"\n >\n <div\n className=\"max-h-[90vh] w-full max-w-3xl overflow-hidden rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--background))] shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <div className=\"flex items-center justify-between border-b border-[hsl(var(--border))] px-4 py-3\">\n <h3 id=\"attachment-preview-title\" className=\"truncate text-sm font-semibold text-[hsl(var(--foreground))]\">\n {filename}\n </h3>\n <div className=\"flex items-center gap-1\">\n {url && (\n <a\n href={url}\n download={filename}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n title=\"下载\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n >\n <Download size={14} />\n </a>\n )}\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n title=\"关闭\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]\"\n >\n <X size={14} />\n </button>\n </div>\n </div>\n <div className=\"max-h-[calc(90vh-56px)] overflow-auto px-4 py-3 text-sm text-[hsl(var(--foreground))]\">\n {renderContent({ mode, url, content, error })}\n </div>\n </div>\n </div>\n )\n\n return createPortal(body, document.body)\n}\n\nfunction renderContent({\n mode,\n url,\n content,\n error,\n}: {\n mode: \"markdown\" | \"text\" | \"default\"\n url: string | null\n content: string | null | undefined\n error: unknown\n}) {\n if (!url) {\n return <p className=\"text-[hsl(var(--muted-foreground))]\">此附件暂无可用预览地址。</p>\n }\n if (mode === \"default\") {\n return (\n <p className=\"text-[hsl(var(--muted-foreground))]\">\n 此类型暂不支持内嵌预览。请点击右上角\n <span className=\"mx-1 font-medium text-[hsl(var(--foreground))]\">下载</span>\n 按钮查看。\n </p>\n )\n }\n if (error) {\n return <p className=\"text-[hsl(var(--destructive))]\">加载失败:{String((error as Error)?.message ?? error)}</p>\n }\n if (content == null) {\n return <p className=\"text-[hsl(var(--muted-foreground))]\">加载中…</p>\n }\n if (mode === \"markdown\") {\n return (\n <MarkdownContent className=\"prose prose-sm prose-invert max-w-none\">{content}</MarkdownContent>\n )\n }\n return (\n <pre className=\"whitespace-pre-wrap font-mono text-xs leading-relaxed\">{content}</pre>\n )\n}\n","import { Bookmark } from \"lucide-react\"\nimport type { ParsedTextContext } from \"../../lib/chat\"\n\ninterface MessageContextPillsProps {\n contexts: ParsedTextContext[]\n}\n\nexport function MessageContextPills({ contexts }: MessageContextPillsProps) {\n if (contexts.length === 0) return null\n\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {contexts.map((ctx, index) => (\n <div\n key={`${ctx.label}:${index}`}\n className=\"flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--primary)/0.25)] bg-[hsl(var(--primary)/0.1)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary)/0.85)]\"\n title={ctx.content}\n >\n <Bookmark size={12} className=\"shrink-0 text-[hsl(var(--primary)/0.65)]\" />\n <span className=\"max-w-56 truncate\">{ctx.label}</span>\n </div>\n ))}\n </div>\n )\n}\n","import { Archive, File, FileCode2, FileText, Film, Music } from \"lucide-react\"\nimport type { FileContentPart } from \"../../schemas/message\"\nimport { cn } from \"../../lib/utils\"\n\nfunction getFileIcon(fileName: string) {\n const lowerName = fileName.toLowerCase()\n\n if (/\\.(zip|rar|7z|tar|gz|bz2|xz)$/.test(lowerName)) {\n return Archive\n }\n if (/\\.(ts|tsx|js|jsx|py|rb|go|rs|java|kt|swift|c|cc|cpp|h|hpp|css|scss|html|json|yaml|yml|toml|md)$/.test(lowerName)) {\n return FileCode2\n }\n if (/\\.(mp3|wav|flac|m4a|aac|ogg)$/.test(lowerName)) {\n return Music\n }\n if (/\\.(mp4|mov|mkv|avi|webm|wmv)$/.test(lowerName)) {\n return Film\n }\n if (/\\.(txt|pdf|doc|docx|rtf|odt)$/.test(lowerName)) {\n return FileText\n }\n return File\n}\n\ninterface MessageFileAttachmentListProps {\n files: FileContentPart[]\n className?: string\n /**\n * R6:点击 pill 时的预览回调。不传时 pill 保持纯展示(向后兼容,Home /\n * ChatDev 等复用点零改动)。调用方自己决定 URL 来源 + 渲染什么(lightbox /\n * FilePreviewDialog / 下载等)。\n */\n onPreview?: (file: FileContentPart) => void\n}\n\nexport function MessageFileAttachmentList({\n files,\n className,\n onPreview,\n}: MessageFileAttachmentListProps) {\n if (files.length === 0) {\n return null\n }\n\n const pillClass =\n \"flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-1 text-[11px] text-[hsl(var(--foreground))]\"\n\n return (\n <div className={cn(\"flex flex-wrap gap-1.5\", className)}>\n {files.map((file) => {\n const Icon = getFileIcon(file.name)\n const key = `${file.name}-${file.data.slice(0, 32)}`\n const content = (\n <>\n <Icon size={12} className=\"shrink-0 text-[hsl(var(--muted-foreground))]\" />\n <span className=\"max-w-32 truncate\">{file.name}</span>\n </>\n )\n if (onPreview) {\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => onPreview(file)}\n className={cn(pillClass, \"cursor-pointer transition-colors hover:border-[hsl(var(--ring)/0.5)]\")}\n title={`预览 ${file.name}`}\n >\n {content}\n </button>\n )\n }\n return (\n <div key={key} className={pillClass} title={file.name}>\n {content}\n </div>\n )\n })}\n </div>\n )\n}\n","import { Check, Copy } from \"lucide-react\"\nimport { useState } from \"react\"\nimport { cn, copyToClipboard } from \"../../lib/utils\"\n\ninterface Props {\n content: string\n className?: string\n}\n\nexport function MessageActions({ content, className }: Props) {\n const [copied, setCopied] = useState(false)\n\n const handleCopy = async () => {\n const ok = await copyToClipboard(content)\n if (ok) {\n setCopied(true)\n setTimeout(() => setCopied(false), 2000)\n }\n }\n\n return (\n <div className={cn(\"flex items-center gap-1 mt-1.5\", className)}>\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] transition-colors\",\n copied\n ? \"text-[hsl(var(--primary))]\"\n : \"text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))]\",\n )}\n >\n {copied ? <Check size={12} /> : <Copy size={12} />}\n <span>{copied ? \"已复制\" : \"复制\"}</span>\n </button>\n </div>\n )\n}\n","import { Archive, File, FileCode2, FileText, Film, Music, FileSpreadsheet, Image } from \"lucide-react\"\nimport type { ParsedTextAttachment } from \"../../lib/chat\"\n\nfunction getFileIcon(fileName: string) {\n const lower = fileName.toLowerCase()\n if (/\\.(zip|rar|7z|tar|gz)$/.test(lower)) return Archive\n if (/\\.(ts|tsx|js|jsx|py|go|rs|java|html|json|yaml|yml|css)$/.test(lower)) return FileCode2\n if (/\\.(mp3|wav|flac|m4a|aac|ogg)$/.test(lower)) return Music\n if (/\\.(mp4|mov|mkv|avi|webm)$/.test(lower)) return Film\n if (/\\.(png|jpg|jpeg|gif|svg|webp|bmp)$/.test(lower)) return Image\n if (/\\.(xlsx?|csv)$/.test(lower)) return FileSpreadsheet\n if (/\\.(txt|pdf|docx?|rtf|md)$/.test(lower)) return FileText\n return File\n}\n\ninterface TextAttachmentPillsProps {\n attachments: ParsedTextAttachment[]\n /**\n * R6:点击 pill 时的预览回调。不传时保持纯展示(向后兼容)。\n */\n onPreview?: (attachment: ParsedTextAttachment) => void\n}\n\nexport function TextAttachmentPills({ attachments, onPreview }: TextAttachmentPillsProps) {\n if (attachments.length === 0) return null\n\n const pillClass =\n \"flex shrink-0 items-center gap-1.5 rounded-full border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--primary)/0.08)] px-2.5 py-1 text-[11px] text-[hsl(var(--primary)/0.8)]\"\n\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {attachments.map((att, index) => {\n const Icon = getFileIcon(att.name)\n const key = `${att.uploadedPath ?? att.name}:${att.name}:${index}`\n const content = (\n <>\n <Icon size={12} className=\"shrink-0 text-[hsl(var(--primary)/0.6)]\" />\n <span className=\"max-w-40 truncate\">{att.name}</span>\n </>\n )\n if (onPreview) {\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => onPreview(att)}\n className={`${pillClass} cursor-pointer transition-colors hover:border-[hsl(var(--primary)/0.45)]`}\n title={`预览 ${att.name}`}\n >\n {content}\n </button>\n )\n }\n return (\n <div key={key} className={pillClass} title={att.name}>\n {content}\n </div>\n )\n })}\n </div>\n )\n}\n","import { RefreshCcw } from \"lucide-react\"\nimport { MarkdownContent } from \"../markdown/MarkdownContent\"\nimport type { ParsedWhatIfPrompt } from \"../../lib/whatif-prompt\"\nimport { useWhatIfQuoteContext } from \"./whatif-quote-context\"\n\ninterface Props {\n parsed: ParsedWhatIfPrompt\n /** 点击引用 chip 时回调。如果未传,尝试从 WhatIfQuoteProvider 取;两者都无则 chip 不可点。 */\n onQuoteClick?: (stepNumber: number) => void\n}\n\n/**\n * what-if 重跑 prompt 的紧凑展示:小徽章 + 步骤跳转 chip + 用户真正输入气泡。\n * 原 prompt 里夹带的 snapshot markdown 不再全量展开——它们对 LLM 有用,\n * 但对用户只会造成噪音;点 chip 可以跳到对应 step 卡查看。\n */\nexport function WhatIfUserBubble({ parsed, onQuoteClick }: Props) {\n const { onJumpToStep } = useWhatIfQuoteContext()\n const handleQuoteClick = onQuoteClick ?? onJumpToStep\n const { fromStep, quotes, userText } = parsed\n\n return (\n <div className=\"flex flex-col items-end gap-2\">\n <div className=\"flex items-center gap-1.5 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.5)] px-2.5 py-0.5 text-[10px] text-[hsl(var(--muted-foreground))]\">\n <RefreshCcw size={10} />\n <span>{fromStep != null ? `重跑自 step ${fromStep}` : \"重跑\"}</span>\n </div>\n\n {quotes.length > 0 && (\n <div className=\"flex flex-wrap justify-end gap-1.5\">\n {quotes.map((q, i) => {\n const clickable = q.stepNumber != null && !!handleQuoteClick\n const label =\n q.stepNumber != null ? `步骤${q.stepNumber} · ${q.label}` : q.label\n return (\n <button\n key={`${q.stepNumber ?? \"x\"}-${i}`}\n type=\"button\"\n disabled={!clickable}\n onClick={() => clickable && handleQuoteClick!(q.stepNumber!)}\n className=\"inline-flex items-center gap-1 rounded-full border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2.5 py-0.5 text-[11px] text-[hsl(var(--muted-foreground))] transition-colors hover:border-[hsl(var(--ring)/0.5)] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] disabled:cursor-default disabled:hover:border-[hsl(var(--border))] disabled:hover:bg-[hsl(var(--card))]\"\n title={clickable ? \"跳转到对应步骤卡片\" : undefined}\n >\n <span>↳</span>\n <span className=\"max-w-[14rem] truncate\">{label}</span>\n </button>\n )\n })}\n </div>\n )}\n\n {userText && (\n <div className=\"rounded-2xl border border-[hsl(var(--user-msg-border))] bg-[hsl(var(--user-msg-bg))] px-4 py-2.5 text-sm leading-relaxed text-[hsl(var(--user-msg-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]\">\n <MarkdownContent\n className=\"prose prose-sm prose-invert max-w-none [&_li>p]:inline [&_p]:mb-3 [&_p:last-child]:mb-0\"\n controls={{ code: true }}\n >\n {userText}\n </MarkdownContent>\n </div>\n )}\n </div>\n )\n}\n","import { createContext, type ReactNode, useContext, useMemo } from \"react\"\n\ninterface WhatIfQuoteContextValue {\n onJumpToStep?: (stepNumber: number) => void\n}\n\nconst WhatIfQuoteContext = createContext<WhatIfQuoteContextValue>({})\n\n/**\n * Provide a callback used by `WhatIfUserBubble`'s quote chip to navigate to\n * the corresponding step card. Host apps (ship-attack) mount this provider\n * near the chat view and wire it to their step selector.\n */\nexport function WhatIfQuoteProvider({\n onJumpToStep,\n children,\n}: {\n onJumpToStep?: (stepNumber: number) => void\n children: ReactNode\n}) {\n const value = useMemo(() => ({ onJumpToStep }), [onJumpToStep])\n return <WhatIfQuoteContext.Provider value={value}>{children}</WhatIfQuoteContext.Provider>\n}\n\nexport function useWhatIfQuoteContext(): WhatIfQuoteContextValue {\n return useContext(WhatIfQuoteContext)\n}\n","import { ChevronDown, ChevronRight, Loader2, Square, XCircle } from \"lucide-react\"\nimport { useState } from \"react\"\nimport { getSocket } from \"../../api/socket\"\nimport type { ArchivedFileInfo, ArchivedToolCallInfo, CompactionInfo } from \"../../schemas/message\"\nimport { useChatStore } from \"../../stores/chat-store\"\nimport { cn } from \"../../lib/utils\"\n\nconst PERCENT_FORMATTER = new Intl.NumberFormat(\"zh-CN\", {\n style: \"percent\",\n maximumFractionDigits: 0,\n})\nfunction formatTokens(value: number | null | undefined) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return \"0\"\n }\n const k = value / 1000\n if (k < 1) {\n return `${Math.round(value)}`\n }\n return k < 10 ? `${k.toFixed(1)}k` : `${Math.round(k)}k`\n}\n\nfunction formatSavedRatio(value: number | null | undefined) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return \"0%\"\n }\n return PERCENT_FORMATTER.format(Math.max(0, Math.min(1, value)))\n}\n\nfunction shortId(compactionId: string | undefined) {\n if (!compactionId) {\n return \"------\"\n }\n return compactionId.slice(0, 6)\n}\n\ntype CompactionCardState = CompactionInfo & {\n status: \"streaming\" | \"completed\" | \"paused\" | \"failed\" | \"interrupted\"\n}\n\nconst ARCHIVED_TOOL_LABELS: Record<string, string> = {\n GetSkillContent: \"读取技能内容\",\n SearchSkills: \"搜索技能\",\n ListSkillTools: \"列出技能工具\",\n LoadSkillTools: \"加载技能工具\",\n}\n\nfunction getArchivedToolLabel(item: ArchivedToolCallInfo) {\n const name = item.tool_name?.trim()\n if (!name) {\n return \"工具调用\"\n }\n return ARCHIVED_TOOL_LABELS[name] ?? name\n}\n\nfunction getArchivePath(item: ArchivedToolCallInfo, files: ArchivedFileInfo[]) {\n if (item.archive_path) {\n return item.archive_path\n }\n return files.find((file) => file.tool_name === item.tool_name)?.relative_path ?? null\n}\n\nfunction isGenericArchiveSummary(summary: string | null | undefined) {\n return /^已归档\\s*\\d+\\s*个大型工具结果。?$/.test(summary?.trim() ?? \"\")\n}\n\nexport function CompactionCard({\n sessionId,\n compaction,\n status,\n}: {\n sessionId: string\n compaction?: CompactionInfo | null\n status?: \"streaming\" | \"completed\" | \"paused\" | \"failed\" | \"interrupted\"\n}) {\n const activeCompaction = useChatStore((state) => state.activeCompactions[sessionId] ?? null)\n const source = compaction\n ? ({\n ...compaction,\n status: status ?? \"completed\",\n } satisfies CompactionCardState)\n : activeCompaction\n const [expanded, setExpanded] = useState(false)\n\n if (!source || !source.compaction_id) {\n return null\n }\n\n const canCancel = source.status === \"streaming\"\n const archivedFiles = source.archived_files ?? []\n const archivedToolCalls = source.archived_tool_calls ?? []\n const archivedCount = source.archived_count ?? archivedToolCalls.length ?? archivedFiles.length\n const hasSummary =\n typeof source.summary_full === \"string\" &&\n source.summary_full.trim().length > 0 &&\n !isGenericArchiveSummary(source.summary_full)\n const hasFailureReason = source.status === \"failed\" && Boolean(source.failure_reason)\n const canExpand =\n (source.status === \"completed\" && (hasSummary || archivedToolCalls.length > 0)) ||\n hasFailureReason\n\n return (\n <div className=\"text-xs text-[hsl(var(--muted-foreground))]\">\n <div className=\"flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n onClick={() => canExpand && setExpanded((prev) => !prev)}\n className={cn(\n \"inline-flex min-w-0 items-center gap-1 rounded-md px-1.5 py-0.5 text-[11px] text-[hsl(var(--muted-foreground))]/65 transition-colors hover:bg-[hsl(var(--muted))]/60 hover:text-[hsl(var(--foreground))]\",\n !canExpand && \"cursor-default hover:bg-transparent hover:text-[hsl(var(--muted-foreground))]/65\",\n )}\n aria-expanded={expanded}\n >\n {canExpand ? (\n expanded ? (\n <ChevronDown size={12} className=\"shrink-0\" />\n ) : (\n <ChevronRight size={12} className=\"shrink-0\" />\n )\n ) : null}\n <span>\n {source.status === \"streaming\" ? (\n <span className=\"inline-flex items-center gap-1\">\n <Loader2 size={12} className=\"animate-spin\" />\n 正在压缩上下文\n </span>\n ) : source.status === \"failed\" ? (\n <span className=\"inline-flex items-center gap-1 text-rose-500/80\">\n <XCircle size={12} />\n 上下文压缩失败\n </span>\n ) : source.status === \"interrupted\" ? (\n <span className=\"inline-flex items-center gap-1 text-amber-500/80\">\n <Square size={11} />\n 上下文压缩已取消\n </span>\n ) : (\n \"上下文已压缩\"\n )}\n </span>\n </button>\n\n {canCancel ? (\n <button\n type=\"button\"\n onClick={() => getSocket().stop(sessionId)}\n className=\"shrink-0 rounded-md border border-current/15 px-2 py-0.5 text-[11px] transition-opacity hover:opacity-80\"\n >\n 取消整理\n </button>\n ) : null}\n </div>\n\n {expanded ? (\n <div className=\"mt-1 max-w-3xl rounded-lg border border-[hsl(var(--border))]/70 bg-[hsl(var(--card))]/80 px-3 py-2 text-[11px] leading-relaxed shadow-sm\">\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1 text-[hsl(var(--muted-foreground))]\">\n <span>#{shortId(source.compaction_id)}</span>\n <span>\n 节省 {formatSavedRatio(source.saved_ratio)}({formatTokens(source.tokens_before)} →{\" \"}\n {formatTokens(source.tokens_after)} token)\n </span>\n <span>归档 {archivedCount} 个工具结果</span>\n </div>\n\n {archivedToolCalls.length > 0 ? (\n <div className=\"mt-2 space-y-1.5\">\n {archivedToolCalls.map((item, index) => {\n const archivePath = getArchivePath(item, archivedFiles)\n return (\n <div\n key={item.tool_call_id || item.entry_id || `${item.tool_name}-${index}`}\n className=\"rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/35 px-2 py-1.5\"\n >\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-[hsl(var(--foreground))]\">\n <span className=\"font-medium\">{getArchivedToolLabel(item)}</span>\n {item.tool_call_id ? (\n <span className=\"font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {item.tool_call_id}\n </span>\n ) : null}\n </div>\n {archivePath ? (\n <div className=\"mt-0.5 break-all font-mono text-[10px] text-[hsl(var(--muted-foreground))]\">\n {archivePath}\n </div>\n ) : null}\n </div>\n )\n })}\n </div>\n ) : null}\n\n {hasSummary ? (\n <pre className=\"mt-2 max-h-[360px] overflow-auto whitespace-pre-wrap rounded-md border border-[hsl(var(--border))]/70 bg-[hsl(var(--muted))]/25 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-[hsl(var(--foreground))]\">\n {source.summary_full}\n </pre>\n ) : null}\n\n {source.status === \"failed\" && source.failure_reason ? (\n <div className=\"mt-2 text-rose-500/90\">失败原因:{source.failure_reason}</div>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n","import { AlertTriangle } from \"lucide-react\"\nimport { Component, type ErrorInfo, type ReactNode } from \"react\"\n\ninterface Props {\n label: string\n details?: string\n resetKey?: string\n children: ReactNode\n}\n\ninterface State {\n componentStack: string\n error: Error | null\n}\n\nfunction getFirstComponentName(componentStack: string): string | null {\n const match = componentStack.match(/\\n\\s+at\\s+([^\\s(]+)/)\n return match?.[1] ?? null\n}\n\nexport class RenderErrorBoundary extends Component<Props, State> {\n state: State = {\n componentStack: \"\",\n error: null,\n }\n\n static getDerivedStateFromError(error: Error): State {\n return {\n componentStack: \"\",\n error,\n }\n }\n\n componentDidCatch(error: Error, info: ErrorInfo) {\n const componentStack = info.componentStack ?? \"\"\n console.error(`${this.props.label} render error:`, error, info)\n this.setState({ componentStack })\n }\n\n componentDidUpdate(prevProps: Props) {\n if (this.state.error && prevProps.resetKey !== this.props.resetKey) {\n this.setState({ componentStack: \"\", error: null })\n }\n }\n\n render() {\n const { children, details, label } = this.props\n const { componentStack, error } = this.state\n\n if (!error) {\n return children\n }\n\n const componentName = getFirstComponentName(componentStack)\n\n return (\n <div className=\"rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100\">\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className=\"mt-0.5 h-4 w-4 shrink-0 text-amber-300\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"font-medium\">{label}渲染失败</div>\n <div className=\"mt-1 break-words text-xs leading-5 text-amber-100/75\">\n {componentName ? `组件:${componentName}。` : null}\n {error.message || \"发生了未预期的渲染错误。\"}\n </div>\n {details ? (\n <div className=\"mt-1 truncate text-xs text-amber-100/55\">{details}</div>\n ) : null}\n </div>\n </div>\n </div>\n )\n }\n}\n","import {\n Bot,\n FilePenLine,\n FileSearch,\n Globe,\n LoaderCircle,\n MessageSquareText,\n Search,\n TerminalSquare,\n WandSparkles,\n type LucideIcon,\n} from \"lucide-react\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport type { ChatMessage, ToolCallInfo } from \"../../schemas/message\"\nimport { useRuntimeStore } from \"../../stores/runtime-store\"\nimport { formatToolName, getToolDisplayLabel } from \"./display-utils\"\n\nconst EMPTY_EVENTS = [] as const\n\nfunction formatElapsedDuration(durationMs: number | null) {\n if (durationMs == null) return null\n\n const totalSeconds = Math.max(0, Math.floor(durationMs / 1000))\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) {\n return `${hours}:${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`\n }\n\n return `${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`\n}\n\nfunction getToolIcon(toolCall: ToolCallInfo): LucideIcon {\n switch (formatToolName(toolCall.name)) {\n case \"Agent\":\n return Bot\n case \"Bash\":\n case \"BgBash\":\n return TerminalSquare\n case \"Read\":\n return FileSearch\n case \"Write\":\n case \"Edit\":\n return FilePenLine\n case \"Ls\":\n case \"Glob\":\n case \"Grep\":\n return Search\n case \"WebSearch\":\n case \"WebFetch\":\n return Globe\n case \"AskUserQuestion\":\n return MessageSquareText\n default:\n return WandSparkles\n }\n}\n\nfunction getLatestPendingTool(messages: ChatMessage[]) {\n const toolCalls = messages.flatMap((message) => message.tool_calls ?? [])\n for (let index = toolCalls.length - 1; index >= 0; index -= 1) {\n if (toolCalls[index].status === \"pending\" || toolCalls[index].status === \"awaiting_answer\") {\n return toolCalls[index]\n }\n }\n return null\n}\n\nfunction getCurrentAction(messages: ChatMessage[]) {\n const pendingTool = getLatestPendingTool(messages)\n if (pendingTool) {\n return {\n Icon: getToolIcon(pendingTool),\n label:\n pendingTool.status === \"awaiting_answer\"\n ? `等待你回答:${getToolDisplayLabel(pendingTool)}`\n : `正在${getToolDisplayLabel(pendingTool)}`,\n }\n }\n\n const lastMessage = messages[messages.length - 1]\n if (lastMessage?.reasoning?.trim()) {\n return {\n Icon: WandSparkles,\n label: \"正在整理思路\",\n }\n }\n\n return {\n Icon: LoaderCircle,\n label: \"正在生成回复\",\n }\n}\n\nfunction getTurnStartedAt(events: readonly { type: string; timestamp: string }[]) {\n for (let index = events.length - 1; index >= 0; index -= 1) {\n if (events[index].type !== \"chat:start\") continue\n const timestamp = new Date(events[index].timestamp).getTime()\n if (!Number.isNaN(timestamp)) {\n return timestamp\n }\n }\n return null\n}\n\nfunction useElapsedDuration(startedAt: number | null, active: boolean) {\n const [now, setNow] = useState(() => Date.now())\n\n useEffect(() => {\n if (!active || startedAt == null) {\n return\n }\n\n setNow(Date.now())\n const timer = window.setInterval(() => {\n setNow(Date.now())\n }, 1000)\n\n return () => window.clearInterval(timer)\n }, [active, startedAt])\n\n if (!active || startedAt == null) {\n return null\n }\n\n return Math.max(0, now - startedAt)\n}\n\ninterface StickyStatusBarProps {\n sessionId: string\n messages: ChatMessage[]\n isStreaming: boolean\n isLastTurn: boolean\n onJumpToLatest: () => void\n}\n\nexport function StickyStatusBar({\n sessionId,\n messages,\n isStreaming,\n isLastTurn,\n onJumpToLatest,\n}: StickyStatusBarProps) {\n const events = useRuntimeStore((state) => state.events[sessionId] ?? EMPTY_EVENTS)\n const startedAt = useMemo(() => getTurnStartedAt(events), [events])\n const elapsedDuration = useElapsedDuration(startedAt, isStreaming && isLastTurn)\n const action = useMemo(() => getCurrentAction(messages), [messages])\n\n if (!isStreaming || !isLastTurn) {\n return null\n }\n\n const elapsedLabel = formatElapsedDuration(elapsedDuration)\n const Icon = action.Icon\n\n return (\n <button\n type=\"button\"\n onClick={onJumpToLatest}\n className=\"sticky top-0 z-20 mb-4 flex w-full items-center gap-3 rounded-2xl border border-[hsl(var(--primary)/0.2)] bg-[hsl(var(--background)/0.92)] px-4 py-3 text-left shadow-[0_12px_32px_-24px_hsl(var(--foreground)/0.6)] backdrop-blur\"\n >\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-[hsl(var(--primary)/0.12)] text-[hsl(var(--primary))]\">\n <Icon size={18} className={Icon === LoaderCircle ? \"animate-spin\" : undefined} />\n </span>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium text-[hsl(var(--foreground))]\">\n {action.label}\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-2 text-xs text-[hsl(var(--muted-foreground))]\">\n {elapsedLabel ? <span className=\"font-mono\">已持续 {elapsedLabel}</span> : null}\n <span>点击跳到最新位置</span>\n </div>\n </div>\n </button>\n )\n}\n","import { cn } from \"../../lib/utils\"\n\nexport interface TurnNavItem {\n id: string\n title: string\n}\n\ninterface TurnNavRailProps {\n items: TurnNavItem[]\n activeTurnId: string | null\n onSelectTurn: (turnId: string) => void\n}\n\nexport function TurnNavRail({\n items,\n activeTurnId,\n onSelectTurn,\n}: TurnNavRailProps) {\n if (items.length < 2) {\n return null\n }\n\n return (\n <nav\n aria-label=\"回合导航\"\n className=\"absolute right-2 top-4 z-10 hidden flex-col items-end gap-0.5 md:flex\"\n >\n {items.map((item, index) => {\n const isActive = item.id === activeTurnId\n\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={() => onSelectTurn(item.id)}\n aria-current={isActive ? \"true\" : undefined}\n className=\"group relative flex h-3.5 items-center\"\n >\n <span className=\"pointer-events-none absolute right-full mr-2 hidden max-w-48 truncate whitespace-nowrap rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--popover))] px-2.5 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-lg group-hover:block\">\n {item.title || `第 ${index + 1} 轮`}\n </span>\n <span\n className={cn(\n \"block rounded-full transition-all\",\n isActive\n ? \"h-1 w-5 bg-[hsl(var(--primary))]\"\n : \"h-0.5 w-3 bg-[hsl(var(--muted-foreground)/0.3)] group-hover:h-1 group-hover:w-5 group-hover:bg-[hsl(var(--muted-foreground)/0.6)]\",\n )}\n />\n </button>\n )\n })}\n </nav>\n )\n}\n"],"mappings":"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","names":["useCallback","attachments","contexts","create","create","r","r","r","r","r","r","r","r","r","create","create","create","buildMessageContent","toolCall","create","create","create","extractModeFromBlocks","create","create","create","create","create","create","create","create","create","create","create","create","create","create","create","create","r","r","r","type","isRecord","type","mode","File","Loader2","Sparkles","X","useQueryClient","useEffect","useEffectEvent","useMemo","useRef","useState","useCallback","useEffect","useRef","useCallback","useEffect","useCallback","useEffect","useRef","useEffect","useCallback","useEffect","useRef","useState","r","r","jsx","useState","useRef","useEffect","useCallback","useEffect","useMemo","useState","File","useCallback","useMemo","useState","jsx","jsxs","segments","FileCompletionMenu","useMemo","FileCompletionMenuContent","useState","useCallback","File","forwardRef","useCallback","useImperativeHandle","useState","jsx","jsxs","SkillCompletionMenu","useEffect","jsx","jsxs","useEffect","useQuery","useMemo","useQuery","EMPTY_TASKS","useQuery","useQuery","useQuery","useQuery","useQuery","useMemo","useMemo","jsx","jsxs","jsx","jsxs","useQuery","useMemo","Mention","PluginKey","jsx","jsxs","File","Loader2","X","useState","r","useEffectEvent","useRef","useEffect","useQueryClient","useMemo","Sparkles","jsx","jsxs","ChevronDown","Lightbulb","useCallback","useEffect","useEffectEvent","useMemo","useRef","useState","useCallback","useMemo","useRef","useState","isAtBottom","escapedFromLock","useEffect","useImperativeHandle","useMemo","useRef","useEffect","useRef","useMemo","targetScrollTop","useImperativeHandle","StickToBottom","ChevronRight","Sparkles","useMemo","useState","Check","Loader2","useEffect","useMemo","useState","Download","useEffect","useMemo","useRef","useState","type","useEffect","useMemo","useState","useMemo","useState","useEffect","jsx","createContext","useContext","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","jsxs","useRef","useState","useEffect","Download","useMemo","jsx","jsxs","useState","useEffect","useMemo","text","Loader2","Check","isNonEmptyString","isNonEmptyString","r","Fragment","jsx","jsxs","useMemo","Sparkles","ChevronRight","useState","parseModeChange","Check","ChevronRight","useCallback","useEffect","useMemo","useRef","useState","jsx","mermaid","createContext","memo","useCallback","useContext","useEffect","useMemo","useRef","useState","createPortal","Streamdown","useMemo","jsx","Component","Fragment","jsx","jsxs","createContext","useContext","memo","useRef","useState","useEffect","useCallback","useMemo","mermaid","Streamdown","createPortal","Check","ChevronRight","FileText","Loader2","MessageSquareMore","useEffect","useMemo","useState","useEffect","useEffectEvent","useRef","useState","jsx","useRef","useState","useEffect","useEffectEvent","Check","ChevronRight","Loader2","MessageSquareMore","X","useMemo","useState","type","jsx","isPlainObject","jsx","jsxs","isPlainObject","jsx","jsxs","row","col","isPlainObject","useState","ChevronRight","Download","Plus","X","useCallback","useEffect","useRef","useState","createPortal","Fragment","jsx","jsxs","jsx","jsxs","useState","isPlainObject","ExternalLink","FileText","Folder","jsx","jsxs","isPlainObject","Folder","FileText","ExternalLink","Fragment","jsx","jsxs","useState","useMemo","Loader2","MessageSquareMore","X","Check","ChevronRight","type","isRecord","useState","IMAGE_EXTS","Download","X","useEffect","createPortal","useQuery","jsx","jsxs","useEffect","useQuery","body","Download","X","createPortal","jsx","jsxs","Archive","File","FileCode2","FileText","Film","Music","Fragment","jsx","jsxs","Archive","FileCode2","Music","Film","FileText","File","Check","Copy","useState","jsx","jsxs","useState","Check","Copy","Archive","File","FileCode2","FileText","Film","Music","Fragment","jsx","jsxs","getFileIcon","lower","createContext","useContext","useMemo","jsx","jsx","jsxs","jsx","jsxs","useState","lower","Fragment","jsx","jsxs","EMPTY_MESSAGES","useMemo","useState","useEffect","MessageSquareMore","ChevronRight","Loader2","Check","FileText","jsx","jsxs","formatToolDuration","formatFileName","parseToolArguments","childMessages","useMemo","useState","useRef","useEffect","ChevronRight","Check","useCallback","r","ChevronDown","ChevronRight","Loader2","Square","useState","jsx","jsxs","useState","ChevronDown","ChevronRight","Loader2","Square","AlertTriangle","Component","jsx","jsxs","Bot","LoaderCircle","useEffect","useMemo","useState","jsx","jsxs","Bot","LoaderCircle","useState","useEffect","useMemo","jsx","jsxs","jsx","jsxs","parseModeChange","useMemo","useRef","useState","useEffectEvent","useEffect","useCallback","ChevronDown","Lightbulb","jsx","jsxs","useCallback"]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|