@coral-ai/chat 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +33 -6
- package/dist/index.js +82 -49
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Chat.tsx","../src/Chat.Canvas.tsx","../src/Chat.Context.tsx","../src/Chat.Error.tsx","../src/fileToBase64.ts","../src/Chat.Messages.tsx","../src/Chat.ThinkingIndicator.tsx","../src/Chat.TaskMessages.ts","../src/Chat.Callout.tsx","../src/Chat.ReasoningBlock.tsx","../src/Chat.TodoList.tsx","../src/Chat.Input.tsx","../src/Chat.AttachButton.tsx","../src/Chat.Approval.tsx","../src/createHandler.ts","../src/Chat.Agent.ts","../src/Chat.Threads.tsx","../src/index.ts"],"sourcesContent":["import React, { useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Caption1,\n Title3,\n makeStyles,\n motionTokens,\n} from \"@fluentui/react-components\";\nimport type { ChatFontSize, ChatFontFamily } from \"@coral-ai/markdown\";\nimport { useCoralConfig } from \"@coral-ai/react\";\nimport type { CoralChartSpec } from \"@coral-ai/charts\";\nimport type { NormalizedChatError } from \"./Chat.Error\";\nimport ChatCanvas from \"./Chat.Canvas\";\nimport ChatMessages from \"./Chat.Messages\";\nimport ChatInput from \"./Chat.Input\";\nimport ChatApproval from \"./Chat.Approval\";\nimport { useChatContext } from \"./Chat.Context\";\n\n// ---- Types (re-exported for consumers) ----\n\nexport type ChatMessage = {\n /** Stable identifier — generated automatically by Chat.Canvas. Used as React key. */\n id?: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n /** Identifies the message type for custom renderer lookup via the `components` prop. */\n type?: string;\n /** Arbitrary data passed to the custom renderer for this message. */\n metadata?: Record<string, unknown>;\n /**\n * If present, this assistant message carries a structured approval request.\n * Rendered above Chat.Input as a pinned selector while `answer` is undefined;\n * once answered, it stays in history with `answer` populated for replay.\n */\n approval?: ChatApprovalRequest;\n /**\n * If present, this assistant message carries a multi-step task plan.\n * Rendered inline as a collapsible checklist above the message text and\n * persists in history for replay. Updated in place as the agent streams.\n */\n todos?: ChatTodo[];\n /**\n * If present, this assistant message carries one or more chart specs.\n * Rendered inline (above the message text) via `<CoralChart>` from\n * `@coral-ai/charts`. Streamed in incrementally as the agent calls the\n * built-in `render_chart` tool, and persisted with the conversation so\n * the visualizations survive reloads.\n */\n charts?: CoralChartSpec[];\n /**\n * If present, the turn that produced this assistant message failed. The\n * message renders as an error card (with a Retry button) instead of normal\n * content. Persisted with the conversation so the error survives reloads.\n */\n error?: NormalizedChatError;\n};\n\n/**\n * One option in a human-in-the-loop approval / multiple-choice prompt.\n * Boolean approval is just two options; N-choice is the same shape with N options.\n */\nexport type ApprovalOption = {\n id: string;\n label: string;\n description?: string;\n appearance?: \"primary\" | \"subtle\" | \"outline\" | \"secondary\";\n /**\n * When true, selecting this option does NOT immediately resolve the approval.\n * The chat input is unlocked so the user can type a free-text reply, which is\n * then sent as the resolution payload (carrying this option's id alongside the text).\n * Convention: a final \"Other / something else\" choice.\n */\n freeform?: boolean;\n};\n\n/** Structured approval request attached to an assistant message. */\nexport type ChatApprovalRequest = {\n /** Stable id used to match the eventual response. */\n id: string;\n question: string;\n description?: string;\n options: ApprovalOption[];\n /**\n * Once the user responds, this is populated and the buttons render in their\n * \"answered\" terminal state. Distinct from `freeform` so freeform replies\n * still record which option was the escape hatch.\n */\n answer?: { optionId: string; text?: string };\n};\n\n/**\n * One step in a multi-step task plan. The agent emits the whole list on each\n * update; the convention is exactly one item `in_progress` at a time.\n */\nexport type ChatTodo = {\n /** Stable id for React key + diffing. Optional; index used as fallback. */\n id?: string;\n /** Imperative title shown when pending/completed, e.g. \"Optimize images\". */\n content: string;\n /** Present-tense title shown while in_progress, e.g. \"Optimizing images\". */\n activeForm?: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n};\n\n/** A single chunk yielded by a streaming onSendMessage. */\nexport type ChatChunk =\n | string\n | { type: \"reasoning\"; content: string }\n /** Sets the thinking-indicator word pool while the handler works. */\n | { type: \"status\"; name: string }\n | { type: \"approval\"; approval: ChatApprovalRequest }\n | { type: \"todos\"; todos: ChatTodo[] }\n /** Appends a chart spec to the current assistant message; renders inline. */\n | { type: \"chart\"; spec: CoralChartSpec };\n\nexport type ChatResponse =\n | string\n | AsyncIterable<ChatChunk>\n | {\n content: string;\n type?: string;\n metadata?: Record<string, unknown>;\n todos?: ChatTodo[];\n };\n\n/** The typed handler signature engineers implement. */\nexport type ChatAttachment = {\n id: string;\n file: File;\n /** Data URL — populated for image/* files only. */\n preview?: string;\n};\n\nexport type AgentHandler = (\n input: string,\n history: ChatMessage[],\n attachments: File[],\n) => ChatResponse | Promise<ChatResponse>;\n\n/** Props passed to a custom message renderer. */\nexport type ChatMessageRendererProps = {\n message: ChatMessage;\n /** Sends a message back into the chat as the user. */\n onReply: (content: string) => void;\n};\n\nexport type ChatComponents = Record<string, React.FC<ChatMessageRendererProps>>;\n\n// ---- Props ----\n\ninterface ChatProps {\n /**\n * Backend URL. Coral POSTs `{ text, history, attachments }` here on send and\n * adapts the response to the existing chat pipeline. Used only when no\n * `onSendMessage` is provided. Falls back to `useCoralConfig().chat.api`\n * when omitted.\n */\n api?: string;\n /**\n * Which entries to render in the chat input's `+` menu. Falls back to\n * `useCoralConfig().chat.attachments` when omitted.\n */\n allowedAttachments?: Array<\"files\" | \"photos\">;\n conversationId?: string;\n initialMessages?: ChatMessage[];\n systemPrompt?: string;\n onSendMessage?: AgentHandler;\n onMessageComplete?: (\n messages: ChatMessage[],\n conversationId?: string,\n ) => void;\n /** Fires on every message-state update (user append, streaming chunk, final). Use for live persistence. */\n onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;\n onError?: (err: unknown) => void;\n autoSendMessage?: string;\n onCopy?: (content: string) => void;\n onNavigate?: (path: string) => void;\n components?: ChatComponents;\n thinkingStatus?: string;\n onStop?: () => void;\n /** Placeholder text for the chat input. @default \"Type a message...\" */\n placeholder?: string;\n /** Disables the entire input. */\n disabled?: boolean;\n /** Slot rendered at the left of the input toolbar. */\n actionsStart?: React.ReactNode;\n /** Slot rendered at the right of the input toolbar, just before Send/Stop. */\n actionsEnd?: React.ReactNode;\n /**\n * Shown above the input while messages is empty.\n * - Pass a `string` to render it as a `Title3` heading that hugs its content.\n * - Pass any other `ReactNode` to flex-fill the available height (centered).\n */\n welcomeMessage?: string | React.ReactNode;\n /**\n * Slot rendered horizontally centered directly under `Chat.Input`, while\n * the chat is empty (no user/assistant messages yet). Typical use is a row\n * of `PromptCard`s as starter prompts. Children can call `useChatContext()`\n * to invoke `sendMessage(text)` on click.\n */\n promptSuggestions?: React.ReactNode;\n /**\n * Pass `null` to disable the chat's built-in surface motion (input slide to\n * bottom on first message). Omit / leave undefined for default motion.\n */\n surfaceMotion?: null;\n /** Font size for assistant message markdown. */\n fontSize?: ChatFontSize;\n /** Font family for assistant message markdown. */\n fontFamily?: ChatFontFamily;\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n emptySlot: {\n width: \"100%\",\n maxWidth: \"768px\",\n margin: \"0 auto\",\n padding: \"0 16px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n },\n contentArea: {\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n minHeight: \"0\",\n },\n inputRow: {\n display: \"flex\",\n width: \"100%\",\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n inputInner: {\n display: \"flex\",\n width: \"100%\",\n maxWidth: \"768px\",\n padding: \"0 16px 16px 16px\",\n boxSizing: \"border-box\",\n },\n suggestionsRow: {\n display: \"flex\",\n width: \"100%\",\n maxWidth: \"768px\",\n margin: \"0 auto\",\n padding: \"0 16px 16px 16px\",\n boxSizing: \"border-box\",\n justifyContent: \"center\",\n },\n});\n\n// ---- Inner layout (reads context, positions via CSS without remounting Input) ----\n\ninterface ChatLayoutProps {\n welcomeMessage?: string | React.ReactNode;\n promptSuggestions?: React.ReactNode;\n surfaceMotion?: null;\n placeholder?: string;\n disabled?: boolean;\n actionsStart?: React.ReactNode;\n actionsEnd?: React.ReactNode;\n components?: ChatComponents;\n onCopy?: (content: string) => void;\n onNavigate?: (path: string) => void;\n fontSize?: ChatFontSize;\n fontFamily?: ChatFontFamily;\n}\n\n// In the panel-right sidecar surface, \"default\" is too large — render it as\n// \"small\". \"small\" and \"large\" pass through unchanged.\nconst remapFontSizeForSurface = (\n size: ChatFontSize | undefined,\n surface: string | null,\n): ChatFontSize | undefined => {\n if (surface === \"panel-right\" && (size === undefined || size === \"default\")) {\n return \"small\";\n }\n return size;\n};\n\nconst ChatLayout: React.FC<ChatLayoutProps> = ({\n welcomeMessage,\n promptSuggestions,\n surfaceMotion,\n placeholder,\n disabled,\n actionsStart,\n actionsEnd,\n components,\n onCopy,\n onNavigate,\n fontSize,\n fontFamily,\n}) => {\n const welcomeIsFill =\n welcomeMessage !== undefined && typeof welcomeMessage !== \"string\";\n const welcomeNode =\n typeof welcomeMessage === \"string\" ? (\n <Title3>{welcomeMessage}</Title3>\n ) : (\n welcomeMessage\n );\n const styles = useStyles();\n const surfaceProbeRef = useRef<HTMLDivElement>(null);\n const [surface, setSurface] = useState<string | null>(null);\n useLayoutEffect(() => {\n const el = surfaceProbeRef.current?.closest(\"[data-coral-surface]\");\n setSurface(el?.getAttribute(\"data-coral-surface\") ?? null);\n }, []);\n const effectiveFontSize = remapFontSizeForSurface(fontSize, surface);\n const { messages, isTyping, pendingApproval, awaitingFreeformApproval } = useChatContext();\n const empty = messages.every((m) => m.role === \"system\") && !isTyping;\n const approvalLocksInput = pendingApproval !== null && awaitingFreeformApproval === null;\n const inputDisabled = disabled || approvalLocksInput;\n\n const motionEnabled = surfaceMotion !== null;\n const curve = motionTokens.curveDecelerateMax;\n const spacerTransition = motionEnabled ? `flex-grow 300ms ${curve}` : \"none\";\n const gapTransition = motionEnabled ? `height 300ms ${curve}` : \"none\";\n\n return (\n <>\n <div\n ref={surfaceProbeRef}\n style={{\n flexGrow: empty && !welcomeIsFill ? 1 : 0,\n flexShrink: 1,\n flexBasis: 0,\n minHeight: 0,\n transition: spacerTransition,\n }}\n />\n <div\n className={styles.contentArea}\n style={{\n flex: empty && !welcomeIsFill ? \"none\" : 1,\n overflow: empty && !welcomeIsFill ? \"visible\" : \"hidden\",\n }}\n >\n {empty ? (\n <div\n className={styles.emptySlot}\n style={\n welcomeIsFill\n ? {\n flex: 1,\n justifyContent: \"center\",\n alignContent: \"center\",\n }\n : undefined\n }\n >\n {welcomeNode}\n </div>\n ) : (\n <ChatMessages\n components={components}\n onCopy={onCopy}\n onNavigate={onNavigate}\n fontSize={effectiveFontSize}\n fontFamily={fontFamily}\n />\n )}\n </div>\n <div style={{ height: empty ? 24 : 0, transition: gapTransition }} />\n <div className={styles.inputRow}>\n <div className={styles.inputInner} style={{ flexDirection: \"column\" }}>\n {pendingApproval && <ChatApproval />}\n <ChatInput\n placeholder={\n approvalLocksInput\n ? \"Choose an option above to continue...\"\n : placeholder\n }\n disabled={inputDisabled}\n actionsStart={actionsStart}\n actionsEnd={actionsEnd}\n />\n </div>\n </div>\n {empty && promptSuggestions && (\n <div className={styles.suggestionsRow}>{promptSuggestions}</div>\n )}\n <div\n style={{\n flexGrow: empty && !welcomeIsFill ? 1 : 0,\n flexShrink: 1,\n flexBasis: 0,\n minHeight: 0,\n transition: spacerTransition,\n }}\n />\n <Caption1\n style={{\n display: \"flex\",\n width: \"100%\",\n justifyContent: \"center\",\n height: \"32px\",\n opacity: 0.5,\n }}\n >\n AI makes mistakes. Check outputs.\n </Caption1>\n </>\n );\n};\n\n// ---- Component ----\n\nconst Chat: React.FC<ChatProps> = ({\n api,\n allowedAttachments,\n conversationId,\n initialMessages,\n systemPrompt,\n onSendMessage,\n onMessageComplete,\n onMessagesChange,\n onError,\n autoSendMessage,\n thinkingStatus,\n onStop,\n welcomeMessage,\n promptSuggestions,\n surfaceMotion,\n components,\n onCopy,\n onNavigate,\n placeholder,\n disabled,\n actionsStart,\n actionsEnd,\n fontSize,\n fontFamily,\n}) => {\n // Project-wide config (from CoralProvider) acts as defaults — component\n // props win when both are set. We read the nested `chat` section since\n // coral.config.{ts,js,json} is now domain-sectioned.\n const chatConfig = useCoralConfig()?.chat;\n\n const resolvedApi = api ?? chatConfig?.api;\n // Explicit prop wins; otherwise fall back to the project config.\n const resolvedAllowedAttachments = allowedAttachments ?? chatConfig?.attachments;\n\n return (\n <ChatCanvas\n api={resolvedApi}\n allowedAttachments={resolvedAllowedAttachments}\n conversationId={conversationId}\n initialMessages={initialMessages}\n systemPrompt={systemPrompt}\n onSendMessage={onSendMessage}\n onMessageComplete={onMessageComplete}\n onMessagesChange={onMessagesChange}\n onError={onError}\n autoSendMessage={autoSendMessage}\n thinkingStatus={thinkingStatus}\n onStop={onStop}\n >\n <ChatLayout\n welcomeMessage={welcomeMessage}\n promptSuggestions={promptSuggestions}\n surfaceMotion={surfaceMotion}\n placeholder={placeholder}\n disabled={disabled}\n actionsStart={actionsStart}\n actionsEnd={actionsEnd}\n components={components}\n onCopy={onCopy}\n onNavigate={onNavigate}\n fontSize={fontSize}\n fontFamily={fontFamily}\n />\n </ChatCanvas>\n );\n};\n\nexport default Chat;\n","import React, { useState, useEffect, useLayoutEffect, useRef, useCallback, ReactNode } from \"react\";\nimport { Button, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { ArrowDown } from \"@coral-ai/bundleicons\";\nimport { ChatContext } from \"./Chat.Context\";\nimport { normalizeChatError } from \"./Chat.Error\";\nimport { fileToBase64 } from \"./fileToBase64\";\nimport type { CoralChartSpec } from \"@coral-ai/charts\";\nimport type { ChatMessage, ChatChunk, AgentHandler, ChatAttachment, ChatApprovalRequest, ChatTodo } from \"./Chat\";\n\n// ---- Props ----\n\nexport interface ChatCanvasProps {\n /**\n * Backend URL Coral POSTs to on send. Used as the built-in handler when\n * `onSendMessage` is not set.\n *\n * Coral serializes attachments to base64 and sends\n * `{ text, history, attachments: [{ name, mediaType, data }] }` as JSON. The\n * response can be `{ type?, reply }` (non-streaming) or a Server-Sent-Events\n * stream of `ChatChunk` JSON lines. The optional `type` field is matched\n * against Coral's built-in task vocabulary to pick the thinking-indicator\n * word pool.\n */\n api?: string;\n /** Which entries to render in the chat input's `+` menu (`Chat.AttachButton`). */\n allowedAttachments?: Array<\"files\" | \"photos\">;\n /** Stable conversation identifier, passed back in onMessageComplete. */\n conversationId?: string;\n /** Pre-load conversation history. */\n initialMessages?: ChatMessage[];\n /** System prompt prepended to every request (not shown in UI). */\n systemPrompt?: string;\n /** Called when the user sends a message. Return a string, async iterable, or ChatResponse. */\n onSendMessage?: (input: string, history: ChatMessage[], attachments: File[]) => ReturnType<AgentHandler>;\n /** Called after every completed assistant response. Use to persist messages. */\n onMessageComplete?: (messages: ChatMessage[], conversationId?: string) => void;\n /** Called on every message-state update (user append, streaming chunk, final). Use for live persistence. */\n onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;\n /** Called when an error occurs during send. */\n onError?: (err: unknown) => void;\n /** Automatically sends this message once on mount. */\n autoSendMessage?: string;\n /** Override the thinking indicator text during generation. */\n thinkingStatus?: string;\n /** Called when the user clicks Stop. Use to abort your fetch/API call. */\n onStop?: () => void;\n children?: ReactNode;\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n root: {\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n flex: \"1\",\n minHeight: \"0\",\n position: \"relative\",\n },\n scrollToBottom: {\n position: \"absolute\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 1000,\n cursor: \"pointer\",\n boxShadow: tokens.shadow8,\n marginBottom: \"48px\",\n backgroundColor: 'var(--colorNeutralBackgroundAlpha2)',\n backdropFilter: 'blur(40px) saturate(150%)',\n },\n});\n\n// ---- Helpers ----\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterable<ChatChunk> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n Symbol.asyncIterator in (value as object)\n );\n}\n\nfunction isRateLimitError(err: unknown): boolean {\n const e = err as Record<string, unknown>;\n const status = Number(e?.status ?? e?.statusCode ?? 0);\n const msg = String(e?.message ?? \"\").toLowerCase();\n return (\n status === 429 ||\n msg.includes(\"rate limit\") ||\n msg.includes(\"too many requests\")\n );\n}\n\n/**\n * Yields a single status chunk identifying the backend's task type, then the\n * reply text. Used by the built-in `api` handler to bridge a one-shot JSON\n * response into Coral's streaming chunk machinery so the thinking indicator\n * can swap its word pool.\n */\nasync function* wrapWithStatusChunk(\n taskType: string,\n reply: string,\n): AsyncIterable<ChatChunk> {\n yield { type: \"status\", name: taskType };\n if (reply) yield reply;\n}\n\n/**\n * Parses a Server-Sent-Events or NDJSON response into a `ChatChunk` async\n * iterable. Each line is expected to be a JSON-encoded `ChatChunk` (string,\n * status, reasoning, approval, or todos). Plain strings are yielded as text.\n */\nasync function* parseStream(res: Response): AsyncIterable<ChatChunk> {\n const reader = res.body?.getReader();\n if (!reader) return;\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const raw of lines) {\n const line = raw.startsWith(\"data:\") ? raw.slice(5).trim() : raw.trim();\n if (!line || line === \"[DONE]\") continue;\n try {\n const parsed = JSON.parse(line);\n if (typeof parsed === \"string\") {\n yield parsed;\n } else if (parsed && typeof parsed === \"object\" && \"type\" in parsed) {\n yield parsed as ChatChunk;\n } else if (parsed && typeof parsed === \"object\" && typeof (parsed as { reply?: unknown }).reply === \"string\") {\n if (typeof (parsed as { type?: unknown }).type === \"string\") {\n yield { type: \"status\", name: (parsed as { type: string }).type };\n }\n yield (parsed as { reply: string }).reply;\n }\n } catch {\n // Treat un-parseable lines as raw text.\n yield line;\n }\n }\n }\n if (buffer.trim()) {\n try {\n const parsed = JSON.parse(buffer);\n if (typeof parsed === \"string\") yield parsed;\n else if (parsed && typeof parsed === \"object\" && \"type\" in parsed) yield parsed as ChatChunk;\n } catch {\n yield buffer;\n }\n }\n}\n\n// ---- Component ----\n\nconst ChatCanvas: React.FC<ChatCanvasProps> = ({\n api,\n allowedAttachments,\n conversationId,\n initialMessages,\n systemPrompt,\n onSendMessage,\n onMessageComplete,\n onMessagesChange,\n onError,\n autoSendMessage,\n thinkingStatus,\n onStop,\n children,\n}) => {\n const styles = useStyles();\n\n // Built-in handler used when an `api` URL is configured and no explicit\n // `onSendMessage` handler is provided. Serializes attachments to base64,\n // POSTs JSON, and adapts the response to Coral's existing\n // `ChatResponse` / `AsyncIterable<ChatChunk>` shape.\n const apiHandler: AgentHandler | undefined = api\n ? async function (input, history, files) {\n const attachments = await Promise.all(\n files.map(async (file) => ({\n name: file.name,\n mediaType: file.type,\n data: await fileToBase64(file),\n })),\n );\n const res = await fetch(api, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n text: input,\n history,\n attachments,\n }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw Object.assign(\n new Error(`Chat API request failed (${res.status}): ${text || res.statusText}`),\n { status: res.status },\n );\n }\n const contentType = res.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"text/event-stream\") || contentType.includes(\"application/x-ndjson\")) {\n return parseStream(res);\n }\n const data = await res.json();\n if (data && typeof data === \"object\") {\n // Optional `type` field becomes a pre-yielded agent chunk so the\n // thinking indicator can swap its word pool. We use a streaming\n // wrapper even for one-shot JSON so the existing chunk machinery\n // handles agent-name routing.\n if (typeof data.type === \"string\") {\n return wrapWithStatusChunk(data.type, String(data.reply ?? \"\"));\n }\n if (typeof data.reply === \"string\") return data.reply;\n }\n return typeof data === \"string\" ? data : \"\";\n }\n : undefined;\n\n const resolvedHandler: AgentHandler | undefined = onSendMessage ?? apiHandler;\n\n const [messages, setMessages] = useState<ChatMessage[]>(\n () => (initialMessages ?? []).map((m) => (m.id ? m : { ...m, id: crypto.randomUUID() })),\n );\n const [input, setInput] = useState(\"\");\n const [isTyping, setIsTyping] = useState(false);\n const [isRetrying, setIsRetrying] = useState(false);\n const [showScrollButton, setShowScrollButton] = useState(false);\n const [inputHeight, setInputHeightState] = useState(0);\n const [isInterrupted, setIsInterrupted] = useState(false);\n const [streamingReasoning, setStreamingReasoning] = useState(\"\");\n const [streamingStatus, setStreamingStatus] = useState<string | undefined>();\n const [attachments, setAttachments] = useState<ChatAttachment[]>([]);\n const [awaitingFreeformApproval, setAwaitingFreeformApproval] = useState<\n { approvalId: string; optionId: string } | null\n >(null);\n\n // Pending approval = latest assistant message whose approval has no answer yet.\n const pendingApproval: ChatApprovalRequest | null = (() => {\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m.role !== \"assistant\") continue;\n if (m.approval && !m.approval.answer) return m.approval;\n // First assistant message without a pending approval blocks earlier matches.\n if (m.approval && m.approval.answer) return null;\n }\n return null;\n })();\n\n const reasoningRef = useRef(\"\");\n const lastUserInputRef = useRef(\"\");\n const hasEverSentRef = useRef(false);\n const currentConversationIdRef = useRef(conversationId);\n const messagesContainerRef = useRef<HTMLDivElement>(null);\n const [messagesEl, setMessagesEl] = useState<HTMLDivElement | null>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const shouldStopRef = useRef(false);\n const userScrolledUpRef = useRef(false);\n\n // Sync initialMessages (e.g. conversation switched externally).\n useEffect(() => {\n setMessages((current) => {\n if ((initialMessages?.length ?? 0) > 0 || current.length === 0) {\n return (initialMessages ?? []).map((m) =>\n m.id ? m : { ...m, id: crypto.randomUUID() },\n );\n }\n return current;\n });\n }, [initialMessages]);\n\n // Track current conversationId so in-flight streams can detect a session switch.\n useEffect(() => {\n currentConversationIdRef.current = conversationId;\n }, [conversationId]);\n\n // Auto-send on mount; ref guard prevents Strict Mode double-fire.\n const autoSentRef = useRef(false);\n useEffect(() => {\n if (autoSendMessage?.trim() && !autoSentRef.current) {\n autoSentRef.current = true;\n sendMessage(autoSendMessage);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const registerMessagesContainer = useCallback((el: HTMLDivElement | null) => {\n messagesContainerRef.current = el;\n setMessagesEl(el);\n }, []);\n\n // Auto-scroll to bottom when messages update (unless user scrolled up).\n useLayoutEffect(() => {\n if (!userScrolledUpRef.current) {\n if (messagesEl) {\n messagesEl.scrollTop = messagesEl.scrollHeight;\n }\n setShowScrollButton(false);\n }\n }, [messages, messagesEl]);\n\n // Scroll detection — attaches lazily when Chat.Messages mounts.\n useEffect(() => {\n const container = messagesEl;\n if (!container) return;\n const handleScroll = () => {\n const { scrollTop, scrollHeight, clientHeight } = container;\n const atBottom = scrollTop + clientHeight >= scrollHeight - 80;\n userScrolledUpRef.current = !atBottom;\n setShowScrollButton(!atBottom);\n };\n container.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => container.removeEventListener(\"scroll\", handleScroll);\n }, [messagesEl]);\n\n const scrollToBottom = () => {\n userScrolledUpRef.current = false;\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n setShowScrollButton(false);\n };\n\n const handleCopy = (content: string) => {\n navigator.clipboard.writeText(content).catch(console.error);\n };\n\n const addAttachments = (files: File[]) => {\n const newItems: ChatAttachment[] = files.map((file) => {\n const attachment: ChatAttachment = { id: crypto.randomUUID(), file };\n if (file.type.startsWith(\"image/\")) {\n const reader = new FileReader();\n reader.onload = (e) => {\n const preview = e.target?.result as string;\n setAttachments((prev) =>\n prev.map((a) => (a.id === attachment.id ? { ...a, preview } : a))\n );\n };\n reader.readAsDataURL(file);\n }\n return attachment;\n });\n setAttachments((prev) => [...prev, ...newItems]);\n };\n\n const removeAttachment = (id: string) => {\n setAttachments((prev) => prev.filter((a) => a.id !== id));\n };\n\n /**\n * Core streaming runner. Given a fully-prepared message array ending with\n * a user turn, invokes the handler and streams the assistant response.\n * Used by sendMessage, regenerate, and editMessage.\n */\n const runHandler = async (\n textToSend: string,\n updatedMessages: ChatMessage[],\n snapshotAttachments: ChatAttachment[],\n ) => {\n const sessionAtSend = conversationId;\n\n lastUserInputRef.current = textToSend;\n userScrolledUpRef.current = false;\n setMessages(updatedMessages);\n onMessagesChange?.(updatedMessages, sessionAtSend);\n setIsTyping(true);\n setIsInterrupted(false);\n shouldStopRef.current = false;\n reasoningRef.current = \"\";\n setStreamingReasoning(\"\");\n setStreamingStatus(undefined);\n\n const historyForAI: ChatMessage[] = systemPrompt\n ? [{ role: \"system\", content: systemPrompt }, ...updatedMessages]\n : updatedMessages;\n\n const MAX_RETRIES = 3;\n\n try {\n if (resolvedHandler) {\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const assistantId = crypto.randomUUID();\n const placeholder: ChatMessage[] = [...updatedMessages, { id: assistantId, role: \"assistant\", content: \"\" }];\n setMessages(placeholder);\n onMessagesChange?.(placeholder, sessionAtSend);\n const response = await resolvedHandler(textToSend, historyForAI, snapshotAttachments.map((a) => a.file));\n\n if (isAsyncIterable(response)) {\n let assistantContent = \"\";\n let rafId: number | null = null;\n let pendingContent = \"\";\n let streamedApproval: ChatApprovalRequest | undefined;\n let streamedTodos: ChatTodo[] | undefined;\n let streamedCharts: CoralChartSpec[] | undefined;\n\n for await (const chunk of response) {\n if (shouldStopRef.current) break;\n // Only bail on an actual conversation switch — not when a new\n // session is created mid-send (undefined → defined), which\n // happens when the app assigns an id on first message.\n if (\n sessionAtSend !== undefined &&\n currentConversationIdRef.current !== sessionAtSend\n ) break;\n if (typeof chunk === \"string\") {\n assistantContent += chunk;\n pendingContent = assistantContent;\n if (rafId === null) {\n rafId = requestAnimationFrame(() => {\n const content = pendingContent;\n // Merge into the existing assistant message rather than\n // replacing it — otherwise fields streamed in earlier\n // (todos, approval) get wiped by the next text chunk and\n // their renderers unmount/remount (flash).\n let nextMsg: ChatMessage = { id: assistantId, role: \"assistant\", content };\n setMessages((prev) => {\n const updated = [...prev];\n const last = updated[updated.length - 1];\n if (last && last.id === assistantId) {\n nextMsg = { ...last, content };\n }\n updated[updated.length - 1] = nextMsg;\n return updated;\n });\n onMessagesChange?.([...updatedMessages, nextMsg], sessionAtSend);\n rafId = null;\n });\n }\n } else if (chunk.type === \"reasoning\") {\n reasoningRef.current += chunk.content;\n setStreamingReasoning(reasoningRef.current);\n } else if (chunk.type === \"status\") {\n setStreamingStatus(chunk.name);\n } else if (chunk.type === \"approval\") {\n streamedApproval = chunk.approval;\n setMessages((prev) => {\n const updated = [...prev];\n const last = updated[updated.length - 1];\n if (last && last.id === assistantId) {\n updated[updated.length - 1] = { ...last, approval: chunk.approval };\n }\n return updated;\n });\n } else if (chunk.type === \"todos\") {\n streamedTodos = chunk.todos;\n setMessages((prev) => {\n const updated = [...prev];\n const last = updated[updated.length - 1];\n if (last && last.id === assistantId) {\n updated[updated.length - 1] = { ...last, todos: chunk.todos };\n }\n return updated;\n });\n } else if (chunk.type === \"chart\") {\n streamedCharts = [...(streamedCharts ?? []), chunk.spec];\n const nextCharts = streamedCharts;\n setMessages((prev) => {\n const updated = [...prev];\n const last = updated[updated.length - 1];\n if (last && last.id === assistantId) {\n updated[updated.length - 1] = { ...last, charts: nextCharts };\n }\n return updated;\n });\n }\n }\n\n if (rafId !== null) cancelAnimationFrame(rafId);\n if (shouldStopRef.current) setIsInterrupted(true);\n\n if (\n sessionAtSend !== undefined &&\n currentConversationIdRef.current !== sessionAtSend\n ) {\n break;\n }\n\n const finalMsg: ChatMessage = {\n id: assistantId,\n role: \"assistant\",\n content: assistantContent,\n ...(reasoningRef.current ? { metadata: { reasoning: reasoningRef.current } } : {}),\n ...(streamedApproval ? { approval: streamedApproval } : {}),\n ...(streamedTodos ? { todos: streamedTodos } : {}),\n ...(streamedCharts ? { charts: streamedCharts } : {}),\n };\n const finalMessages = [...updatedMessages, finalMsg];\n setMessages(finalMessages);\n onMessagesChange?.(finalMessages, sessionAtSend);\n onMessageComplete?.(finalMessages, sessionAtSend);\n } else if (typeof response === \"string\") {\n if (currentConversationIdRef.current !== sessionAtSend) break;\n const finalMessages: ChatMessage[] = [...updatedMessages, { id: assistantId, role: \"assistant\" as const, content: response }];\n setMessages(finalMessages);\n onMessagesChange?.(finalMessages, sessionAtSend);\n onMessageComplete?.(finalMessages, sessionAtSend);\n } else {\n if (currentConversationIdRef.current !== sessionAtSend) break;\n const assistantMsg: ChatMessage = {\n id: assistantId,\n role: \"assistant\",\n content: response.content,\n type: response.type,\n metadata: response.metadata,\n todos: response.todos,\n };\n const finalMessages = [...updatedMessages, assistantMsg];\n setMessages(finalMessages);\n onMessagesChange?.(finalMessages, sessionAtSend);\n onMessageComplete?.(finalMessages, sessionAtSend);\n }\n\n break;\n } catch (err) {\n if (isRateLimitError(err) && attempt < MAX_RETRIES - 1) {\n setIsRetrying(true);\n await new Promise<void>((r) => setTimeout(r, (attempt + 1) * 3000));\n continue;\n }\n throw err;\n }\n }\n }\n } catch (err) {\n onError?.(err);\n // Persist the failure as an assistant message carrying a normalized\n // error. Keeping it in the message stream (vs. transient state) means\n // the error card survives reloads and chat-tab switches.\n if (\n sessionAtSend === undefined ||\n currentConversationIdRef.current === sessionAtSend\n ) {\n const erroredMessages: ChatMessage[] = [\n ...updatedMessages,\n {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: \"\",\n error: normalizeChatError(err),\n },\n ];\n setMessages(erroredMessages);\n onMessagesChange?.(erroredMessages, sessionAtSend);\n }\n } finally {\n setIsRetrying(false);\n setIsTyping(false);\n }\n };\n\n /**\n * Marks an approval request as answered. If the chosen option is `freeform`,\n * transitions into the awaiting-freeform state instead — the next user\n * submission via sendMessage will then resolve the approval with the typed\n * text. Otherwise resolves immediately and re-runs the agent so it can\n * react to the user's choice.\n */\n const resolveApproval = (approvalId: string, optionId: string) => {\n const target = messages.find(\n (m) => m.role === \"assistant\" && m.approval?.id === approvalId,\n );\n if (!target || !target.approval) return;\n if (target.approval.answer) return;\n\n const option = target.approval.options.find((o) => o.id === optionId);\n if (!option) return;\n\n if (option.freeform) {\n setAwaitingFreeformApproval({ approvalId, optionId });\n return;\n }\n\n // Immediate resolution: stamp the answer and append a typed user reply.\n const updated = messages.map((m) =>\n m.role === \"assistant\" && m.approval?.id === approvalId\n ? { ...m, approval: { ...m.approval!, answer: { optionId } } }\n : m,\n );\n const replyText = option.label;\n const userMsg: ChatMessage = {\n id: crypto.randomUUID(),\n role: \"user\",\n type: \"approval_response\",\n content: replyText,\n metadata: { approvalId, optionId, label: option.label },\n };\n const next = [...updated, userMsg];\n void runHandler(replyText, next, []);\n };\n\n const sendMessage = async (overrideInput?: string) => {\n const textToSend = overrideInput ?? input;\n if (!textToSend.trim()) return;\n\n // Freeform approval interception: the next submission is the approval reply.\n if (awaitingFreeformApproval) {\n const { approvalId, optionId } = awaitingFreeformApproval;\n const target = messages.find(\n (m) => m.role === \"assistant\" && m.approval?.id === approvalId,\n );\n if (target && target.approval) {\n const option = target.approval.options.find((o) => o.id === optionId);\n const updated = messages.map((m) =>\n m.role === \"assistant\" && m.approval?.id === approvalId\n ? { ...m, approval: { ...m.approval!, answer: { optionId, text: textToSend } } }\n : m,\n );\n const userMsg: ChatMessage = {\n id: crypto.randomUUID(),\n role: \"user\",\n type: \"approval_response\",\n content: textToSend.replace(/^[\\n\\r]+|[\\n\\r]+$/g, \"\"),\n metadata: { approvalId, optionId, label: option?.label, text: textToSend },\n };\n const next = [...updated, userMsg];\n if (!overrideInput) setInput(\"\");\n setAwaitingFreeformApproval(null);\n hasEverSentRef.current = true;\n await runHandler(textToSend, next, []);\n return;\n }\n // Target gone (shouldn't happen) — clear awaiting state and fall through.\n setAwaitingFreeformApproval(null);\n }\n\n hasEverSentRef.current = true;\n\n // overrideInput is used by retry/error flows where the caller wants to\n // discard the previous failed user+assistant pair before resending.\n // For a fresh send, drop a trailing errored assistant message so a stale\n // error card doesn't get stranded mid-conversation.\n const lastMessage = messages[messages.length - 1];\n const baseMessages = overrideInput\n ? messages.filter((_, i) => i < messages.length - 2)\n : lastMessage?.role === \"assistant\" && lastMessage.error\n ? messages.slice(0, -1)\n : messages;\n\n const snapshotAttachments = attachments;\n const attachmentMeta = snapshotAttachments.map((a) => ({\n name: a.file.name,\n type: a.file.type,\n preview: a.preview,\n }));\n\n const updatedMessages: ChatMessage[] = [\n ...baseMessages,\n {\n id: crypto.randomUUID(),\n role: \"user\",\n content: textToSend.replace(/^[\\n\\r]+|[\\n\\r]+$/g, \"\"),\n ...(attachmentMeta.length > 0 ? { metadata: { attachments: attachmentMeta } } : {}),\n },\n ];\n\n if (!overrideInput) setInput(\"\");\n setAttachments([]);\n\n await runHandler(textToSend, updatedMessages, snapshotAttachments);\n };\n\n /**\n * Resolves the user-message index that should drive a regenerate.\n * - No id: the last user message in the array.\n * - Id of a user message: that message.\n * - Id of an assistant message: the user message immediately preceding it.\n * Returns -1 if no valid target exists.\n */\n const resolveRegenerateTarget = (messageId?: string): number => {\n if (!messageId) {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") return i;\n }\n return -1;\n }\n const idx = messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return -1;\n if (messages[idx].role === \"user\") return idx;\n if (messages[idx].role === \"assistant\") {\n for (let i = idx - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") return i;\n }\n }\n return -1;\n };\n\n const regenerate = async (messageId?: string) => {\n const userIdx = resolveRegenerateTarget(messageId);\n if (userIdx === -1) return;\n const userMsg = messages[userIdx];\n const baseMessages = messages.slice(0, userIdx + 1);\n await runHandler(userMsg.content, baseMessages, []);\n };\n\n const editMessage = async (messageId: string, newContent: string) => {\n const idx = messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return;\n if (messages[idx].role !== \"user\") return;\n const trimmed = newContent.replace(/^[\\n\\r]+|[\\n\\r]+$/g, \"\");\n if (!trimmed.trim()) return;\n\n const editedMessage: ChatMessage = {\n ...messages[idx],\n content: trimmed,\n };\n const baseMessages: ChatMessage[] = [\n ...messages.slice(0, idx),\n editedMessage,\n ];\n await runHandler(trimmed, baseMessages, []);\n };\n\n return (\n <ChatContext.Provider\n value={{\n sendMessage,\n regenerate,\n editMessage,\n scrollToBottom,\n handleCopy,\n messages,\n setMessages,\n input,\n setInput,\n isTyping,\n isRetrying,\n isInterrupted,\n streamingReasoning,\n streamingStatus,\n thinkingStatus,\n showScrollButton,\n setInputHeight: setInputHeightState,\n messagesContainerRef,\n registerMessagesContainer,\n bottomRef,\n lastUserInputRef,\n hasEverSentRef,\n shouldStopRef,\n onStop,\n attachments,\n addAttachments,\n removeAttachment,\n allowedAttachments,\n pendingApproval,\n awaitingFreeformApproval,\n resolveApproval,\n }}\n >\n <div className={styles.root}>\n {children}\n {showScrollButton && (\n <Button\n onClick={scrollToBottom}\n className={styles.scrollToBottom}\n shape=\"circular\"\n style={{\n bottom: inputHeight + 16,\n backgroundColor: \"transparent\",\n border: `1px solid ${tokens.colorNeutralStroke3}`,\n backdropFilter: \"saturate(180%) blur(16px)\",\n }}\n icon={<ArrowDown style={{ fontSize: \"16px\" }} />}\n />\n )}\n </div>\n </ChatContext.Provider>\n );\n};\n\nexport default ChatCanvas;\n","import { createContext, useContext } from \"react\";\nimport type React from \"react\";\nimport type { ChatMessage, ChatAttachment, ChatApprovalRequest } from \"./Chat\";\n\nexport interface ChatContextValue {\n // ── Actions ───────────────────────────────────────────────────────────────\n sendMessage: (overrideInput?: string) => Promise<void>;\n /**\n * Re-runs the assistant turn following the matching user message.\n * If `messageId` is omitted, regenerates the last assistant message.\n * If `messageId` targets an assistant message, the matching user prompt is replayed.\n * If `messageId` targets a user message, the existing assistant reply for that turn is discarded and re-generated.\n */\n regenerate: (messageId?: string) => Promise<void>;\n /**\n * Replaces the content of an existing user message and re-runs from that point.\n * Truncates everything after the edited message and re-invokes the handler.\n */\n editMessage: (messageId: string, newContent: string) => Promise<void>;\n scrollToBottom: () => void;\n /** Pre-binds navigator.clipboard.writeText + the onCopy prop callback. */\n handleCopy: (content: string) => void;\n\n // ── Message state ─────────────────────────────────────────────────────────\n messages: ChatMessage[];\n setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>;\n\n // ── Input state ───────────────────────────────────────────────────────────\n input: string;\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n // ── Generation state ──────────────────────────────────────────────────────\n isTyping: boolean;\n isRetrying: boolean;\n isInterrupted: boolean;\n streamingReasoning: string;\n /** Name from the latest streamed `status` chunk — picks the thinking-indicator word pool. */\n streamingStatus?: string;\n /** Forwarded from Chat.Canvas thinkingStatus prop so Chat.Messages can read it. */\n thinkingStatus?: string;\n\n // ── Scroll / layout ───────────────────────────────────────────────────────\n showScrollButton: boolean;\n /** Called by Chat.Input to report its measured height so Canvas positions the scroll button. */\n setInputHeight: (height: number) => void;\n\n // ── Refs exposed to children ──────────────────────────────────────────────\n messagesContainerRef: React.RefObject<HTMLDivElement | null>;\n /** Called by Chat.Messages on mount/unmount so Canvas can attach scroll listener lazily. */\n registerMessagesContainer: (el: HTMLDivElement | null) => void;\n bottomRef: React.RefObject<HTMLDivElement | null>;\n lastUserInputRef: React.MutableRefObject<string>;\n hasEverSentRef: React.MutableRefObject<boolean>;\n shouldStopRef: React.MutableRefObject<boolean>;\n\n // ── Attachments ───────────────────────────────────────────────────────────\n attachments: ChatAttachment[];\n addAttachments: (files: File[]) => void;\n removeAttachment: (id: string) => void;\n /** Declarative list of allowed attachment kinds; renders the `+` menu in Chat.Input when set. */\n allowedAttachments?: Array<\"files\" | \"photos\">;\n\n // ── Approval (HITL) ───────────────────────────────────────────────────────\n /** Latest unanswered approval request from the assistant, or null. */\n pendingApproval: ChatApprovalRequest | null;\n /**\n * Set when the user clicks an option marked `freeform: true`. While this is\n * non-null, Chat.Input is unlocked and the next submission resolves the\n * approval (carrying the typed text) instead of being sent as a normal turn.\n */\n awaitingFreeformApproval: { approvalId: string; optionId: string } | null;\n /**\n * Resolves an approval request. If the option is `freeform`, transitions\n * into the awaiting-freeform state instead of resolving immediately.\n */\n resolveApproval: (approvalId: string, optionId: string) => void;\n\n // ── Callbacks forwarded from Canvas props ─────────────────────────────────\n onStop?: () => void;\n}\n\nexport const ChatContext = createContext<ChatContextValue>({} as ChatContextValue);\n\nexport function useChatContext(): ChatContextValue {\n return useContext(ChatContext);\n}\n","import React from \"react\";\nimport { Body1, Button, makeStyles, tokens } from \"@fluentui/react-components\";\nimport {\n ErrorCircle20Regular,\n Clock20Regular,\n LockClosed20Regular,\n PlugDisconnected20Regular,\n Warning20Regular,\n ArrowCounterclockwise16Regular,\n} from \"@fluentui/react-icons\";\n\n// ---- Error normalization ----\n\nexport type ErrorCategory =\n | \"auth_billing\"\n | \"rate_limit\"\n | \"overloaded\"\n | \"bad_input\"\n | \"not_found\"\n | \"server_error\"\n | \"unknown\";\n\n/**\n * A categorized, user-friendly error. This shape is JSON-serializable so it\n * can be stored on a `ChatMessage` and survive persistence / rehydration.\n */\nexport interface NormalizedChatError {\n category: ErrorCategory;\n message: string;\n}\n\nconst ERROR_CATEGORIES: ErrorCategory[] = [\n \"auth_billing\",\n \"rate_limit\",\n \"overloaded\",\n \"bad_input\",\n \"not_found\",\n \"server_error\",\n \"unknown\",\n];\n\n/** True when `err` is already a `NormalizedChatError` (e.g. rehydrated from storage). */\nfunction isNormalizedChatError(err: unknown): err is NormalizedChatError {\n return (\n !!err &&\n typeof err === \"object\" &&\n typeof (err as NormalizedChatError).message === \"string\" &&\n ERROR_CATEGORIES.includes((err as NormalizedChatError).category)\n );\n}\n\n/**\n * Normalizes raw errors from Anthropic, OpenAI, and Google Gemini into a\n * common category + user-friendly message. Safe to call with any unknown value.\n * Idempotent — passing an already-normalized error returns it unchanged.\n */\nexport function normalizeChatError(err: unknown): NormalizedChatError {\n // Already normalized (persisted error rehydrated from storage) — pass through.\n if (isNormalizedChatError(err)) return err;\n\n const anyErr = err as Record<string, unknown>;\n const rawMessage = String(\n anyErr?.message ?? (anyErr?.error as Record<string, unknown>)?.message ?? err ?? \"\"\n ).toLowerCase();\n\n const status = Number(anyErr?.status ?? anyErr?.statusCode ?? 0);\n const errorType = String(\n (anyErr?.error as Record<string, unknown>)?.type ?? anyErr?.type ?? anyErr?.code ?? \"\"\n );\n const errorCode = String(\n (anyErr?.error as Record<string, unknown>)?.code ?? anyErr?.code ?? \"\"\n );\n\n // Auth / billing — Anthropic \"credit\", OpenAI \"insufficient_quota\", Gemini PERMISSION_DENIED\n if (\n rawMessage.includes(\"credit\") ||\n rawMessage.includes(\"billing\") ||\n rawMessage.includes(\"insufficient_quota\") ||\n errorCode === \"insufficient_quota\" ||\n errorType === \"PERMISSION_DENIED\"\n ) {\n return {\n category: \"auth_billing\",\n message: \"API credits exhausted. Add credits in your provider's billing dashboard.\",\n };\n }\n\n // Rate limit — Anthropic rate_limit_error, OpenAI 429, Gemini RESOURCE_EXHAUSTED\n if (\n errorType === \"rate_limit_error\" ||\n rawMessage.includes(\"rate limit\") ||\n rawMessage.includes(\"too many requests\")\n ) {\n return {\n category: \"rate_limit\",\n message: \"You're being rate limited. Wait a moment and try again.\",\n };\n }\n\n // Overloaded — Anthropic overloaded_error (529), OpenAI 503\n if (\n status === 529 ||\n status === 503 ||\n errorType === \"overloaded_error\" ||\n errorType === \"RESOURCE_EXHAUSTED\" ||\n rawMessage.includes(\"overload\") ||\n rawMessage.includes(\"capacity\")\n ) {\n return {\n category: \"overloaded\",\n message: \"The AI service is overloaded right now. Try again in a few seconds.\",\n };\n }\n\n // Not found — OpenAI 404 / model_not_found, Gemini NOT_FOUND\n if (\n status === 404 ||\n errorType === \"NOT_FOUND\" ||\n rawMessage.includes(\"model_not_found\") ||\n rawMessage.includes(\"not found\")\n ) {\n return {\n category: \"not_found\",\n message: \"Model not found. Check the model name in your configuration.\",\n };\n }\n\n // Bad input — Anthropic/OpenAI invalid_request_error (400), Gemini INVALID_ARGUMENT\n if (\n status === 400 ||\n errorType === \"invalid_request_error\" ||\n errorType === \"INVALID_ARGUMENT\"\n ) {\n return {\n category: \"bad_input\",\n message: \"The request was invalid. Check your message or API configuration.\",\n };\n }\n\n // Server error — 5xx, Anthropic api_error, Gemini INTERNAL\n if (status >= 500 || errorType === \"api_error\" || errorType === \"INTERNAL\") {\n return {\n category: \"server_error\",\n message: \"The AI service hit an internal error. Try again shortly.\",\n };\n }\n\n return {\n category: \"unknown\",\n message: \"Something went wrong. Check your connection and try again.\",\n };\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n root: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"8px\",\n padding: \"12px\",\n borderRadius: tokens.borderRadiusXLarge,\n backgroundColor: tokens.colorNeutralBackground3,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n color: tokens.colorNeutralForeground3,\n width: \"100%\",\n boxSizing: \"border-box\",\n margin: \"8px 0\",\n },\n left: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n minWidth: 0,\n },\n message: {\n fontFamily: \"var(--fontFamilyMonospace)\",\n },\n});\n\nconst categoryIcon: Record<ErrorCategory, React.ReactElement> = {\n auth_billing: <LockClosed20Regular />,\n rate_limit: <Clock20Regular />,\n overloaded: <PlugDisconnected20Regular />,\n bad_input: <Warning20Regular />,\n not_found: <ErrorCircle20Regular />,\n server_error: <ErrorCircle20Regular />,\n unknown: <Warning20Regular />,\n};\n\n// ---- Component ----\n\nexport interface ChatErrorProps {\n /** Raw error thrown by your onSendMessage handler — any provider shape works. */\n error: unknown;\n /** Optional retry callback shown as a button. */\n onRetry?: () => void;\n}\n\nconst ChatError: React.FC<ChatErrorProps> = ({ error, onRetry }) => {\n const styles = useStyles();\n const { category, message } = normalizeChatError(error);\n\n return (\n <div className={styles.root}>\n <span className={styles.left}>\n {categoryIcon[category]}\n <Body1 className={styles.message}>{message}</Body1>\n </span>\n {onRetry && (\n <Button\n size=\"small\"\n appearance=\"primary\"\n onClick={onRetry}\n >\n Retry\n </Button>\n )}\n </div>\n );\n};\n\nexport default ChatError;\n","/**\n * Reads a browser `File` and returns its raw base64 payload (without the\n * `data:<mime>;base64,` prefix).\n *\n * Used by Coral's built-in `api` handler to serialize attachments before\n * POSTing them to the engineer's backend, and exported so consumers writing\n * a custom `onSendMessage` can reuse the same encoding.\n */\nexport function fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const comma = dataUrl.indexOf(\",\");\n resolve(comma === -1 ? dataUrl : dataUrl.slice(comma + 1));\n };\n reader.onerror = () => reject(reader.error ?? new Error(\"FileReader failed\"));\n reader.readAsDataURL(file);\n });\n}\n","import React, { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Body1,\n Button,\n Caption1,\n makeStyles,\n tokens,\n} from \"@fluentui/react-components\";\nimport {\n ArrowClockwise,\n Copy,\n Edit as EditIcon,\n Info,\n Warning,\n} from \"@coral-ai/bundleicons\";\nimport {\n CoralMarkdown,\n type ChatFontSize,\n type ChatFontFamily,\n} from \"@coral-ai/markdown\";\nimport { useChatContext } from \"./Chat.Context\";\nimport ThinkingIndicator from \"./Chat.ThinkingIndicator\";\nimport { resolveTaskMessages } from \"./Chat.TaskMessages\";\nimport ChatCallout from \"./Chat.Callout\";\nimport ChatError from \"./Chat.Error\";\nimport ReasoningBlock from \"./Chat.ReasoningBlock\";\nimport ChatTodoList from \"./Chat.TodoList\";\nimport { CoralChart } from \"@coral-ai/charts\";\nimport type { ChatMessage, ChatComponents } from \"./Chat\";\nimport { CheckmarkCircle20Filled } from \"@fluentui/react-icons\";\n\n// ---- Props ----\n\nexport interface ChatMessagesProps {\n /**\n * Custom renderers keyed by message type.\n * Falls back to default markdown rendering if no match.\n */\n components?: ChatComponents;\n /** Called when the user copies an assistant message. */\n onCopy?: (content: string) => void;\n /** Called when the user clicks an internal link (href starts with \"/\"). */\n onNavigate?: (path: string) => void;\n /** Font size for assistant message markdown. */\n fontSize?: ChatFontSize;\n /** Font family for assistant message markdown. */\n fontFamily?: ChatFontFamily;\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n messages: {\n flex: \"1\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n padding: \"40px 0\",\n boxSizing: \"border-box\",\n scrollbarGutter: \"stable both-edges\",\n },\n messageWrapper: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"24px\",\n width: \"100%\",\n maxWidth: \"768px\",\n padding: \"0 16px\",\n boxSizing: \"border-box\",\n },\n // ── User message column: holds attachments + bubble + hover-only footer ──\n userRow: {\n alignSelf: \"flex-end\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n maxWidth: \"80%\",\n \"&:hover .coral-user-footer, &:focus-within .coral-user-footer\": {\n opacity: 1,\n },\n },\n userBubble: {\n backgroundColor: tokens.colorNeutralBackground2,\n color: tokens.colorNeutralForeground2,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n padding: \"8px 12px\",\n borderRadius: tokens.borderRadiusXLarge,\n wordBreak: \"break-word\",\n boxSizing: \"border-box\",\n },\n userFooter: {\n display: \"flex\",\n justifyContent: \"flex-end\",\n marginTop: \"6px\",\n marginRight: \"-10px\",\n opacity: 0,\n transition: \"opacity 120ms ease-in-out\",\n },\n userActions: {\n display: \"flex\",\n },\n // ── Inline edit mode ──\n userEditWrap: {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"stretch\",\n width: \"min(640px, 80vw)\",\n gap: \"8px\",\n },\n userEditTextarea: {\n backgroundColor: tokens.colorNeutralBackground2,\n color: tokens.colorNeutralForeground2,\n border: `1px solid ${tokens.colorNeutralStroke1}`,\n padding: \"8px 12px\",\n borderRadius: tokens.borderRadiusLarge,\n fontFamily: tokens.fontFamilyBase,\n fontSize: tokens.fontSizeBase300,\n lineHeight: tokens.lineHeightBase300,\n resize: \"none\",\n outline: \"none\",\n width: \"100%\",\n boxSizing: \"border-box\",\n minHeight: \"40px\",\n \"&:focus\": {\n border: `1px solid ${tokens.colorNeutralStroke3}`,\n },\n },\n userEditFooter: {\n display: \"flex\",\n marginTop: \"8px\",\n // marginLeft: \"12px\",\n color: `${tokens.colorNeutralForeground3}`,\n gap: \"12px\",\n alignItems: \"center\",\n },\n userEditActions: {\n display: \"flex\",\n justifyContent: \"flex-end\",\n gap: \"8px\",\n },\n // ── Assistant message ──\n messageAssistant: {\n alignSelf: \"flex-start\",\n width: \"100%\",\n color: tokens.colorNeutralForeground2,\n wordBreak: \"break-word\",\n boxSizing: \"border-box\",\n \"&:hover .coral-assistant-footer, &:focus-within .coral-assistant-footer\": {\n opacity: 1,\n },\n },\n assistantFooter: {\n display: \"flex\",\n justifyContent: \"space-between\",\n marginTop: \"6px\",\n marginLeft: \"-10px\",\n // Hover-only by default; the latest message overrides this to stay visible.\n opacity: 0,\n transition: \"opacity 120ms ease-in-out\",\n },\n assistantActions: {\n display: \"flex\",\n },\n copiedBadge: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"32px\",\n height: \"32px\",\n color: tokens.colorPaletteSeafoamForeground2,\n },\n footerIconButton: {\n color: tokens.colorNeutralForeground3,\n },\n});\n\n// ---- Component ----\n\nconst ChatMessages: React.FC<ChatMessagesProps> = ({\n components,\n onCopy,\n onNavigate,\n fontSize,\n fontFamily,\n}) => {\n const styles = useStyles();\n const ctx = useChatContext();\n const {\n messages,\n setMessages,\n isTyping,\n isRetrying,\n isInterrupted,\n streamingReasoning,\n streamingStatus,\n thinkingStatus,\n sendMessage,\n regenerate,\n editMessage,\n handleCopy,\n lastUserInputRef,\n registerMessagesContainer,\n bottomRef,\n } = ctx;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const [surface, setSurface] = useState<string | null>(null);\n useLayoutEffect(() => {\n const el = containerRef.current?.closest(\"[data-coral-surface]\");\n setSurface(el?.getAttribute(\"data-coral-surface\") ?? null);\n }, []);\n const isSidecar = surface === \"panel-right\";\n const [copiedKey, setCopiedKey] = useState<string | null>(null);\n const copiedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // ── Edit mode state ──────────────────────────────────────────────────────\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editDraft, setEditDraft] = useState(\"\");\n const editTextareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n registerMessagesContainer(containerRef.current);\n return () => registerMessagesContainer(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Auto-grow + focus the edit textarea when entering edit mode.\n useLayoutEffect(() => {\n if (editingId && editTextareaRef.current) {\n const ta = editTextareaRef.current;\n ta.focus();\n ta.setSelectionRange(ta.value.length, ta.value.length);\n ta.style.height = \"auto\";\n ta.style.height = `${ta.scrollHeight}px`;\n }\n }, [editingId]);\n\n const startEdit = (msg: ChatMessage) => {\n if (!msg.id) return;\n setEditingId(msg.id);\n setEditDraft(msg.content);\n };\n\n const cancelEdit = () => {\n setEditingId(null);\n setEditDraft(\"\");\n };\n\n const saveEdit = async () => {\n if (!editingId) return;\n const trimmed = editDraft.trim();\n if (!trimmed) return;\n const id = editingId;\n setEditingId(null);\n setEditDraft(\"\");\n await editMessage(id, trimmed);\n };\n\n const handleEditTextareaInput = (\n e: React.ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setEditDraft(e.target.value);\n const ta = e.target;\n ta.style.height = \"auto\";\n ta.style.height = `${ta.scrollHeight}px`;\n };\n\n const handleEditKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n cancelEdit();\n } else if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n void saveEdit();\n }\n };\n\n const onCopyMerged = (content: string, key: string) => {\n handleCopy(content);\n onCopy?.(content);\n if (copiedTimerRef.current) clearTimeout(copiedTimerRef.current);\n setCopiedKey(key);\n copiedTimerRef.current = setTimeout(() => setCopiedKey(null), 1500);\n };\n\n // ── Renderers ────────────────────────────────────────────────────────────\n\n const renderUserMessage = (msg: ChatMessage, index: number) => {\n const key = msg.id ?? `idx-${index}`;\n const isEditing = !!msg.id && editingId === msg.id;\n const attachments = Array.isArray(msg.metadata?.attachments)\n ? (msg.metadata!.attachments as Array<{\n name: string;\n type: string;\n preview?: string;\n }>)\n : null;\n\n return (\n <div key={key} className={styles.userRow}>\n {attachments && (\n <div\n style={{\n display: \"flex\",\n gap: \"6px\",\n flexWrap: \"wrap\",\n marginBottom: \"6px\",\n }}\n >\n {attachments.map((a, i) =>\n a.type.startsWith(\"image/\") && a.preview ? (\n <img\n key={i}\n src={a.preview}\n alt={a.name}\n style={{\n width: 64,\n height: 64,\n borderRadius: tokens.borderRadiusMedium,\n objectFit: \"cover\",\n }}\n />\n ) : (\n <span\n key={i}\n style={{\n fontSize: 12,\n padding: \"2px 8px\",\n borderRadius: tokens.borderRadiusSmall,\n backgroundColor: tokens.colorNeutralBackground3,\n color: tokens.colorNeutralForeground2,\n }}\n >\n 📄 {a.name}\n </span>\n ),\n )}\n </div>\n )}\n\n {isEditing ? (\n <div className={styles.userEditWrap}>\n <textarea\n ref={editTextareaRef}\n className={styles.userEditTextarea}\n value={editDraft}\n onChange={handleEditTextareaInput}\n onKeyDown={handleEditKeyDown}\n rows={1}\n />\n\n <div className={styles.userEditFooter}>\n <Info\n style={{\n marginRight: \"6px\",\n color: `${tokens.colorNeutralForeground3}`,\n fontSize: \"20px\",\n boxSizing: \"border-box\",\n flexShrink: 0,\n }}\n />\n <Caption1>\n Editing this message will discard the current response and\n regenerate from here.\n </Caption1>\n <div className={styles.userEditActions}>\n <Button appearance=\"subtle\" onClick={cancelEdit}>\n Cancel\n </Button>\n <Button\n appearance=\"primary\"\n onClick={saveEdit}\n disabled={!editDraft.trim()}\n >\n Save\n </Button>\n </div>\n </div>\n </div>\n ) : (\n <>\n <div className={styles.userBubble}>\n <Body1>\n {msg.content.split(\"\\n\").map((line, i, arr) => (\n <React.Fragment key={i}>\n {line}\n {i < arr.length - 1 && <br />}\n </React.Fragment>\n ))}\n </Body1>\n </div>\n {msg.id && (\n <div className={`${styles.userFooter} coral-user-footer`}>\n <div className={styles.userActions}>\n {copiedKey === `user-${key}` ? (\n <span className={styles.copiedBadge}>\n <CheckmarkCircle20Filled />\n </span>\n ) : (\n <Button\n onClick={() => onCopyMerged(msg.content, `user-${key}`)}\n title=\"Copy message\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<Copy />}\n />\n )}\n <Button\n onClick={() => startEdit(msg)}\n title=\"Edit message\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<EditIcon />}\n />\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n };\n\n const renderAssistantMessage = (msg: ChatMessage, index: number) => {\n const isLatest = index === messages.length - 1;\n const reasoning =\n isLatest && isTyping\n ? streamingReasoning\n : (msg.metadata?.reasoning as string | undefined);\n\n if (msg.type && components?.[msg.type]) {\n const CustomRenderer = components[msg.type];\n return (\n <CustomRenderer\n message={msg}\n onReply={(content) => {\n const updatedMessages: ChatMessage[] = [\n ...messages.slice(0, index + 1),\n { role: \"user\", content },\n ];\n setMessages(updatedMessages);\n sendMessage(content);\n }}\n />\n );\n }\n\n const key = msg.id ?? `idx-${index}`;\n\n return (\n <div>\n {reasoning && (\n <ReasoningBlock\n content={reasoning}\n isStreaming={isLatest && isTyping && !msg.content}\n />\n )}\n {msg.todos && msg.todos.length > 0 && (\n <ChatTodoList todos={msg.todos} />\n )}\n {msg.charts && msg.charts.length > 0 && (\n <>\n {msg.charts.map((spec, i) => (\n <CoralChart key={i} spec={spec} />\n ))}\n </>\n )}\n <CoralMarkdown\n onNavigate={onNavigate}\n fontSize={fontSize}\n fontFamily={fontFamily}\n >\n {msg.content}\n </CoralMarkdown>\n {msg.error && (\n <ChatError\n error={msg.error}\n onRetry={() => {\n const userMsg = messages[index - 1];\n if (userMsg?.role === \"user\") sendMessage(userMsg.content);\n }}\n />\n )}\n {isInterrupted && !isTyping && isLatest && (\n <ChatCallout\n message=\"Response was interrupted\"\n onRetry={() => sendMessage(lastUserInputRef.current)}\n />\n )}\n {!(isTyping && isLatest) && msg.content.trim() && (\n <div\n className={`${styles.assistantFooter} coral-assistant-footer`}\n // Latest message keeps its footer pinned visible; older ones\n // fall back to the hover-only rule on `.messageAssistant`.\n style={isLatest ? { opacity: 1 } : undefined}\n >\n <div className={styles.assistantActions}>\n {copiedKey === `assistant-${key}` ? (\n <span className={styles.copiedBadge}>\n <CheckmarkCircle20Filled />\n </span>\n ) : (\n <Button\n onClick={() => onCopyMerged(msg.content, `assistant-${key}`)}\n title=\"Copy response\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<Copy />}\n />\n )}\n {isLatest && (\n <Button\n onClick={() => regenerate(msg.id)}\n title=\"Regenerate response\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<ArrowClockwise />}\n />\n )}\n </div>\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={styles.messages} ref={containerRef}>\n <div\n className={styles.messageWrapper}\n style={isSidecar ? { padding: \"0 8px\" } : undefined}\n >\n {messages.map((msg, index) => {\n if (msg.role === \"user\") {\n return renderUserMessage(msg, index);\n }\n const key = msg.id ?? `idx-${index}`;\n const isLatest = index === messages.length - 1;\n return (\n <div\n key={key}\n className={`${styles.messageAssistant} coral-message-assistant${isLatest ? \" is-latest\" : \"\"}`}\n >\n {renderAssistantMessage(msg, index)}\n </div>\n );\n })}\n\n {isTyping && (\n <ThinkingIndicator\n isRetrying={isRetrying}\n status={thinkingStatus}\n messages={resolveTaskMessages(streamingStatus)}\n />\n )}\n <div ref={bottomRef} />\n </div>\n </div>\n );\n};\n\nexport default ChatMessages;\n","import React, { useState, useEffect, useRef } from \"react\";\nimport { makeStyles, Spinner, tokens } from \"@fluentui/react-components\";\n\nconst thinkingMessages = [\n \"Generating\",\n \"Thinking\",\n \"Optimizing\",\n \"Processing\",\n \"Analyzing\",\n \"Drafting\",\n \"Evaluating\",\n \"Computing\",\n \"Synthesizing\",\n \"Reviewing\",\n \"Refining\",\n];\n\nconst retryingMessages = [\n \"Still working\",\n \"Awaiting\",\n \"Hang tight\",\n \"One moment\",\n \"Almost there\",\n \"Just a moment\",\n \"Reconnecting\",\n];\n\nconst TYPING_SPEED = 80; // ms per character\nconst HOLD_DURATION = 1300; // ms to hold the full word before moving on\n\nconst useStyles = makeStyles({\n root: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n width: \"100%\",\n color: tokens.colorNeutralForeground3,\n },\n text: {\n // fontFamily: tokens.fontFamilyBase,\n // fontSize: tokens.fontSizeBase200,\n // color: tokens.colorNeutralForeground3,\n fontFamily: \"var(--fontFamilyMonospace)\",\n minWidth: \"0\",\n },\n cursor: {\n display: \"inline-block\",\n width: \"6px\",\n height: \"1em\",\n backgroundColor: tokens.colorNeutralForeground3,\n marginLeft: \"1px\",\n verticalAlign: \"text-bottom\",\n animationName: {\n \"0%, 100%\": { opacity: \"1\" },\n \"50%\": { opacity: \"0\" },\n },\n animationDuration: \"0.9s\",\n animationTimingFunction: \"step-end\",\n animationIterationCount: \"infinite\",\n },\n});\n\ninterface ThinkingIndicatorProps {\n isRetrying?: boolean;\n /** Override the cycling animation with a static status string. The animated icon is retained. */\n status?: string;\n /**\n * Override the pool of cycling words. Falls back to the default `thinkingMessages`\n * pool when omitted. Ignored while `isRetrying` is true (retry uses its own pool).\n */\n messages?: string[];\n}\n\nconst ThinkingIndicator: React.FC<ThinkingIndicatorProps> = ({ isRetrying = false, status, messages }) => {\n const styles = useStyles();\n const [displayText, setDisplayText] = useState(\"\");\n const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const msgIdxRef = useRef(0);\n const charIdxRef = useRef(0);\n\n useEffect(() => {\n const pool = isRetrying ? retryingMessages : (messages && messages.length > 0 ? messages : thinkingMessages);\n // Reset animation when mode switches\n msgIdxRef.current = 0;\n charIdxRef.current = 0;\n\n const tick = () => {\n const word = pool[msgIdxRef.current];\n\n if (charIdxRef.current < word.length) {\n charIdxRef.current += 1;\n setDisplayText(word.slice(0, charIdxRef.current));\n timerRef.current = setTimeout(tick, TYPING_SPEED);\n } else {\n // Finished typing the word — hold, then advance\n timerRef.current = setTimeout(() => {\n msgIdxRef.current = (msgIdxRef.current + 1) % pool.length;\n charIdxRef.current = 0;\n tick();\n }, HOLD_DURATION);\n }\n };\n\n tick();\n return () => clearTimeout(timerRef.current);\n }, [isRetrying, messages]);\n\n return (\n <div className={styles.root}>\n <Spinner size=\"tiny\" />\n <span className={styles.text}>\n {status ?? displayText}\n <span className={styles.cursor} />\n </span>\n </div>\n );\n};\n\nexport default ThinkingIndicator;\n","/**\n * Built-in task vocabulary for the thinking indicator's per-task word pools.\n *\n * A handler streams a `{ type: \"status\", name }` chunk to tell the indicator\n * which pool to cycle while it works. `name` is matched against these keys;\n * anything unrecognized falls back to the `text` pool.\n *\n * - `text` — default text-only response.\n * - `photo` — vision / image-reading responses.\n * - `file` — document / PDF responses.\n * - `voice` — audio transcription responses.\n */\nexport type CoralTaskType = \"text\" | \"photo\" | \"file\" | \"voice\";\n\nexport const DEFAULT_TASK_MESSAGES: Record<CoralTaskType, string[]> = {\n text: [\n \"Generating\",\n \"Thinking\",\n \"Optimizing\",\n \"Processing\",\n \"Analyzing\",\n \"Drafting\",\n \"Evaluating\",\n \"Computing\",\n \"Synthesizing\",\n \"Reviewing\",\n \"Refining\",\n ],\n photo: [\"Looking\", \"Examining\", \"Reading image\", \"Analyzing visuals\"],\n file: [\"Reading document\", \"Parsing\", \"Reviewing\", \"Scanning\"],\n voice: [\"Listening\", \"Transcribing\", \"Processing audio\"],\n};\n\n/**\n * Picks the thinking-indicator word pool for a streamed status name. If `name`\n * matches a built-in task type, its pool is used; otherwise the `text` pool is\n * the fallback. For bespoke copy, use the `thinkingStatus` prop on `<Chat>`.\n */\nexport function resolveTaskMessages(name?: string): string[] {\n if (name && name in DEFAULT_TASK_MESSAGES) {\n return DEFAULT_TASK_MESSAGES[name as CoralTaskType];\n }\n return DEFAULT_TASK_MESSAGES.text;\n}\n","import React from \"react\";\nimport { Body1, Button, makeStyles, mergeClasses, tokens } from \"@fluentui/react-components\";\nimport { ChatWarning20Regular } from \"@fluentui/react-icons\";\n\ninterface ChatCalloutProps {\n message: string;\n onRetry?: () => void;\n className?: string;\n}\n\nconst useStyles = makeStyles({\n root: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"8px\",\n padding: \"12px 12px\",\n borderRadius: tokens.borderRadiusXLarge,\n backgroundColor: tokens.colorNeutralBackground3,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n color: tokens.colorNeutralForeground3,\n width: \"100%\",\n boxSizing: \"border-box\",\n margin: \"24px 0\",\n },\n left: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n },\n label: {\n fontFamily: \"var(--fontFamilyMonospace)\",\n },\n retryButton: {\n minWidth: 0,\n },\n});\n\nconst ChatCallout: React.FC<ChatCalloutProps> = ({ message, onRetry, className }) => {\n const styles = useStyles();\n\n return (\n <div className={mergeClasses(styles.root, className)}>\n <span className={styles.left}>\n <ChatWarning20Regular />\n <Body1 className={styles.label}>{message}</Body1>\n </span>\n {onRetry && (\n <Button\n onClick={onRetry}\n className={styles.retryButton}\n size=\"small\"\n appearance=\"primary\"\n >\n Retry\n </Button>\n )}\n </div>\n );\n};\n\nexport default ChatCallout;\n","import React, { useState, useEffect, useRef } from \"react\";\nimport { Body1, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { ChevronDown16Regular, ChevronRight16Regular } from \"@fluentui/react-icons\";\n\nexport interface ReasoningBlockProps {\n /** Full accumulated reasoning content. */\n content: string;\n /** True while the model is still streaming reasoning tokens. */\n isStreaming?: boolean;\n}\n\nconst useStyles = makeStyles({\n root: {\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n margin: \"12px 0 40px 0\",\n },\n header: {\n display: \"flex\",\n alignItems: \"center\",\n padding: \"0\",\n cursor: \"pointer\",\n background: \"none\",\n border: \"none\",\n width: \"100%\",\n textAlign: \"left\",\n gap: \"8px\",\n },\n labelRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n minWidth: 0,\n },\n pulseContainer: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"16px\",\n height: \"16px\",\n },\n pulse: {\n flexShrink: 0,\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: tokens.colorNeutralForeground3,\n animationName: {\n \"0%, 100%\": { opacity: \"1\" },\n \"50%\": { opacity: \"0.2\" },\n },\n animationDuration: \"1.2s\",\n animationTimingFunction: \"ease-in-out\",\n animationIterationCount: \"infinite\",\n },\n pulseDone: {\n flexShrink: 0,\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: tokens.colorBrandForeground1,\n },\n label: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n marginBottom: \"2px\",\n },\n chevron: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n transition: \"transform 0.2s ease\",\n },\n chevronExpanded: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n transition: \"transform 0.2s ease\",\n transform: \"rotate(90deg)\",\n },\n expanded: {\n padding: \"16px 0 0 0\",\n marginLeft: \"22px\",\n fontSize: tokens.fontSizeBase300,\n color: tokens.colorNeutralForeground3,\n fontFamily: \"var(--fontFamilyMonospace)\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n // maxHeight: \"320px\",\n // overflowY: \"auto\",\n },\n});\n\nconst ReasoningBlock: React.FC<ReasoningBlockProps> = ({\n content,\n isStreaming = false,\n}) => {\n const styles = useStyles();\n const [expanded, setExpanded] = useState(false);\n const [duration, setDuration] = useState<number | null>(null);\n const startTimeRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (isStreaming) {\n startTimeRef.current = Date.now();\n setDuration(null);\n } else if (startTimeRef.current !== null) {\n setDuration(Math.round((Date.now() - startTimeRef.current) / 1000));\n startTimeRef.current = null;\n }\n }, [isStreaming]);\n\n const label = isStreaming\n ? \"Thinking\"\n : duration !== null\n ? `Thought for ${duration}s`\n : \"Thought\";\n\n return (\n <div className={styles.root}>\n <button className={styles.header} onClick={() => setExpanded((e) => !e)}>\n <div className={styles.labelRow}>\n <div className={styles.pulseContainer}>\n <span className={isStreaming ? styles.pulse : styles.pulseDone} />\n </div>\n <Body1 className={styles.label}>{label}</Body1>\n <ChevronRight16Regular\n className={expanded ? styles.chevronExpanded : styles.chevron}\n />\n </div>\n </button>\n\n {expanded && (\n <div className={styles.expanded}>{content}</div>\n )}\n </div>\n );\n};\n\nexport default ReasoningBlock;\n","import React, { useState } from \"react\";\nimport {\n Body1,\n Caption1,\n makeStyles,\n tokens,\n} from \"@fluentui/react-components\";\nimport {\n CheckboxCheckedFilled,\n CheckboxUncheckedRegular,\n ChevronRightRegular,\n SquareHintRegular,\n} from \"@fluentui/react-icons\";\nimport type { ChatTodo } from \"./Chat\";\n\nexport interface ChatTodoListProps {\n /** The current task plan. The whole list is replaced on each agent update. */\n todos: ChatTodo[];\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst useStyles = makeStyles({\n root: {\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n margin: \"12px 0\",\n borderRadius: \"var(--borderRadiusXLarge)\",\n backgroundColor: \"var(--colorNeutralBackgroundAlpha2)\",\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n overflow: \"hidden\",\n },\n header: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"10px 14px\",\n cursor: \"pointer\",\n background: \"none\",\n border: \"none\",\n width: \"100%\",\n textAlign: \"left\",\n },\n label: {\n color: tokens.colorNeutralForeground2,\n flexShrink: 0,\n },\n count: {\n color: tokens.colorNeutralForeground3,\n marginLeft: \"auto\",\n flexShrink: 0,\n },\n chevron: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n fontSize: \"16px\",\n transition: \"transform 0.2s ease\",\n },\n chevronExpanded: {\n transform: \"rotate(90deg)\",\n },\n list: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"8px\",\n padding: \"2px 14px 14px 14px\",\n },\n item: {\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: \"8px\",\n },\n iconCell: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"20px\",\n height: \"20px\",\n fontSize: \"20px\",\n flexShrink: 0,\n },\n pendingIcon: {\n color: tokens.colorNeutralForegroundDisabled,\n },\n activeIcon: {\n color: tokens.colorNeutralForeground2,\n },\n doneIcon: {\n color: tokens.colorPaletteSeafoamForeground2,\n },\n text: {\n minWidth: 0,\n wordBreak: \"break-word\",\n },\n pendingText: {\n color: tokens.colorNeutralForeground3,\n },\n activeText: {\n color: tokens.colorNeutralForeground1,\n fontWeight: tokens.fontWeightSemibold,\n },\n doneText: {\n color: tokens.colorNeutralForeground3,\n textDecorationLine: \"line-through\",\n },\n});\n\nconst ChatTodoList: React.FC<ChatTodoListProps> = ({\n todos,\n className,\n style,\n}) => {\n const styles = useStyles();\n\n const total = todos.length;\n const completed = todos.filter((t) => t.status === \"completed\").length;\n // The list stays open as the agent works — collapsing is the user's call,\n // never the chat's. Defaults open; the header toggle is the only thing that\n // changes it, so streaming todo updates can't make it flash open/closed.\n const [expanded, setExpanded] = useState(true);\n\n if (total === 0) return null;\n\n return (\n <div\n className={`${styles.root}${className ? ` ${className}` : \"\"}`}\n style={style}\n role=\"group\"\n aria-label={`Task plan, ${completed} of ${total} done`}\n >\n <button\n type=\"button\"\n className={styles.header}\n onClick={() => setExpanded((e) => !e)}\n aria-expanded={expanded}\n >\n <ChevronRightRegular\n className={`${styles.chevron}${expanded ? ` ${styles.chevronExpanded}` : \"\"}`}\n />\n <Body1 className={styles.label}>Tasks</Body1>\n <Caption1 className={styles.count}>\n {completed}/{total}\n </Caption1>\n </button>\n\n {expanded && (\n <div className={styles.list} role=\"list\">\n {todos.map((todo, index) => {\n const text =\n todo.status === \"in_progress\"\n ? (todo.activeForm ?? todo.content)\n : todo.content;\n const textClass =\n todo.status === \"completed\"\n ? styles.doneText\n : todo.status === \"in_progress\"\n ? styles.activeText\n : styles.pendingText;\n return (\n <div\n key={todo.id ?? `todo-${index}`}\n className={styles.item}\n role=\"listitem\"\n >\n <span className={styles.iconCell}>\n {todo.status === \"completed\" ? (\n <CheckboxCheckedFilled className={styles.doneIcon} />\n ) : todo.status === \"in_progress\" ? (\n <CheckboxUncheckedRegular className={styles.activeIcon} />\n ) : (\n <SquareHintRegular className={styles.pendingIcon} />\n )}\n </span>\n <Body1 className={`${styles.text} ${textClass}`}>{text}</Body1>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n};\n\nexport default ChatTodoList;\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport { Body1, Button, Tag, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { Dismiss, Send, Stop } from \"@coral-ai/bundleicons\";\nimport { useChatContext } from \"./Chat.Context\";\nimport ChatAttachButton, { type ChatAttachType } from \"./Chat.AttachButton\";\nimport type { ChatAttachment } from \"./Chat\";\n\n// ---- Props ----\n\nexport interface ChatInputProps {\n /** Current input value. Optional inside Chat.Canvas — auto-wired from context. */\n value?: string;\n /** Change handler. Optional inside Chat.Canvas — auto-wired from context. */\n onChange?: (val: string) => void;\n /** Called on Enter. Optional inside Chat.Canvas — auto-wired to sendMessage. */\n onEnter?: () => void;\n placeholder?: string;\n /** Disabled state. */\n disabled?: boolean;\n style?: React.CSSProperties;\n /** Slot rendered at the left of the bottom toolbar. */\n actionsStart?: React.ReactNode;\n /** Slot rendered at the right of the bottom toolbar, just before Send/Stop. */\n actionsEnd?: React.ReactNode;\n /** Override attachments when used outside a Chat.Canvas. */\n attachments?: ChatAttachment[];\n /** Override remove handler when used outside a Chat.Canvas. */\n removeAttachment?: (id: string) => void;\n /**\n * Renders the `+` (Chat.AttachButton) menu before `actionsStart` content.\n * When omitted, falls back to the value in `useChatContext().allowedAttachments`\n * (set by Chat / Chat.Canvas via the `allowedAttachments` prop). When both are\n * undefined, no `+` button renders — current behavior preserved.\n */\n allowedAttachments?: ChatAttachType[];\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n wrapper: {\n width: \"100%\",\n margin: \"0 auto\",\n },\n card: {\n display: \"inline-flex\",\n flexDirection: \"column\",\n gap: \"8px\",\n alignItems: \"stretch\",\n width: \"100%\",\n padding: \"8px\",\n borderRadius: \"var(--borderRadiusXLarge)\",\n backgroundColor: \"var(--colorNeutralBackgroundAlpha2)\",\n transition: \"border-color 0.2s ease-in-out\",\n position: \"relative\",\n boxSizing: \"border-box\",\n overflow: \"hidden\",\n },\n cardFocused: {\n boxShadow: tokens.shadow28,\n },\n cardDisabled: {\n opacity: \"0.3\",\n pointerEvents: \"none\",\n },\n attachmentsRow: {\n display: \"flex\",\n gap: \"8px\",\n overflowX: \"auto\",\n padding: \"0 4px\",\n },\n attachmentItem: {\n position: \"relative\",\n flexShrink: 0,\n width: \"128px\",\n height: \"128px\",\n borderRadius: \"var(--borderRadiusMedium)\",\n overflow: \"hidden\",\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n backgroundColor: \"var(--colorNeutralBackground3)\",\n display: \"flex\",\n flexDirection: \"column\",\n },\n attachmentImage: {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n attachmentFile: {\n padding: \"12px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n justifyContent: \"space-between\",\n },\n attachmentFileName: {\n wordBreak: \"break-all\",\n color: \"var(--colorNeutralForeground2)\",\n overflow: \"hidden\",\n maxHeight: \"36px\",\n lineHeight: \"1.2\",\n },\n attachmentDismiss: {\n position: \"absolute\",\n top: \"6px\",\n right: \"6px\",\n },\n textarea: {\n resize: \"none\",\n overflowY: \"auto\",\n height: \"auto\",\n minHeight: \"24px\",\n maxHeight: \"150px\",\n padding: \"8px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n outline: \"none\",\n fontFamily: \"var(--fontFamilyBase)\",\n fontSize: \"var(--fontSizeBase300)\",\n fontWeight: \"var(--fontWeightRegular)\",\n color: \"var(--colorNeutralForeground1)\",\n lineHeight: \"1.5\",\n boxSizing: \"border-box\",\n width: \"100%\",\n },\n toolbar: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n maxHeight: \"32px\",\n },\n toolbarSide: {\n display: \"flex\",\n alignItems: \"center\",\n },\n focusBar: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"2px\",\n backgroundColor: \"var(--colorCompoundBrandStroke)\",\n transition: \"transform 0.2s ease-in-out\",\n textAlign: \"center\",\n },\n focusBarVisible: {\n transform: \"scaleX(1)\",\n },\n focusBarHidden: {\n transform: \"scaleX(0)\",\n },\n});\n\n// ---- Component ----\n\nconst ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(\n (\n {\n value: valueProp,\n onChange: onChangeProp,\n onEnter: onEnterProp,\n placeholder = \"Type a message...\",\n disabled: disabledProp,\n style,\n actionsStart,\n actionsEnd,\n attachments: attachmentsProp,\n removeAttachment: removeAttachmentProp,\n allowedAttachments: allowedAttachmentsProp,\n },\n ref,\n ) => {\n const styles = useStyles();\n const [isFocused, setIsFocused] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useImperativeHandle(ref, () => textareaRef.current as HTMLTextAreaElement);\n\n // ── Context wiring ────────────────────────────────────────────────────────\n const ctx = useChatContext();\n const isInsideCanvas = ctx.setInput !== undefined;\n const attachments = isInsideCanvas ? ctx.attachments : (attachmentsProp ?? []);\n const removeAttachment = isInsideCanvas ? ctx.removeAttachment : (removeAttachmentProp ?? (() => {}));\n const allowedAttachments = allowedAttachmentsProp ?? (isInsideCanvas ? ctx.allowedAttachments : undefined);\n\n const value = valueProp ?? (isInsideCanvas ? ctx.input : \"\");\n const onChange = onChangeProp ?? (isInsideCanvas ? ctx.setInput : () => {});\n const disabled = disabledProp ?? false;\n const onEnter =\n onEnterProp ??\n (isInsideCanvas\n ? () => {\n if (!ctx.isTyping) ctx.sendMessage();\n }\n : undefined);\n\n // ── Height reporting to Canvas (for scroll-button positioning) ────────────\n useEffect(() => {\n if (!isInsideCanvas) return;\n const el = containerRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n ctx.setInputHeight(el.offsetHeight);\n });\n ro.observe(el);\n ctx.setInputHeight(el.offsetHeight);\n return () => ro.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isInsideCanvas]);\n\n // ── Auto-grow textarea ────────────────────────────────────────────────────\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;\n }\n }, [value]);\n\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => {\n el.style.height = \"auto\";\n el.style.height = `${el.scrollHeight}px`;\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n // ── Send / Stop (always present in Canvas mode) ───────────────────────────\n const sendStopButton = isInsideCanvas ? (\n ctx.isTyping ? (\n <Button\n appearance=\"transparent\"\n onClick={() => {\n ctx.shouldStopRef.current = true;\n ctx.onStop?.();\n }}\n icon={<Stop />}\n style={{ cursor: \"default\" }}\n />\n ) : (\n <Button\n appearance=\"transparent\"\n onClick={() => ctx.sendMessage()}\n icon={<Send />}\n disabled={!value.trim()}\n style={{ cursor: \"default\" }}\n />\n )\n ) : null;\n\n return (\n <div ref={containerRef} className={styles.wrapper} style={style}>\n <div\n className={`${styles.card}${isFocused ? ` ${styles.cardFocused}` : \"\"}${disabled ? ` ${styles.cardDisabled}` : \"\"}`}\n style={{\n border: isFocused\n ? `1px solid ${tokens.colorNeutralStroke1}`\n : `1px solid ${tokens.colorNeutralStroke2}`,\n }}\n >\n {attachments.length > 0 && (\n <div className={styles.attachmentsRow}>\n {attachments.map((a) => {\n const ext = a.file.name.split(\".\").pop()?.toUpperCase() ?? \"FILE\";\n return (\n <div key={a.id} className={styles.attachmentItem}>\n {a.preview ? (\n <img\n src={a.preview}\n alt={a.file.name}\n className={styles.attachmentImage}\n />\n ) : (\n <div className={styles.attachmentFile}>\n <Body1 className={styles.attachmentFileName}>\n {a.file.name}\n </Body1>\n <Tag appearance=\"outline\" size=\"small\">\n {ext}\n </Tag>\n </div>\n )}\n <Button\n icon={<Dismiss />}\n size=\"small\"\n onClick={() => removeAttachment(a.id)}\n className={styles.attachmentDismiss}\n />\n </div>\n );\n })}\n </div>\n )}\n\n <textarea\n disabled={disabled}\n ref={textareaRef}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n onEnter?.();\n }\n }}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n placeholder={placeholder}\n rows={1}\n className={styles.textarea}\n />\n\n <div className={styles.toolbar}>\n <div className={styles.toolbarSide}>\n {allowedAttachments && allowedAttachments.length > 0 && (\n <ChatAttachButton types={allowedAttachments} />\n )}\n {actionsStart}\n </div>\n <div className={styles.toolbarSide}>\n {actionsEnd}\n {sendStopButton}\n </div>\n </div>\n\n <span\n className={`${styles.focusBar} ${isFocused ? styles.focusBarVisible : styles.focusBarHidden}`}\n />\n </div>\n </div>\n );\n },\n);\n\nexport default ChatInput;\n","import React, { useRef } from \"react\";\nimport {\n Button,\n Menu,\n MenuTrigger,\n MenuPopover,\n MenuList,\n MenuItem,\n} from \"@fluentui/react-components\";\nimport { Add, DocumentAdd, ImageAdd } from \"@coral-ai/bundleicons\";\nimport { useChatContext } from \"./Chat.Context\";\n\nexport type ChatAttachType = \"files\" | \"photos\";\n\nexport interface ChatAttachButtonProps {\n /**\n * Which entries to render in the `+` menu. Order in the array is the order\n * shown in the menu. Defaults to `['files', 'photos']`.\n */\n types?: ChatAttachType[];\n}\n\n/**\n * The \"+\" button rendered by default to the left of the chat input toolbar.\n *\n * Opens a Fluent menu with \"Add files\" / \"Add photos\" entries (subset\n * controlled by `types`). Selecting one opens the native OS file picker via a\n * hidden `<input type=\"file\">` and pushes the resulting `File[]` through\n * `addAttachments` on `useChatContext`. From there the existing chat pipeline\n * stages the files, renders preview tiles above the textarea, and hands the\n * raw `File[]` to the agent handler on send.\n *\n * Engineers don't typically render this directly — `<Chat allowedAttachments>`\n * does it for them. It's exported so the same component can be dropped into\n * `actionsStart` for fully custom layouts.\n */\nconst ChatAttachButton: React.FC<ChatAttachButtonProps> = ({\n types = [\"files\", \"photos\"],\n}) => {\n const { addAttachments } = useChatContext();\n const fileRef = useRef<HTMLInputElement>(null);\n const photoRef = useRef<HTMLInputElement>(null);\n\n const showFiles = types.includes(\"files\");\n const showPhotos = types.includes(\"photos\");\n\n return (\n <>\n {showFiles && (\n <input\n ref={fileRef}\n type=\"file\"\n hidden\n multiple\n onChange={(e) => {\n if (e.target.files) addAttachments([...e.target.files]);\n e.target.value = \"\";\n }}\n />\n )}\n {showPhotos && (\n <input\n ref={photoRef}\n type=\"file\"\n hidden\n multiple\n accept=\"image/*\"\n onChange={(e) => {\n if (e.target.files) addAttachments([...e.target.files]);\n e.target.value = \"\";\n }}\n />\n )}\n <Menu>\n <MenuTrigger>\n <Button appearance=\"subtle\" icon={<Add />} />\n </MenuTrigger>\n <MenuPopover>\n <MenuList>\n {types.map((t) =>\n t === \"files\" ? (\n <MenuItem\n key=\"files\"\n icon={<DocumentAdd />}\n onClick={() => fileRef.current?.click()}\n >\n Add files\n </MenuItem>\n ) : (\n <MenuItem\n key=\"photos\"\n icon={<ImageAdd />}\n onClick={() => photoRef.current?.click()}\n >\n Add photos\n </MenuItem>\n ),\n )}\n </MenuList>\n </MenuPopover>\n </Menu>\n </>\n );\n};\n\nexport default ChatAttachButton;\n","import React from \"react\";\nimport { Body1, Body1Strong, Body2, Button, Caption1, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { useChatContext } from \"./Chat.Context\";\nimport type { ApprovalOption, ChatApprovalRequest } from \"./Chat\";\n\nexport interface ChatApprovalProps {\n /**\n * Override the approval request to render. Defaults to `pendingApproval`\n * from context. Useful for storybook / standalone previews.\n */\n approval?: ChatApprovalRequest | null;\n /**\n * Override the resolver. Defaults to `resolveApproval` from context.\n */\n onSelect?: (optionId: string) => void;\n /** Disable all buttons. Defaults to false. */\n disabled?: boolean;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst useStyles = makeStyles({\n root: {\n width: \"100%\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"24px\",\n padding: \"12px 14px\",\n marginBottom: \"8px\",\n borderRadius: \"var(--borderRadiusXLarge)\",\n backgroundColor: \"var(--colorNeutralBackgroundAlpha2)\",\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n },\n header: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"2px\",\n },\n description: {\n color: tokens.colorNeutralForeground3,\n },\n optionsRow: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"6px\",\n\n },\n optionsColumn: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"6px\",\n\n },\n optionStacked: {\n justifyContent: \"flex-start\",\n },\n hint: {\n color: tokens.colorNeutralForeground3,\n // fontStyle: \"italic\",\n },\n});\n\nfunction shouldStackVertically(options: ApprovalOption[]): boolean {\n if (options.length > 3) return true;\n const totalLength = options.reduce((sum, o) => sum + o.label.length, 0);\n if (totalLength > 40) return true;\n if (options.some((o) => !!o.description)) return true;\n return false;\n}\n\nconst ChatApproval: React.FC<ChatApprovalProps> = ({\n approval: approvalProp,\n onSelect: onSelectProp,\n disabled = false,\n className,\n style,\n}) => {\n const styles = useStyles();\n const ctx = useChatContext();\n const approval = approvalProp ?? ctx.pendingApproval;\n if (!approval) return null;\n\n const onSelect = onSelectProp ?? ((optionId: string) => ctx.resolveApproval(approval.id, optionId));\n const answeredId = approval.answer?.optionId;\n const isAnswered = answeredId !== undefined;\n const awaitingFreeform =\n ctx.awaitingFreeformApproval?.approvalId === approval.id\n ? ctx.awaitingFreeformApproval\n : null;\n const stack = shouldStackVertically(approval.options);\n\n return (\n <div\n className={`${styles.root}${className ? ` ${className}` : \"\"}`}\n style={style}\n role=\"group\"\n aria-label={approval.question}\n >\n <div className={styles.header}>\n <Body1Strong>{approval.question}</Body1Strong>\n {approval.description && (\n <Body1 className={styles.description}>{approval.description}</Body1>\n )}\n </div>\n <div className={stack ? styles.optionsColumn : styles.optionsRow}>\n {approval.options.map((opt) => {\n const selected =\n answeredId === opt.id || awaitingFreeform?.optionId === opt.id;\n const baseAppearance = opt.appearance ?? (opt.freeform ? \"subtle\" : \"outline\");\n const appearance = selected ? \"primary\" : baseAppearance;\n return (\n <Button\n key={opt.id}\n appearance={appearance}\n disabled={disabled || isAnswered}\n onClick={() => onSelect(opt.id)}\n className={stack ? styles.optionStacked : undefined}\n style={{\n height:'40px'\n }}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n {awaitingFreeform && !isAnswered && (\n <Caption1 className={styles.hint}>\n Type your reply in the message box below.\n </Caption1>\n )}\n </div>\n );\n};\n\nexport default ChatApproval;\n","import type { AgentHandler, ChatChunk } from \"./Chat\";\nimport { fileToBase64 } from \"./fileToBase64\";\n\ntype CreateHandlerOptions = {\n /** Your backend endpoint. Receives POST { input, history, attachments }. */\n endpoint: string;\n /** Additional headers (e.g. Authorization). */\n headers?: HeadersInit;\n};\n\n/**\n * Wraps a fetch endpoint into an AgentHandler.\n *\n * On send it POSTs JSON to `endpoint`:\n *\n * ```json\n * {\n * \"input\": \"the user's latest message\",\n * \"history\": [{ \"role\": \"user\", \"content\": \"...\" }],\n * \"attachments\": [{ \"name\": \"cat.jpg\", \"mediaType\": \"image/jpeg\", \"data\": \"<base64>\" }]\n * }\n * ```\n *\n * Attached files are base64-encoded with `fileToBase64` (same encoding as\n * Coral's built-in `api` handler); `attachments` is `[]` when none are staged.\n *\n * The endpoint should stream newline-delimited responses where each line is either:\n * - A plain text chunk (yielded as a string)\n * - A JSON-encoded ChatChunk object (e.g. `{\"type\":\"reasoning\",\"content\":\"...\"}`)\n * - An SSE `data: ...` line (the `data: ` prefix is stripped automatically)\n * - `[DONE]` to signal end-of-stream\n *\n * @example\n * <Chat onSendMessage={createHandler({ endpoint: '/api/chat' })} />\n */\nexport function createHandler({ endpoint, headers }: CreateHandlerOptions): AgentHandler {\n return async function* (input, history, files) {\n const attachments = await Promise.all(\n files.map(async (file) => ({\n name: file.name,\n mediaType: file.type,\n data: await fileToBase64(file),\n })),\n );\n\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify({ input, history, attachments }),\n });\n\n if (!res.ok || !res.body) {\n throw Object.assign(new Error(`${res.status} ${res.statusText}`), {\n status: res.status,\n statusText: res.statusText,\n });\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\"; // keep any incomplete final line\n\n for (const line of lines) {\n // Strip SSE prefix\n const text = line.startsWith(\"data: \") ? line.slice(6) : line;\n if (!text || text === \"[DONE]\") continue;\n\n try {\n const chunk = JSON.parse(text) as ChatChunk;\n yield chunk;\n } catch {\n // Plain text line\n yield text;\n }\n }\n }\n };\n}\n","import type { CoralChartSpec } from \"@coral-ai/charts\";\nimport type {\n AgentHandler,\n ChatChunk,\n ChatMessage,\n ChatTodo,\n ChatApprovalRequest,\n ApprovalOption,\n} from \"./Chat\";\n\n/**\n * Model-agnostic agent tool-use runner.\n *\n * `createAgentHandler` turns a provider-neutral `callModel` adapter into a\n * Coral `AgentHandler`. Coral owns the tool-use loop, the built-in\n * `update_todos` / `request_approval` tools, and the approval pause/resume\n * bridge. The engineer owns exactly one function — `callModel` — which is the\n * only provider-specific code (Claude, Azure OpenAI, …).\n */\n\n// ---- Neutral types ----------------------------------------------------------\n\n/** A tool definition. `parameters` is standard JSON Schema for the tool input. */\nexport type ToolSpec = {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n};\n\n/** A tool invocation emitted by the model. */\nexport type ToolCall = { id: string; name: string; input: unknown };\n\n/**\n * One message in the neutral agent conversation. `raw` on assistant messages\n * is an opaque passthrough for provider-native content blocks (e.g. Claude\n * `thinking` + `tool_use` blocks that must replay verbatim across the loop) —\n * the runner never inspects it; the adapter prefers it when rebuilding.\n */\nexport type AgentMessage =\n | { role: \"user\"; content: string }\n | { role: \"assistant\"; content: string; toolCalls?: ToolCall[]; raw?: unknown }\n | { role: \"tool\"; toolCallId: string; content: string };\n\n/** What the runner hands the `callModel` adapter for each model call. */\nexport type ModelRequest = {\n system?: string;\n messages: AgentMessage[];\n tools: ToolSpec[];\n /** Present only on the first model call of a turn. */\n attachments?: File[];\n};\n\n/** A streamed event from the `callModel` adapter. */\nexport type ModelStreamEvent =\n | { type: \"text\"; delta: string }\n | { type: \"reasoning\"; delta: string }\n | { type: \"tool_call\"; toolCall: ToolCall }\n /** Opaque provider-native representation of the assistant turn, for replay. */\n | { type: \"raw\"; raw: unknown };\n\n/** The one function an engineer implements per provider. */\nexport type CallModel = (req: ModelRequest) => AsyncIterable<ModelStreamEvent>;\n\n/** Result of executing a custom tool — fed back to the model. */\nexport type ToolResult = { content: string };\n\n/** A custom tool the engineer registers alongside the built-ins. */\nexport type AgentTool = {\n spec: ToolSpec;\n execute: (input: unknown) => ToolResult | Promise<ToolResult>;\n};\n\n/** Paused-agent state, stashed while waiting for an approval answer. */\nexport type AgentSnapshot = {\n messages: AgentMessage[];\n pendingToolCallId: string;\n};\n\n/**\n * Where paused agent state is stored between the approval request and the\n * user's answer. Defaults to an in-memory Map — for a server handler that\n * spans processes, supply a Redis/db-backed implementation.\n */\nexport type AgentSessionStore = {\n get(id: string): AgentSnapshot | undefined | Promise<AgentSnapshot | undefined>;\n set(id: string, snap: AgentSnapshot): void | Promise<void>;\n delete(id: string): void | Promise<void>;\n};\n\n// ---- Built-in tool specs ----------------------------------------------------\n\n/** Built-in tool: render / update the inline task checklist. */\nexport const UPDATE_TODOS_TOOL: ToolSpec = {\n name: \"update_todos\",\n description:\n \"Display or update the multi-step task plan shown to the user as an inline \" +\n \"checklist. Call this when you begin a task that takes 3 or more distinct \" +\n \"steps, and again every time a step changes status. Always send the COMPLETE \" +\n \"list of todos — it replaces the previous one. Keep exactly one item \" +\n \"'in_progress' at a time.\",\n parameters: {\n type: \"object\",\n properties: {\n todos: {\n type: \"array\",\n description: \"The full task list, in order.\",\n items: {\n type: \"object\",\n properties: {\n content: {\n type: \"string\",\n description: \"Imperative title, e.g. 'Optimize images'.\",\n },\n activeForm: {\n type: \"string\",\n description:\n \"Present-tense title shown while this step is in progress, \" +\n \"e.g. 'Optimizing images'.\",\n },\n status: {\n type: \"string\",\n enum: [\"pending\", \"in_progress\", \"completed\"],\n },\n },\n required: [\"content\", \"status\"],\n },\n },\n },\n required: [\"todos\"],\n },\n};\n\n/** Built-in tool: pause and ask the user to approve / choose before continuing. */\nexport const REQUEST_APPROVAL_TOOL: ToolSpec = {\n name: \"request_approval\",\n description:\n \"Pause and ask the user to approve an action or choose between options \" +\n \"before continuing. The conversation halts until the user responds — their \" +\n \"choice comes back as this tool's result. Use this before any consequential \" +\n \"or irreversible action (deleting, sending, purchasing, etc).\",\n parameters: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question or action to confirm.\",\n },\n description: {\n type: \"string\",\n description: \"Optional extra context shown below the question.\",\n },\n options: {\n type: \"array\",\n description: \"The choices offered to the user.\",\n items: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n label: { type: \"string\" },\n description: { type: \"string\" },\n freeform: {\n type: \"boolean\",\n description:\n \"If true, choosing this option lets the user type a free-text \" +\n \"reply instead of a canned choice.\",\n },\n },\n required: [\"id\", \"label\"],\n },\n },\n },\n required: [\"question\", \"options\"],\n },\n};\n\n/** Built-in tool: render a chart inline as part of the assistant message. */\nexport const RENDER_CHART_TOOL: ToolSpec = {\n name: \"render_chart\",\n description:\n \"Render a chart inline in the assistant message. Call this when a \" +\n \"visualization (bar or line) communicates the data more clearly than \" +\n \"prose or a table. The chart appears above your text — refer to it \" +\n \"naturally (\\\"as the chart above shows…\\\") and do NOT also produce ASCII \" +\n \"charts or code blocks for the same data. May be called multiple times \" +\n \"in a turn to render multiple charts.\",\n parameters: {\n type: \"object\",\n properties: {\n kind: {\n type: \"string\",\n enum: [\"bar\", \"line\"],\n description: \"Use 'bar' for categorical comparisons, 'line' for trends over an ordered axis.\",\n },\n title: { type: \"string\", description: \"Title shown above the chart.\" },\n xKey: {\n type: \"string\",\n description: \"Key in each `data` row that supplies the x-axis label.\",\n },\n series: {\n type: \"array\",\n description: \"One entry per data series (one bar group / one line).\",\n items: {\n type: \"object\",\n properties: {\n dataKey: {\n type: \"string\",\n description: \"Key in each `data` row holding this series' numeric value.\",\n },\n label: {\n type: \"string\",\n description: \"Display label shown in the legend and tooltip.\",\n },\n },\n required: [\"dataKey\", \"label\"],\n },\n },\n data: {\n type: \"array\",\n description:\n \"Rows of data containing the xKey and every series' dataKey. \" +\n \"Example: `[{ quarter: 'Q1', alice: 92, bob: 78 }, …]`.\",\n items: { type: \"object\" },\n },\n },\n required: [\"kind\", \"title\", \"xKey\", \"series\", \"data\"],\n },\n};\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction createMemoryStore(): AgentSessionStore {\n const map = new Map<string, AgentSnapshot>();\n return {\n get: (id) => map.get(id),\n set: (id, snap) => {\n map.set(id, snap);\n },\n delete: (id) => {\n map.delete(id);\n },\n };\n}\n\n/** Coral message history → neutral agent messages (system messages dropped). */\nfunction historyToAgentMessages(history: ChatMessage[]): AgentMessage[] {\n const out: AgentMessage[] = [];\n for (const m of history) {\n if (m.role === \"user\") out.push({ role: \"user\", content: m.content });\n else if (m.role === \"assistant\") out.push({ role: \"assistant\", content: m.content });\n }\n return out;\n}\n\n/** Coerce a model-supplied `update_todos` input into ChatTodo[]. */\nfunction extractTodos(input: unknown): ChatTodo[] {\n const todos = (input as { todos?: unknown } | null)?.todos;\n if (!Array.isArray(todos)) return [];\n return todos.map((t, i): ChatTodo => {\n const o = (t ?? {}) as Record<string, unknown>;\n return {\n id: typeof o.id === \"string\" ? o.id : `todo-${i}`,\n content: String(o.content ?? \"\"),\n activeForm: typeof o.activeForm === \"string\" ? o.activeForm : undefined,\n status:\n o.status === \"in_progress\" || o.status === \"completed\"\n ? o.status\n : \"pending\",\n };\n });\n}\n\n/** Coerce a model-supplied `render_chart` input into a CoralChartSpec. */\nfunction buildChartSpec(input: unknown): CoralChartSpec | null {\n const o = (input ?? {}) as Record<string, unknown>;\n const kind = o.kind === \"line\" ? \"line\" : \"bar\";\n const title = typeof o.title === \"string\" ? o.title : \"\";\n const xKey = typeof o.xKey === \"string\" ? o.xKey : \"\";\n const rawSeries = Array.isArray(o.series) ? o.series : [];\n const series = rawSeries\n .map((s, i) => {\n const obj = (s ?? {}) as Record<string, unknown>;\n const dataKey = typeof obj.dataKey === \"string\" ? obj.dataKey : \"\";\n const label = typeof obj.label === \"string\" ? obj.label : dataKey || `series-${i}`;\n return dataKey ? { dataKey, label } : null;\n })\n .filter((s): s is { dataKey: string; label: string } => s !== null);\n const data = Array.isArray(o.data)\n ? (o.data.filter(\n (r) => r && typeof r === \"object\",\n ) as Array<Record<string, string | number>>)\n : [];\n if (!xKey || series.length === 0 || data.length === 0) return null;\n return { kind, title, xKey, series, data };\n}\n\n/** Coerce a model-supplied `request_approval` input into a ChatApprovalRequest. */\nfunction buildApproval(tc: ToolCall): ChatApprovalRequest {\n const input = (tc.input ?? {}) as Record<string, unknown>;\n const rawOptions = Array.isArray(input.options) ? input.options : [];\n const options: ApprovalOption[] = rawOptions.map((o, i) => {\n const obj = (o ?? {}) as Record<string, unknown>;\n return {\n id: typeof obj.id === \"string\" ? obj.id : `opt-${i}`,\n label: String(obj.label ?? `Option ${i + 1}`),\n description: typeof obj.description === \"string\" ? obj.description : undefined,\n freeform: obj.freeform === true ? true : undefined,\n };\n });\n return {\n // The tool-call id is the approval id — Coral round-trips it as\n // metadata.approvalId, which is the session-store key on resume.\n id: tc.id,\n question: String(input.question ?? \"Approve?\"),\n description:\n typeof input.description === \"string\" ? input.description : undefined,\n options,\n };\n}\n\n// ---- The runner -------------------------------------------------------------\n\nexport type CreateAgentHandlerOptions = {\n /** Provider adapter — the only provider-specific code. */\n callModel: CallModel;\n /** Base system prompt. Merged with any `systemPrompt` Coral injects. */\n system?: string;\n /** Custom tools, registered alongside the built-in update_todos / request_approval. */\n tools?: AgentTool[];\n /** Max tool-loop iterations per turn. Default 8. */\n maxSteps?: number;\n /** Where paused-agent state lives. Default: in-memory Map. */\n sessionStore?: AgentSessionStore;\n};\n\n/**\n * Builds a Coral `AgentHandler` that runs a provider-agnostic tool-use loop.\n *\n * @example\n * <Chat onSendMessage={createAgentHandler({ callModel: claudeCallModel })} />\n */\nexport function createAgentHandler(options: CreateAgentHandlerOptions): AgentHandler {\n const { callModel, system, tools = [], maxSteps = 8 } = options;\n const store = options.sessionStore ?? createMemoryStore();\n const customByName = new Map(tools.map((t) => [t.spec.name, t]));\n const toolSpecs: ToolSpec[] = [\n UPDATE_TODOS_TOOL,\n REQUEST_APPROVAL_TOOL,\n RENDER_CHART_TOOL,\n ...tools.map((t) => t.spec),\n ];\n\n return async function* (\n _input: string,\n history: ChatMessage[],\n attachments: File[],\n ): AsyncGenerator<ChatChunk> {\n const sysFromHistory = history\n .filter((m) => m.role === \"system\")\n .map((m) => m.content);\n const effectiveSystem =\n [system, ...sysFromHistory].filter(Boolean).join(\"\\n\\n\") || undefined;\n\n // --- A. Resume an approval, or start a fresh turn ---\n const last = history[history.length - 1];\n let messages: AgentMessage[];\n let firstCallAttachments: File[] | undefined;\n\n const resumeId =\n last?.role === \"user\" &&\n last.type === \"approval_response\" &&\n typeof last.metadata?.approvalId === \"string\"\n ? (last.metadata.approvalId as string)\n : undefined;\n const snapshot = resumeId ? await store.get(resumeId) : undefined;\n\n if (resumeId && snapshot) {\n await store.delete(resumeId);\n const meta = last!.metadata as Record<string, unknown>;\n const answer =\n (typeof meta.text === \"string\" && meta.text) ||\n (typeof meta.label === \"string\" && meta.label) ||\n last!.content;\n messages = [\n ...snapshot.messages,\n {\n role: \"tool\",\n toolCallId: snapshot.pendingToolCallId,\n content: `The user chose: ${answer}`,\n },\n ];\n } else {\n // Coral appends the new user message to history before calling the\n // handler, so converting history is enough — don't re-append `input`.\n messages = historyToAgentMessages(history);\n firstCallAttachments = attachments.length > 0 ? attachments : undefined;\n }\n\n // --- B. Tool-use loop ---\n for (let step = 0; step < maxSteps; step++) {\n const events = callModel({\n system: effectiveSystem,\n messages,\n tools: toolSpecs,\n attachments: step === 0 ? firstCallAttachments : undefined,\n });\n\n let assistantText = \"\";\n let assistantRaw: unknown;\n const toolCalls: ToolCall[] = [];\n\n for await (const ev of events) {\n if (ev.type === \"text\") {\n assistantText += ev.delta;\n yield ev.delta;\n } else if (ev.type === \"reasoning\") {\n yield { type: \"reasoning\", content: ev.delta };\n } else if (ev.type === \"tool_call\") {\n toolCalls.push(ev.toolCall);\n } else if (ev.type === \"raw\") {\n assistantRaw = ev.raw;\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: assistantText,\n ...(toolCalls.length > 0 ? { toolCalls } : {}),\n ...(assistantRaw !== undefined ? { raw: assistantRaw } : {}),\n });\n\n // No tool calls — the model gave its final answer.\n if (toolCalls.length === 0) return;\n\n for (const tc of toolCalls) {\n if (tc.name === UPDATE_TODOS_TOOL.name) {\n yield { type: \"todos\", todos: extractTodos(tc.input) };\n messages.push({\n role: \"tool\",\n toolCallId: tc.id,\n content: \"Task list updated and shown to the user.\",\n });\n } else if (tc.name === REQUEST_APPROVAL_TOOL.name) {\n yield { type: \"approval\", approval: buildApproval(tc) };\n // Pause: stash state keyed by the tool-call id and end the turn.\n // It resumes when the user answers (see the resume branch above).\n await store.set(tc.id, { messages, pendingToolCallId: tc.id });\n return;\n } else if (tc.name === RENDER_CHART_TOOL.name) {\n const spec = buildChartSpec(tc.input);\n if (spec) {\n yield { type: \"chart\", spec };\n messages.push({\n role: \"tool\",\n toolCallId: tc.id,\n content: \"Chart rendered and shown to the user above your text.\",\n });\n } else {\n messages.push({\n role: \"tool\",\n toolCallId: tc.id,\n content:\n \"Error: chart spec was invalid. Need non-empty `xKey`, \" +\n \"at least one entry in `series`, and at least one row in `data`.\",\n });\n }\n } else {\n const tool = customByName.get(tc.name);\n let content: string;\n if (!tool) {\n content = `Error: unknown tool \"${tc.name}\".`;\n } else {\n try {\n content = (await tool.execute(tc.input)).content;\n } catch (err) {\n content = `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n messages.push({ role: \"tool\", toolCallId: tc.id, content });\n }\n }\n }\n\n yield \"\\n\\n_(Reached the tool-step limit for this turn.)_\";\n };\n}\n","import * as React from \"react\";\nimport type { ChatMessage } from \"./Chat\";\n\n/**\n * A stored conversation. Consumers typically persist this shape via the\n * adapter they pass to `ChatThreadsProvider`.\n */\nexport interface ChatThread {\n id: string;\n title: string;\n messages: ChatMessage[];\n createdAt?: number;\n updatedAt?: number;\n}\n\n/**\n * Storage seam. Implement this against your backend (REST, IndexedDB,\n * Firestore, etc.). The provider handles in-memory state so UI updates are\n * synchronous; your adapter only needs to persist.\n */\nexport interface ChatThreadsAdapter {\n list(): Promise<ChatThread[]> | ChatThread[];\n get?(id: string): Promise<ChatThread | undefined> | ChatThread | undefined;\n create(initial?: Partial<ChatThread>): Promise<ChatThread> | ChatThread;\n save(thread: ChatThread): Promise<void> | void;\n rename(id: string, newTitle: string): Promise<void> | void;\n remove(id: string): Promise<void> | void;\n}\n\nexport interface ChatThreadsContextValue {\n threads: ChatThread[];\n activeThreadId?: string;\n activeThread?: ChatThread;\n setActiveThreadId: (id: string | undefined) => void;\n createThread: (initial?: Partial<ChatThread>) => Promise<ChatThread>;\n renameThread: (id: string, newTitle: string) => Promise<void>;\n removeThread: (id: string) => Promise<void>;\n updateThreadMessages: (id: string, messages: ChatMessage[]) => void;\n isLoading: boolean;\n}\n\nconst ChatThreadsContext = React.createContext<ChatThreadsContextValue | null>(\n null,\n);\n\nexport function useChatThreads(): ChatThreadsContextValue {\n const value = React.useContext(ChatThreadsContext);\n if (!value) {\n throw new Error(\n \"useChatThreads must be used inside <ChatThreadsProvider>.\",\n );\n }\n return value;\n}\n\n/** Default adapter — holds threads in a module-less closure. Use for demos or unit tests. */\nexport function createMemoryThreadsAdapter(\n initialThreads: ChatThread[] = [],\n): ChatThreadsAdapter {\n let threads: ChatThread[] = [...initialThreads];\n return {\n list: () => threads,\n get: (id) => threads.find((t) => t.id === id),\n create: (initial) => {\n const thread: ChatThread = {\n id: initial?.id ?? crypto.randomUUID(),\n title: initial?.title ?? \"New chat\",\n messages: initial?.messages ?? [],\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n threads = [thread, ...threads];\n return thread;\n },\n save: (thread) => {\n const idx = threads.findIndex((t) => t.id === thread.id);\n const next: ChatThread = { ...thread, updatedAt: Date.now() };\n threads = idx >= 0\n ? threads.map((t, i) => (i === idx ? next : t))\n : [next, ...threads];\n },\n rename: (id, newTitle) => {\n threads = threads.map((t) =>\n t.id === id ? { ...t, title: newTitle, updatedAt: Date.now() } : t,\n );\n },\n remove: (id) => {\n threads = threads.filter((t) => t.id !== id);\n },\n };\n}\n\nexport interface ChatThreadsProviderProps {\n /** Storage adapter. Defaults to an in-memory adapter if omitted. */\n adapter?: ChatThreadsAdapter;\n /** Controlled active thread id. */\n activeThreadId?: string;\n /** Uncontrolled initial active thread id. */\n defaultActiveThreadId?: string;\n /** Fired when the active thread changes (both controlled and uncontrolled). */\n onActiveThreadChange?: (id: string | undefined) => void;\n children?: React.ReactNode;\n}\n\nexport function ChatThreadsProvider({\n adapter: providedAdapter,\n activeThreadId: controlledId,\n defaultActiveThreadId,\n onActiveThreadChange,\n children,\n}: ChatThreadsProviderProps) {\n const adapter = React.useMemo(\n () => providedAdapter ?? createMemoryThreadsAdapter(),\n [providedAdapter],\n );\n\n const [threads, setThreads] = React.useState<ChatThread[]>([]);\n const [uncontrolledId, setUncontrolledId] = React.useState<string | undefined>(\n defaultActiveThreadId,\n );\n const [isLoading, setIsLoading] = React.useState(true);\n\n const isControlled = controlledId !== undefined;\n const activeThreadId = isControlled ? controlledId : uncontrolledId;\n\n const setActiveThreadId = React.useCallback(\n (id: string | undefined) => {\n if (!isControlled) setUncontrolledId(id);\n onActiveThreadChange?.(id);\n },\n [isControlled, onActiveThreadChange],\n );\n\n React.useEffect(() => {\n let cancelled = false;\n (async () => {\n setIsLoading(true);\n const result = await adapter.list();\n if (cancelled) return;\n setThreads(result);\n setIsLoading(false);\n })();\n return () => {\n cancelled = true;\n };\n }, [adapter]);\n\n const createThread = React.useCallback(\n async (initial?: Partial<ChatThread>) => {\n const thread = await adapter.create(initial);\n setThreads((prev) => [thread, ...prev.filter((t) => t.id !== thread.id)]);\n return thread;\n },\n [adapter],\n );\n\n const renameThread = React.useCallback(\n async (id: string, newTitle: string) => {\n await adapter.rename(id, newTitle);\n setThreads((prev) =>\n prev.map((t) =>\n t.id === id ? { ...t, title: newTitle, updatedAt: Date.now() } : t,\n ),\n );\n },\n [adapter],\n );\n\n const removeThread = React.useCallback(\n async (id: string) => {\n await adapter.remove(id);\n setThreads((prev) => prev.filter((t) => t.id !== id));\n if (activeThreadId === id) setActiveThreadId(undefined);\n },\n [adapter, activeThreadId, setActiveThreadId],\n );\n\n const threadsRef = React.useRef(threads);\n threadsRef.current = threads;\n\n const updateThreadMessages = React.useCallback(\n (id: string, messages: ChatMessage[]) => {\n const existing = threadsRef.current.find((t) => t.id === id);\n if (!existing) return;\n const next: ChatThread = {\n ...existing,\n messages,\n updatedAt: Date.now(),\n };\n setThreads((prev) => prev.map((t) => (t.id === id ? next : t)));\n void adapter.save(next);\n },\n [adapter],\n );\n\n const activeThread = React.useMemo(\n () => threads.find((t) => t.id === activeThreadId),\n [threads, activeThreadId],\n );\n\n const value = React.useMemo<ChatThreadsContextValue>(\n () => ({\n threads,\n activeThreadId,\n activeThread,\n setActiveThreadId,\n createThread,\n renameThread,\n removeThread,\n updateThreadMessages,\n isLoading,\n }),\n [\n threads,\n activeThreadId,\n activeThread,\n setActiveThreadId,\n createThread,\n renameThread,\n removeThread,\n updateThreadMessages,\n isLoading,\n ],\n );\n\n return (\n <ChatThreadsContext.Provider value={value}>\n {children}\n </ChatThreadsContext.Provider>\n );\n}\n","import _ChatRoot from \"./Chat\";\nimport _ChatCanvas from \"./Chat.Canvas\";\nimport _ChatMessages from \"./Chat.Messages\";\nimport _ChatInput from \"./Chat.Input\";\nimport _ChatError, { normalizeChatError as _normalizeChatError } from \"./Chat.Error\";\nimport _ChatCallout from \"./Chat.Callout\";\nimport _ChatApproval from \"./Chat.Approval\";\nimport _ChatTodoList from \"./Chat.TodoList\";\nimport _ChatAttachButton from \"./Chat.AttachButton\";\nimport _ChatThinkingIndicator from \"./Chat.ThinkingIndicator\";\nimport { createHandler as _createHandler } from \"./createHandler\";\n\nexport const Chat: typeof _ChatRoot & {\n Canvas: typeof _ChatCanvas;\n Messages: typeof _ChatMessages;\n Input: typeof _ChatInput;\n Error: typeof _ChatError;\n Callout: typeof _ChatCallout;\n Approval: typeof _ChatApproval;\n TodoList: typeof _ChatTodoList;\n AttachButton: typeof _ChatAttachButton;\n ThinkingIndicator: typeof _ChatThinkingIndicator;\n} = Object.assign(_ChatRoot, {\n Canvas: _ChatCanvas,\n Messages: _ChatMessages,\n Input: _ChatInput,\n Error: _ChatError,\n Callout: _ChatCallout,\n Approval: _ChatApproval,\n TodoList: _ChatTodoList,\n AttachButton: _ChatAttachButton,\n ThinkingIndicator: _ChatThinkingIndicator,\n});\n\nexport const normalizeChatError = _normalizeChatError;\nexport const createHandler = _createHandler;\n\nexport {\n createAgentHandler,\n UPDATE_TODOS_TOOL,\n REQUEST_APPROVAL_TOOL,\n RENDER_CHART_TOOL,\n} from \"./Chat.Agent\";\nexport type {\n CallModel,\n ModelRequest,\n ModelStreamEvent,\n AgentMessage,\n ToolCall,\n ToolSpec,\n AgentTool,\n ToolResult,\n AgentSnapshot,\n AgentSessionStore,\n CreateAgentHandlerOptions,\n} from \"./Chat.Agent\";\n\nexport { useChatContext } from \"./Chat.Context\";\nexport { fileToBase64 } from \"./fileToBase64\";\nexport {\n DEFAULT_TASK_MESSAGES,\n resolveTaskMessages,\n} from \"./Chat.TaskMessages\";\n\nexport {\n ChatThreadsProvider,\n useChatThreads,\n createMemoryThreadsAdapter,\n} from \"./Chat.Threads\";\nexport type {\n ChatThread,\n ChatThreadsAdapter,\n ChatThreadsContextValue,\n ChatThreadsProviderProps,\n} from \"./Chat.Threads\";\n\nexport type {\n ChatMessage,\n ChatChunk,\n ChatResponse,\n AgentHandler,\n ChatAttachment,\n ChatMessageRendererProps,\n ChatComponents,\n ApprovalOption,\n ChatApprovalRequest,\n ChatTodo,\n} from \"./Chat\";\nexport type { ChatApprovalProps } from \"./Chat.Approval\";\nexport type { ChatTodoListProps } from \"./Chat.TodoList\";\nexport type { ChatCanvasProps } from \"./Chat.Canvas\";\nexport type { ChatMessagesProps } from \"./Chat.Messages\";\nexport type { ChatInputProps } from \"./Chat.Input\";\nexport type { ChatErrorProps, NormalizedChatError, ErrorCategory } from \"./Chat.Error\";\nexport type { ChatAttachButtonProps, ChatAttachType } from \"./Chat.AttachButton\";\nexport type { CoralTaskType } from \"./Chat.TaskMessages\";\n"],"mappings":"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","names":["useLayoutEffect","useRef","useState","Caption1","makeStyles","Button","makeStyles","tokens","jsx","jsxs","useStyles","makeStyles","tokens","input","attachments","Button","React","useEffect","useLayoutEffect","useRef","useState","Body1","Button","Caption1","makeStyles","tokens","useState","useEffect","useRef","makeStyles","tokens","jsx","jsxs","useStyles","Body1","Button","makeStyles","tokens","jsx","jsxs","useStyles","useState","useEffect","useRef","Body1","makeStyles","tokens","jsx","jsxs","useStyles","useState","Body1","makeStyles","tokens","jsx","jsxs","useStyles","jsx","jsxs","useStyles","makeStyles","tokens","useRef","useState","useLayoutEffect","useEffect","Caption1","Button","Body1","React","useRef","useState","useEffect","Body1","Button","makeStyles","tokens","useRef","Button","Fragment","jsx","jsxs","useRef","Button","jsx","jsxs","useStyles","makeStyles","tokens","useState","useRef","useEffect","Button","Body1","Body1","Button","Caption1","makeStyles","tokens","jsx","jsxs","useStyles","makeStyles","tokens","Body1","Button","Caption1","Fragment","jsx","jsxs","useStyles","makeStyles","useRef","useState","useLayoutEffect","Caption1","React","jsx","Chat","normalizeChatError","createHandler"]}
|
|
1
|
+
{"version":3,"sources":["../src/Chat.tsx","../src/Chat.Canvas.tsx","../src/Chat.Context.tsx","../src/Chat.Error.tsx","../src/fileToBase64.ts","../src/Chat.Messages.tsx","../src/Chat.ThinkingIndicator.tsx","../src/Chat.TaskMessages.ts","../src/Chat.Callout.tsx","../src/Chat.ReasoningBlock.tsx","../src/Chat.TodoList.tsx","../src/Chat.Input.tsx","../src/Chat.AttachButton.tsx","../src/Chat.Approval.tsx","../src/createHandler.ts","../src/Chat.Agent.ts","../src/Chat.Threads.tsx","../src/index.ts"],"sourcesContent":["import React, { useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Caption1,\n Title3,\n makeStyles,\n motionTokens,\n} from \"@fluentui/react-components\";\nimport type { ChatFontSize, ChatFontFamily } from \"@coral-ai/markdown\";\nimport { useCoralConfig } from \"@coral-ai/react\";\nimport type { CoralChartSpec } from \"@coral-ai/charts\";\nimport type { NormalizedChatError } from \"./Chat.Error\";\nimport ChatCanvas from \"./Chat.Canvas\";\nimport ChatMessages from \"./Chat.Messages\";\nimport ChatInput from \"./Chat.Input\";\nimport ChatApproval from \"./Chat.Approval\";\nimport { useChatContext } from \"./Chat.Context\";\n\n// ---- Types (re-exported for consumers) ----\n\nexport type ChatMessage = {\n /** Stable identifier — generated automatically by Chat.Canvas. Used as React key. */\n id?: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n /** Identifies the message type for custom renderer lookup via the `components` prop. */\n type?: string;\n /** Arbitrary data passed to the custom renderer for this message. */\n metadata?: Record<string, unknown>;\n /**\n * If present, this assistant message carries a structured approval request.\n * Rendered above Chat.Input as a pinned selector while `answer` is undefined;\n * once answered, it stays in history with `answer` populated for replay.\n */\n approval?: ChatApprovalRequest;\n /**\n * If present, this assistant message carries a multi-step task plan.\n * Legacy field — new messages use `blocks` to position the todo list\n * inline at the stream point where it first appeared. Still read by the\n * renderer as a fallback for persisted messages saved before blocks.\n */\n todos?: ChatTodo[];\n /**\n * If present, this assistant message carries one or more chart specs.\n * Legacy field — new messages use `blocks` to position each chart at\n * the stream point where it was emitted. Still read by the renderer\n * as a fallback for persisted messages saved before blocks.\n */\n charts?: CoralChartSpec[];\n /**\n * Ordered list of inline blocks (text, charts, todos) in the order the\n * agent emitted them. Renderers iterate this in stream order so a chart\n * tool call appears at the exact point in the prose where it happened,\n * matching the convention used by Claude.ai and ChatGPT.\n *\n * When absent, the renderer synthesizes blocks from the legacy\n * `content` / `charts` / `todos` fields so old persisted conversations\n * still display correctly.\n */\n blocks?: ChatBlock[];\n /**\n * If present, the turn that produced this assistant message failed. The\n * message renders as an error card (with a Retry button) instead of normal\n * content. Persisted with the conversation so the error survives reloads.\n */\n error?: NormalizedChatError;\n};\n\n/**\n * One option in a human-in-the-loop approval / multiple-choice prompt.\n * Boolean approval is just two options; N-choice is the same shape with N options.\n */\nexport type ApprovalOption = {\n id: string;\n label: string;\n description?: string;\n appearance?: \"primary\" | \"subtle\" | \"outline\" | \"secondary\";\n /**\n * When true, selecting this option does NOT immediately resolve the approval.\n * The chat input is unlocked so the user can type a free-text reply, which is\n * then sent as the resolution payload (carrying this option's id alongside the text).\n * Convention: a final \"Other / something else\" choice.\n */\n freeform?: boolean;\n};\n\n/** Structured approval request attached to an assistant message. */\nexport type ChatApprovalRequest = {\n /** Stable id used to match the eventual response. */\n id: string;\n question: string;\n description?: string;\n options: ApprovalOption[];\n /**\n * Once the user responds, this is populated and the buttons render in their\n * \"answered\" terminal state. Distinct from `freeform` so freeform replies\n * still record which option was the escape hatch.\n */\n answer?: { optionId: string; text?: string };\n};\n\n/**\n * One inline block within an assistant message. Blocks are rendered in the\n * order the agent emitted them, so charts and todo lists appear at the exact\n * stream position where they happened (e.g. text → chart → text), rather than\n * being pinned above the message.\n */\nexport type ChatBlock =\n | { type: \"text\"; content: string }\n | { type: \"chart\"; spec: CoralChartSpec }\n | { type: \"todos\"; todos: ChatTodo[] };\n\n/**\n * One step in a multi-step task plan. The agent emits the whole list on each\n * update; the convention is exactly one item `in_progress` at a time.\n */\nexport type ChatTodo = {\n /** Stable id for React key + diffing. Optional; index used as fallback. */\n id?: string;\n /** Imperative title shown when pending/completed, e.g. \"Optimize images\". */\n content: string;\n /** Present-tense title shown while in_progress, e.g. \"Optimizing images\". */\n activeForm?: string;\n status: \"pending\" | \"in_progress\" | \"completed\";\n};\n\n/** A single chunk yielded by a streaming onSendMessage. */\nexport type ChatChunk =\n | string\n | { type: \"reasoning\"; content: string }\n /** Sets the thinking-indicator word pool while the handler works. */\n | { type: \"status\"; name: string }\n | { type: \"approval\"; approval: ChatApprovalRequest }\n | { type: \"todos\"; todos: ChatTodo[] }\n /** Appends a chart spec to the current assistant message; renders inline. */\n | { type: \"chart\"; spec: CoralChartSpec };\n\nexport type ChatResponse =\n | string\n | AsyncIterable<ChatChunk>\n | {\n content: string;\n type?: string;\n metadata?: Record<string, unknown>;\n todos?: ChatTodo[];\n };\n\n/** The typed handler signature engineers implement. */\nexport type ChatAttachment = {\n id: string;\n file: File;\n /** Data URL — populated for image/* files only. */\n preview?: string;\n};\n\nexport type AgentHandler = (\n input: string,\n history: ChatMessage[],\n attachments: File[],\n) => ChatResponse | Promise<ChatResponse>;\n\n/** Props passed to a custom message renderer. */\nexport type ChatMessageRendererProps = {\n message: ChatMessage;\n /** Sends a message back into the chat as the user. */\n onReply: (content: string) => void;\n};\n\nexport type ChatComponents = Record<string, React.FC<ChatMessageRendererProps>>;\n\n// ---- Props ----\n\ninterface ChatProps {\n /**\n * Backend URL. Coral POSTs `{ text, history, attachments }` here on send and\n * adapts the response to the existing chat pipeline. Used only when no\n * `onSendMessage` is provided. Falls back to `useCoralConfig().chat.api`\n * when omitted.\n */\n api?: string;\n /**\n * Which entries to render in the chat input's `+` menu. Falls back to\n * `useCoralConfig().chat.attachments` when omitted.\n */\n allowedAttachments?: Array<\"files\" | \"photos\">;\n conversationId?: string;\n initialMessages?: ChatMessage[];\n systemPrompt?: string;\n onSendMessage?: AgentHandler;\n onMessageComplete?: (\n messages: ChatMessage[],\n conversationId?: string,\n ) => void;\n /** Fires on every message-state update (user append, streaming chunk, final). Use for live persistence. */\n onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;\n onError?: (err: unknown) => void;\n autoSendMessage?: string;\n onCopy?: (content: string) => void;\n onNavigate?: (path: string) => void;\n components?: ChatComponents;\n thinkingStatus?: string;\n onStop?: () => void;\n /** Placeholder text for the chat input. @default \"Type a message...\" */\n placeholder?: string;\n /** Disables the entire input. */\n disabled?: boolean;\n /** Slot rendered at the left of the input toolbar. */\n actionsStart?: React.ReactNode;\n /** Slot rendered at the right of the input toolbar, just before Send/Stop. */\n actionsEnd?: React.ReactNode;\n /**\n * Shown above the input while messages is empty.\n * - Pass a `string` to render it as a `Title3` heading that hugs its content.\n * - Pass any other `ReactNode` to flex-fill the available height (centered).\n */\n welcomeMessage?: string | React.ReactNode;\n /**\n * Slot rendered horizontally centered directly under `Chat.Input`, while\n * the chat is empty (no user/assistant messages yet). Typical use is a row\n * of `PromptCard`s as starter prompts. Children can call `useChatContext()`\n * to invoke `sendMessage(text)` on click.\n */\n promptSuggestions?: React.ReactNode;\n /**\n * Pass `null` to disable the chat's built-in surface motion (input slide to\n * bottom on first message). Omit / leave undefined for default motion.\n */\n surfaceMotion?: null;\n /** Font size for assistant message markdown. */\n fontSize?: ChatFontSize;\n /** Font family for assistant message markdown. */\n fontFamily?: ChatFontFamily;\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n emptySlot: {\n width: \"100%\",\n maxWidth: \"768px\",\n margin: \"0 auto\",\n padding: \"0 16px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n },\n contentArea: {\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n minHeight: \"0\",\n },\n inputRow: {\n display: \"flex\",\n width: \"100%\",\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n inputInner: {\n display: \"flex\",\n width: \"100%\",\n maxWidth: \"768px\",\n padding: \"0 16px 16px 16px\",\n boxSizing: \"border-box\",\n },\n suggestionsRow: {\n display: \"flex\",\n width: \"100%\",\n maxWidth: \"768px\",\n margin: \"0 auto\",\n padding: \"0 16px 16px 16px\",\n boxSizing: \"border-box\",\n justifyContent: \"center\",\n },\n});\n\n// ---- Inner layout (reads context, positions via CSS without remounting Input) ----\n\ninterface ChatLayoutProps {\n welcomeMessage?: string | React.ReactNode;\n promptSuggestions?: React.ReactNode;\n surfaceMotion?: null;\n placeholder?: string;\n disabled?: boolean;\n actionsStart?: React.ReactNode;\n actionsEnd?: React.ReactNode;\n components?: ChatComponents;\n onCopy?: (content: string) => void;\n onNavigate?: (path: string) => void;\n fontSize?: ChatFontSize;\n fontFamily?: ChatFontFamily;\n}\n\n// In the panel-right sidecar surface, \"default\" is too large — render it as\n// \"small\". \"small\" and \"large\" pass through unchanged.\nconst remapFontSizeForSurface = (\n size: ChatFontSize | undefined,\n surface: string | null,\n): ChatFontSize | undefined => {\n if (surface === \"panel-right\" && (size === undefined || size === \"default\")) {\n return \"small\";\n }\n return size;\n};\n\nconst ChatLayout: React.FC<ChatLayoutProps> = ({\n welcomeMessage,\n promptSuggestions,\n surfaceMotion,\n placeholder,\n disabled,\n actionsStart,\n actionsEnd,\n components,\n onCopy,\n onNavigate,\n fontSize,\n fontFamily,\n}) => {\n const welcomeIsFill =\n welcomeMessage !== undefined && typeof welcomeMessage !== \"string\";\n const welcomeNode =\n typeof welcomeMessage === \"string\" ? (\n <Title3>{welcomeMessage}</Title3>\n ) : (\n welcomeMessage\n );\n const styles = useStyles();\n const surfaceProbeRef = useRef<HTMLDivElement>(null);\n const [surface, setSurface] = useState<string | null>(null);\n useLayoutEffect(() => {\n const el = surfaceProbeRef.current?.closest(\"[data-coral-surface]\");\n setSurface(el?.getAttribute(\"data-coral-surface\") ?? null);\n }, []);\n const effectiveFontSize = remapFontSizeForSurface(fontSize, surface);\n const { messages, isTyping, pendingApproval, awaitingFreeformApproval } = useChatContext();\n const empty = messages.every((m) => m.role === \"system\") && !isTyping;\n const approvalLocksInput = pendingApproval !== null && awaitingFreeformApproval === null;\n const inputDisabled = disabled || approvalLocksInput;\n\n const motionEnabled = surfaceMotion !== null;\n const curve = motionTokens.curveDecelerateMax;\n const spacerTransition = motionEnabled ? `flex-grow 300ms ${curve}` : \"none\";\n const gapTransition = motionEnabled ? `height 300ms ${curve}` : \"none\";\n\n return (\n <>\n <div\n ref={surfaceProbeRef}\n style={{\n flexGrow: empty && !welcomeIsFill ? 1 : 0,\n flexShrink: 1,\n flexBasis: 0,\n minHeight: 0,\n transition: spacerTransition,\n }}\n />\n <div\n className={styles.contentArea}\n style={{\n flex: empty && !welcomeIsFill ? \"none\" : 1,\n overflow: empty && !welcomeIsFill ? \"visible\" : \"hidden\",\n }}\n >\n {empty ? (\n <div\n className={styles.emptySlot}\n style={\n welcomeIsFill\n ? {\n flex: 1,\n justifyContent: \"center\",\n alignContent: \"center\",\n }\n : undefined\n }\n >\n {welcomeNode}\n </div>\n ) : (\n <ChatMessages\n components={components}\n onCopy={onCopy}\n onNavigate={onNavigate}\n fontSize={effectiveFontSize}\n fontFamily={fontFamily}\n />\n )}\n </div>\n <div style={{ height: empty ? 24 : 0, transition: gapTransition }} />\n <div className={styles.inputRow}>\n <div className={styles.inputInner} style={{ flexDirection: \"column\" }}>\n {pendingApproval && <ChatApproval />}\n <ChatInput\n placeholder={\n approvalLocksInput\n ? \"Choose an option above to continue...\"\n : placeholder\n }\n disabled={inputDisabled}\n actionsStart={actionsStart}\n actionsEnd={actionsEnd}\n />\n </div>\n </div>\n {empty && promptSuggestions && (\n <div className={styles.suggestionsRow}>{promptSuggestions}</div>\n )}\n <div\n style={{\n flexGrow: empty && !welcomeIsFill ? 1 : 0,\n flexShrink: 1,\n flexBasis: 0,\n minHeight: 0,\n transition: spacerTransition,\n }}\n />\n <Caption1\n style={{\n display: \"flex\",\n width: \"100%\",\n justifyContent: \"center\",\n height: \"32px\",\n opacity: 0.5,\n }}\n >\n AI makes mistakes. Check outputs.\n </Caption1>\n </>\n );\n};\n\n// ---- Component ----\n\nconst Chat: React.FC<ChatProps> = ({\n api,\n allowedAttachments,\n conversationId,\n initialMessages,\n systemPrompt,\n onSendMessage,\n onMessageComplete,\n onMessagesChange,\n onError,\n autoSendMessage,\n thinkingStatus,\n onStop,\n welcomeMessage,\n promptSuggestions,\n surfaceMotion,\n components,\n onCopy,\n onNavigate,\n placeholder,\n disabled,\n actionsStart,\n actionsEnd,\n fontSize,\n fontFamily,\n}) => {\n // Project-wide config (from CoralProvider) acts as defaults — component\n // props win when both are set. We read the nested `chat` section since\n // coral.config.{ts,js,json} is now domain-sectioned.\n const chatConfig = useCoralConfig()?.chat;\n\n const resolvedApi = api ?? chatConfig?.api;\n // Explicit prop wins; otherwise fall back to the project config.\n const resolvedAllowedAttachments = allowedAttachments ?? chatConfig?.attachments;\n\n return (\n <ChatCanvas\n api={resolvedApi}\n allowedAttachments={resolvedAllowedAttachments}\n conversationId={conversationId}\n initialMessages={initialMessages}\n systemPrompt={systemPrompt}\n onSendMessage={onSendMessage}\n onMessageComplete={onMessageComplete}\n onMessagesChange={onMessagesChange}\n onError={onError}\n autoSendMessage={autoSendMessage}\n thinkingStatus={thinkingStatus}\n onStop={onStop}\n >\n <ChatLayout\n welcomeMessage={welcomeMessage}\n promptSuggestions={promptSuggestions}\n surfaceMotion={surfaceMotion}\n placeholder={placeholder}\n disabled={disabled}\n actionsStart={actionsStart}\n actionsEnd={actionsEnd}\n components={components}\n onCopy={onCopy}\n onNavigate={onNavigate}\n fontSize={fontSize}\n fontFamily={fontFamily}\n />\n </ChatCanvas>\n );\n};\n\nexport default Chat;\n","import React, { useState, useEffect, useLayoutEffect, useRef, useCallback, ReactNode } from \"react\";\nimport { Button, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { ArrowDown } from \"@coral-ai/bundleicons\";\nimport { ChatContext } from \"./Chat.Context\";\nimport { normalizeChatError } from \"./Chat.Error\";\nimport { fileToBase64 } from \"./fileToBase64\";\nimport type { ChatBlock, ChatMessage, ChatChunk, AgentHandler, ChatAttachment, ChatApprovalRequest } from \"./Chat\";\n\n// ---- Props ----\n\nexport interface ChatCanvasProps {\n /**\n * Backend URL Coral POSTs to on send. Used as the built-in handler when\n * `onSendMessage` is not set.\n *\n * Coral serializes attachments to base64 and sends\n * `{ text, history, attachments: [{ name, mediaType, data }] }` as JSON. The\n * response can be `{ type?, reply }` (non-streaming) or a Server-Sent-Events\n * stream of `ChatChunk` JSON lines. The optional `type` field is matched\n * against Coral's built-in task vocabulary to pick the thinking-indicator\n * word pool.\n */\n api?: string;\n /** Which entries to render in the chat input's `+` menu (`Chat.AttachButton`). */\n allowedAttachments?: Array<\"files\" | \"photos\">;\n /** Stable conversation identifier, passed back in onMessageComplete. */\n conversationId?: string;\n /** Pre-load conversation history. */\n initialMessages?: ChatMessage[];\n /** System prompt prepended to every request (not shown in UI). */\n systemPrompt?: string;\n /** Called when the user sends a message. Return a string, async iterable, or ChatResponse. */\n onSendMessage?: (input: string, history: ChatMessage[], attachments: File[]) => ReturnType<AgentHandler>;\n /** Called after every completed assistant response. Use to persist messages. */\n onMessageComplete?: (messages: ChatMessage[], conversationId?: string) => void;\n /** Called on every message-state update (user append, streaming chunk, final). Use for live persistence. */\n onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;\n /** Called when an error occurs during send. */\n onError?: (err: unknown) => void;\n /** Automatically sends this message once on mount. */\n autoSendMessage?: string;\n /** Override the thinking indicator text during generation. */\n thinkingStatus?: string;\n /** Called when the user clicks Stop. Use to abort your fetch/API call. */\n onStop?: () => void;\n children?: ReactNode;\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n root: {\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"column\",\n flex: \"1\",\n minHeight: \"0\",\n position: \"relative\",\n },\n scrollToBottom: {\n position: \"absolute\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 1000,\n cursor: \"pointer\",\n boxShadow: tokens.shadow8,\n marginBottom: \"48px\",\n backgroundColor: 'var(--colorNeutralBackgroundAlpha2)',\n backdropFilter: 'blur(40px) saturate(150%)',\n },\n});\n\n// ---- Helpers ----\n\nfunction isAsyncIterable(value: unknown): value is AsyncIterable<ChatChunk> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n Symbol.asyncIterator in (value as object)\n );\n}\n\nfunction isRateLimitError(err: unknown): boolean {\n const e = err as Record<string, unknown>;\n const status = Number(e?.status ?? e?.statusCode ?? 0);\n const msg = String(e?.message ?? \"\").toLowerCase();\n return (\n status === 429 ||\n msg.includes(\"rate limit\") ||\n msg.includes(\"too many requests\")\n );\n}\n\n/**\n * Yields a single status chunk identifying the backend's task type, then the\n * reply text. Used by the built-in `api` handler to bridge a one-shot JSON\n * response into Coral's streaming chunk machinery so the thinking indicator\n * can swap its word pool.\n */\nasync function* wrapWithStatusChunk(\n taskType: string,\n reply: string,\n): AsyncIterable<ChatChunk> {\n yield { type: \"status\", name: taskType };\n if (reply) yield reply;\n}\n\n/**\n * Parses a Server-Sent-Events or NDJSON response into a `ChatChunk` async\n * iterable. Each line is expected to be a JSON-encoded `ChatChunk` (string,\n * status, reasoning, approval, or todos). Plain strings are yielded as text.\n */\nasync function* parseStream(res: Response): AsyncIterable<ChatChunk> {\n const reader = res.body?.getReader();\n if (!reader) return;\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const raw of lines) {\n const line = raw.startsWith(\"data:\") ? raw.slice(5).trim() : raw.trim();\n if (!line || line === \"[DONE]\") continue;\n try {\n const parsed = JSON.parse(line);\n if (typeof parsed === \"string\") {\n yield parsed;\n } else if (parsed && typeof parsed === \"object\" && \"type\" in parsed) {\n yield parsed as ChatChunk;\n } else if (parsed && typeof parsed === \"object\" && typeof (parsed as { reply?: unknown }).reply === \"string\") {\n if (typeof (parsed as { type?: unknown }).type === \"string\") {\n yield { type: \"status\", name: (parsed as { type: string }).type };\n }\n yield (parsed as { reply: string }).reply;\n }\n } catch {\n // Treat un-parseable lines as raw text.\n yield line;\n }\n }\n }\n if (buffer.trim()) {\n try {\n const parsed = JSON.parse(buffer);\n if (typeof parsed === \"string\") yield parsed;\n else if (parsed && typeof parsed === \"object\" && \"type\" in parsed) yield parsed as ChatChunk;\n } catch {\n yield buffer;\n }\n }\n}\n\n// ---- Component ----\n\nconst ChatCanvas: React.FC<ChatCanvasProps> = ({\n api,\n allowedAttachments,\n conversationId,\n initialMessages,\n systemPrompt,\n onSendMessage,\n onMessageComplete,\n onMessagesChange,\n onError,\n autoSendMessage,\n thinkingStatus,\n onStop,\n children,\n}) => {\n const styles = useStyles();\n\n // Built-in handler used when an `api` URL is configured and no explicit\n // `onSendMessage` handler is provided. Serializes attachments to base64,\n // POSTs JSON, and adapts the response to Coral's existing\n // `ChatResponse` / `AsyncIterable<ChatChunk>` shape.\n const apiHandler: AgentHandler | undefined = api\n ? async function (input, history, files) {\n const attachments = await Promise.all(\n files.map(async (file) => ({\n name: file.name,\n mediaType: file.type,\n data: await fileToBase64(file),\n })),\n );\n const res = await fetch(api, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n text: input,\n history,\n attachments,\n }),\n });\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n throw Object.assign(\n new Error(`Chat API request failed (${res.status}): ${text || res.statusText}`),\n { status: res.status },\n );\n }\n const contentType = res.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"text/event-stream\") || contentType.includes(\"application/x-ndjson\")) {\n return parseStream(res);\n }\n const data = await res.json();\n if (data && typeof data === \"object\") {\n // Optional `type` field becomes a pre-yielded agent chunk so the\n // thinking indicator can swap its word pool. We use a streaming\n // wrapper even for one-shot JSON so the existing chunk machinery\n // handles agent-name routing.\n if (typeof data.type === \"string\") {\n return wrapWithStatusChunk(data.type, String(data.reply ?? \"\"));\n }\n if (typeof data.reply === \"string\") return data.reply;\n }\n return typeof data === \"string\" ? data : \"\";\n }\n : undefined;\n\n const resolvedHandler: AgentHandler | undefined = onSendMessage ?? apiHandler;\n\n const [messages, setMessages] = useState<ChatMessage[]>(\n () => (initialMessages ?? []).map((m) => (m.id ? m : { ...m, id: crypto.randomUUID() })),\n );\n const [input, setInput] = useState(\"\");\n const [isTyping, setIsTyping] = useState(false);\n const [isRetrying, setIsRetrying] = useState(false);\n const [showScrollButton, setShowScrollButton] = useState(false);\n const [inputHeight, setInputHeightState] = useState(0);\n const [isInterrupted, setIsInterrupted] = useState(false);\n const [streamingReasoning, setStreamingReasoning] = useState(\"\");\n const [streamingStatus, setStreamingStatus] = useState<string | undefined>();\n const [attachments, setAttachments] = useState<ChatAttachment[]>([]);\n const [awaitingFreeformApproval, setAwaitingFreeformApproval] = useState<\n { approvalId: string; optionId: string } | null\n >(null);\n\n // Pending approval = latest assistant message whose approval has no answer yet.\n const pendingApproval: ChatApprovalRequest | null = (() => {\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (m.role !== \"assistant\") continue;\n if (m.approval && !m.approval.answer) return m.approval;\n // First assistant message without a pending approval blocks earlier matches.\n if (m.approval && m.approval.answer) return null;\n }\n return null;\n })();\n\n const reasoningRef = useRef(\"\");\n const lastUserInputRef = useRef(\"\");\n const hasEverSentRef = useRef(false);\n const currentConversationIdRef = useRef(conversationId);\n const messagesContainerRef = useRef<HTMLDivElement>(null);\n const [messagesEl, setMessagesEl] = useState<HTMLDivElement | null>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const shouldStopRef = useRef(false);\n const userScrolledUpRef = useRef(false);\n\n // Sync initialMessages (e.g. conversation switched externally).\n useEffect(() => {\n setMessages((current) => {\n if ((initialMessages?.length ?? 0) > 0 || current.length === 0) {\n return (initialMessages ?? []).map((m) =>\n m.id ? m : { ...m, id: crypto.randomUUID() },\n );\n }\n return current;\n });\n }, [initialMessages]);\n\n // Track current conversationId so in-flight streams can detect a session switch.\n useEffect(() => {\n currentConversationIdRef.current = conversationId;\n }, [conversationId]);\n\n // Auto-send on mount; ref guard prevents Strict Mode double-fire.\n const autoSentRef = useRef(false);\n useEffect(() => {\n if (autoSendMessage?.trim() && !autoSentRef.current) {\n autoSentRef.current = true;\n sendMessage(autoSendMessage);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const registerMessagesContainer = useCallback((el: HTMLDivElement | null) => {\n messagesContainerRef.current = el;\n setMessagesEl(el);\n }, []);\n\n // Auto-scroll to bottom when messages update (unless user scrolled up).\n useLayoutEffect(() => {\n if (!userScrolledUpRef.current) {\n if (messagesEl) {\n messagesEl.scrollTop = messagesEl.scrollHeight;\n }\n setShowScrollButton(false);\n }\n }, [messages, messagesEl]);\n\n // Scroll detection — attaches lazily when Chat.Messages mounts.\n useEffect(() => {\n const container = messagesEl;\n if (!container) return;\n const handleScroll = () => {\n const { scrollTop, scrollHeight, clientHeight } = container;\n const atBottom = scrollTop + clientHeight >= scrollHeight - 80;\n userScrolledUpRef.current = !atBottom;\n setShowScrollButton(!atBottom);\n };\n container.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => container.removeEventListener(\"scroll\", handleScroll);\n }, [messagesEl]);\n\n const scrollToBottom = () => {\n userScrolledUpRef.current = false;\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n setShowScrollButton(false);\n };\n\n const handleCopy = (content: string) => {\n navigator.clipboard.writeText(content).catch(console.error);\n };\n\n const addAttachments = (files: File[]) => {\n const newItems: ChatAttachment[] = files.map((file) => {\n const attachment: ChatAttachment = { id: crypto.randomUUID(), file };\n if (file.type.startsWith(\"image/\")) {\n const reader = new FileReader();\n reader.onload = (e) => {\n const preview = e.target?.result as string;\n setAttachments((prev) =>\n prev.map((a) => (a.id === attachment.id ? { ...a, preview } : a))\n );\n };\n reader.readAsDataURL(file);\n }\n return attachment;\n });\n setAttachments((prev) => [...prev, ...newItems]);\n };\n\n const removeAttachment = (id: string) => {\n setAttachments((prev) => prev.filter((a) => a.id !== id));\n };\n\n /**\n * Core streaming runner. Given a fully-prepared message array ending with\n * a user turn, invokes the handler and streams the assistant response.\n * Used by sendMessage, regenerate, and editMessage.\n */\n const runHandler = async (\n textToSend: string,\n updatedMessages: ChatMessage[],\n snapshotAttachments: ChatAttachment[],\n ) => {\n const sessionAtSend = conversationId;\n\n lastUserInputRef.current = textToSend;\n userScrolledUpRef.current = false;\n setMessages(updatedMessages);\n onMessagesChange?.(updatedMessages, sessionAtSend);\n setIsTyping(true);\n setIsInterrupted(false);\n shouldStopRef.current = false;\n reasoningRef.current = \"\";\n setStreamingReasoning(\"\");\n setStreamingStatus(undefined);\n\n const historyForAI: ChatMessage[] = systemPrompt\n ? [{ role: \"system\", content: systemPrompt }, ...updatedMessages]\n : updatedMessages;\n\n const MAX_RETRIES = 3;\n\n try {\n if (resolvedHandler) {\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const assistantId = crypto.randomUUID();\n const placeholder: ChatMessage[] = [...updatedMessages, { id: assistantId, role: \"assistant\", content: \"\" }];\n setMessages(placeholder);\n onMessagesChange?.(placeholder, sessionAtSend);\n const response = await resolvedHandler(textToSend, historyForAI, snapshotAttachments.map((a) => a.file));\n\n if (isAsyncIterable(response)) {\n // We build an ordered `blocks` array as the agent streams so that\n // text, charts, and todo lists render at the exact stream point\n // where they were emitted (matching the Claude.ai / ChatGPT\n // convention). Plain `assistantContent` is also kept — it backs\n // `msg.content` for copy / footer-visibility checks.\n let assistantContent = \"\";\n const blocks: ChatBlock[] = [];\n // Open text being appended to by string chunks. Flushed into\n // `blocks` whenever a non-text block (chart / first todos) is\n // inserted, then a new open buffer starts on the next text chunk.\n let openText = \"\";\n // Index in `blocks` of the todo block for THIS turn, if any.\n // Subsequent `todos` chunks mutate this slot in place so the\n // checklist stays anchored at its original position.\n let todosIndex: number | null = null;\n let rafId: number | null = null;\n let streamedApproval: ChatApprovalRequest | undefined;\n\n const snapshotBlocks = (): ChatBlock[] =>\n openText\n ? [...blocks, { type: \"text\", content: openText }]\n : blocks;\n const flushOpenText = () => {\n if (openText) {\n blocks.push({ type: \"text\", content: openText });\n openText = \"\";\n }\n };\n const commit = () => {\n const nextBlocks = snapshotBlocks();\n let nextMsg: ChatMessage = {\n id: assistantId,\n role: \"assistant\",\n content: assistantContent,\n blocks: nextBlocks,\n };\n setMessages((prev) => {\n const updated = [...prev];\n const last = updated[updated.length - 1];\n if (last && last.id === assistantId) {\n nextMsg = {\n ...last,\n content: assistantContent,\n blocks: nextBlocks,\n };\n }\n updated[updated.length - 1] = nextMsg;\n return updated;\n });\n onMessagesChange?.(\n [...updatedMessages, nextMsg],\n sessionAtSend,\n );\n };\n\n for await (const chunk of response) {\n if (shouldStopRef.current) break;\n // Only bail on an actual conversation switch — not when a new\n // session is created mid-send (undefined → defined), which\n // happens when the app assigns an id on first message.\n if (\n sessionAtSend !== undefined &&\n currentConversationIdRef.current !== sessionAtSend\n ) break;\n if (typeof chunk === \"string\") {\n assistantContent += chunk;\n openText += chunk;\n // Batch text re-renders into one frame so fast token streams\n // don't thrash setState. Non-text chunks commit immediately\n // because they're rare and need to land in stream order.\n if (rafId === null) {\n rafId = requestAnimationFrame(() => {\n rafId = null;\n commit();\n });\n }\n } else if (chunk.type === \"reasoning\") {\n reasoningRef.current += chunk.content;\n setStreamingReasoning(reasoningRef.current);\n } else if (chunk.type === \"status\") {\n setStreamingStatus(chunk.name);\n } else if (chunk.type === \"approval\") {\n streamedApproval = chunk.approval;\n setMessages((prev) => {\n const updated = [...prev];\n const last = updated[updated.length - 1];\n if (last && last.id === assistantId) {\n updated[updated.length - 1] = { ...last, approval: chunk.approval };\n }\n return updated;\n });\n } else if (chunk.type === \"todos\") {\n if (todosIndex === null) {\n flushOpenText();\n todosIndex = blocks.length;\n blocks.push({ type: \"todos\", todos: chunk.todos });\n } else {\n blocks[todosIndex] = { type: \"todos\", todos: chunk.todos };\n }\n commit();\n } else if (chunk.type === \"chart\") {\n flushOpenText();\n blocks.push({ type: \"chart\", spec: chunk.spec });\n commit();\n }\n }\n\n if (rafId !== null) cancelAnimationFrame(rafId);\n if (shouldStopRef.current) setIsInterrupted(true);\n\n if (\n sessionAtSend !== undefined &&\n currentConversationIdRef.current !== sessionAtSend\n ) {\n break;\n }\n\n flushOpenText();\n const finalMsg: ChatMessage = {\n id: assistantId,\n role: \"assistant\",\n content: assistantContent,\n blocks,\n ...(reasoningRef.current ? { metadata: { reasoning: reasoningRef.current } } : {}),\n ...(streamedApproval ? { approval: streamedApproval } : {}),\n };\n const finalMessages = [...updatedMessages, finalMsg];\n setMessages(finalMessages);\n onMessagesChange?.(finalMessages, sessionAtSend);\n onMessageComplete?.(finalMessages, sessionAtSend);\n } else if (typeof response === \"string\") {\n if (currentConversationIdRef.current !== sessionAtSend) break;\n const finalMessages: ChatMessage[] = [...updatedMessages, { id: assistantId, role: \"assistant\" as const, content: response }];\n setMessages(finalMessages);\n onMessagesChange?.(finalMessages, sessionAtSend);\n onMessageComplete?.(finalMessages, sessionAtSend);\n } else {\n if (currentConversationIdRef.current !== sessionAtSend) break;\n const assistantMsg: ChatMessage = {\n id: assistantId,\n role: \"assistant\",\n content: response.content,\n type: response.type,\n metadata: response.metadata,\n todos: response.todos,\n };\n const finalMessages = [...updatedMessages, assistantMsg];\n setMessages(finalMessages);\n onMessagesChange?.(finalMessages, sessionAtSend);\n onMessageComplete?.(finalMessages, sessionAtSend);\n }\n\n break;\n } catch (err) {\n if (isRateLimitError(err) && attempt < MAX_RETRIES - 1) {\n setIsRetrying(true);\n await new Promise<void>((r) => setTimeout(r, (attempt + 1) * 3000));\n continue;\n }\n throw err;\n }\n }\n }\n } catch (err) {\n onError?.(err);\n // Persist the failure as an assistant message carrying a normalized\n // error. Keeping it in the message stream (vs. transient state) means\n // the error card survives reloads and chat-tab switches.\n if (\n sessionAtSend === undefined ||\n currentConversationIdRef.current === sessionAtSend\n ) {\n const erroredMessages: ChatMessage[] = [\n ...updatedMessages,\n {\n id: crypto.randomUUID(),\n role: \"assistant\",\n content: \"\",\n error: normalizeChatError(err),\n },\n ];\n setMessages(erroredMessages);\n onMessagesChange?.(erroredMessages, sessionAtSend);\n }\n } finally {\n setIsRetrying(false);\n setIsTyping(false);\n }\n };\n\n /**\n * Marks an approval request as answered. If the chosen option is `freeform`,\n * transitions into the awaiting-freeform state instead — the next user\n * submission via sendMessage will then resolve the approval with the typed\n * text. Otherwise resolves immediately and re-runs the agent so it can\n * react to the user's choice.\n */\n const resolveApproval = (approvalId: string, optionId: string) => {\n const target = messages.find(\n (m) => m.role === \"assistant\" && m.approval?.id === approvalId,\n );\n if (!target || !target.approval) return;\n if (target.approval.answer) return;\n\n const option = target.approval.options.find((o) => o.id === optionId);\n if (!option) return;\n\n if (option.freeform) {\n setAwaitingFreeformApproval({ approvalId, optionId });\n return;\n }\n\n // Immediate resolution: stamp the answer and append a typed user reply.\n const updated = messages.map((m) =>\n m.role === \"assistant\" && m.approval?.id === approvalId\n ? { ...m, approval: { ...m.approval!, answer: { optionId } } }\n : m,\n );\n const replyText = option.label;\n const userMsg: ChatMessage = {\n id: crypto.randomUUID(),\n role: \"user\",\n type: \"approval_response\",\n content: replyText,\n metadata: { approvalId, optionId, label: option.label },\n };\n const next = [...updated, userMsg];\n void runHandler(replyText, next, []);\n };\n\n const sendMessage = async (overrideInput?: string) => {\n const textToSend = overrideInput ?? input;\n if (!textToSend.trim()) return;\n\n // Freeform approval interception: the next submission is the approval reply.\n if (awaitingFreeformApproval) {\n const { approvalId, optionId } = awaitingFreeformApproval;\n const target = messages.find(\n (m) => m.role === \"assistant\" && m.approval?.id === approvalId,\n );\n if (target && target.approval) {\n const option = target.approval.options.find((o) => o.id === optionId);\n const updated = messages.map((m) =>\n m.role === \"assistant\" && m.approval?.id === approvalId\n ? { ...m, approval: { ...m.approval!, answer: { optionId, text: textToSend } } }\n : m,\n );\n const userMsg: ChatMessage = {\n id: crypto.randomUUID(),\n role: \"user\",\n type: \"approval_response\",\n content: textToSend.replace(/^[\\n\\r]+|[\\n\\r]+$/g, \"\"),\n metadata: { approvalId, optionId, label: option?.label, text: textToSend },\n };\n const next = [...updated, userMsg];\n if (!overrideInput) setInput(\"\");\n setAwaitingFreeformApproval(null);\n hasEverSentRef.current = true;\n await runHandler(textToSend, next, []);\n return;\n }\n // Target gone (shouldn't happen) — clear awaiting state and fall through.\n setAwaitingFreeformApproval(null);\n }\n\n hasEverSentRef.current = true;\n\n // overrideInput is used by retry/error flows where the caller wants to\n // discard the previous failed user+assistant pair before resending.\n // For a fresh send, drop a trailing errored assistant message so a stale\n // error card doesn't get stranded mid-conversation.\n const lastMessage = messages[messages.length - 1];\n const baseMessages = overrideInput\n ? messages.filter((_, i) => i < messages.length - 2)\n : lastMessage?.role === \"assistant\" && lastMessage.error\n ? messages.slice(0, -1)\n : messages;\n\n const snapshotAttachments = attachments;\n const attachmentMeta = snapshotAttachments.map((a) => ({\n name: a.file.name,\n type: a.file.type,\n preview: a.preview,\n }));\n\n const updatedMessages: ChatMessage[] = [\n ...baseMessages,\n {\n id: crypto.randomUUID(),\n role: \"user\",\n content: textToSend.replace(/^[\\n\\r]+|[\\n\\r]+$/g, \"\"),\n ...(attachmentMeta.length > 0 ? { metadata: { attachments: attachmentMeta } } : {}),\n },\n ];\n\n if (!overrideInput) setInput(\"\");\n setAttachments([]);\n\n await runHandler(textToSend, updatedMessages, snapshotAttachments);\n };\n\n /**\n * Resolves the user-message index that should drive a regenerate.\n * - No id: the last user message in the array.\n * - Id of a user message: that message.\n * - Id of an assistant message: the user message immediately preceding it.\n * Returns -1 if no valid target exists.\n */\n const resolveRegenerateTarget = (messageId?: string): number => {\n if (!messageId) {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") return i;\n }\n return -1;\n }\n const idx = messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return -1;\n if (messages[idx].role === \"user\") return idx;\n if (messages[idx].role === \"assistant\") {\n for (let i = idx - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") return i;\n }\n }\n return -1;\n };\n\n const regenerate = async (messageId?: string) => {\n const userIdx = resolveRegenerateTarget(messageId);\n if (userIdx === -1) return;\n const userMsg = messages[userIdx];\n const baseMessages = messages.slice(0, userIdx + 1);\n await runHandler(userMsg.content, baseMessages, []);\n };\n\n const editMessage = async (messageId: string, newContent: string) => {\n const idx = messages.findIndex((m) => m.id === messageId);\n if (idx === -1) return;\n if (messages[idx].role !== \"user\") return;\n const trimmed = newContent.replace(/^[\\n\\r]+|[\\n\\r]+$/g, \"\");\n if (!trimmed.trim()) return;\n\n const editedMessage: ChatMessage = {\n ...messages[idx],\n content: trimmed,\n };\n const baseMessages: ChatMessage[] = [\n ...messages.slice(0, idx),\n editedMessage,\n ];\n await runHandler(trimmed, baseMessages, []);\n };\n\n return (\n <ChatContext.Provider\n value={{\n sendMessage,\n regenerate,\n editMessage,\n scrollToBottom,\n handleCopy,\n messages,\n setMessages,\n input,\n setInput,\n isTyping,\n isRetrying,\n isInterrupted,\n streamingReasoning,\n streamingStatus,\n thinkingStatus,\n showScrollButton,\n setInputHeight: setInputHeightState,\n messagesContainerRef,\n registerMessagesContainer,\n bottomRef,\n lastUserInputRef,\n hasEverSentRef,\n shouldStopRef,\n onStop,\n attachments,\n addAttachments,\n removeAttachment,\n allowedAttachments,\n pendingApproval,\n awaitingFreeformApproval,\n resolveApproval,\n }}\n >\n <div className={styles.root}>\n {children}\n {showScrollButton && (\n <Button\n onClick={scrollToBottom}\n className={styles.scrollToBottom}\n shape=\"circular\"\n style={{\n bottom: inputHeight + 16,\n backgroundColor: \"transparent\",\n border: `1px solid ${tokens.colorNeutralStroke3}`,\n backdropFilter: \"saturate(180%) blur(16px)\",\n }}\n icon={<ArrowDown style={{ fontSize: \"16px\" }} />}\n />\n )}\n </div>\n </ChatContext.Provider>\n );\n};\n\nexport default ChatCanvas;\n","import { createContext, useContext } from \"react\";\nimport type React from \"react\";\nimport type { ChatMessage, ChatAttachment, ChatApprovalRequest } from \"./Chat\";\n\nexport interface ChatContextValue {\n // ── Actions ───────────────────────────────────────────────────────────────\n sendMessage: (overrideInput?: string) => Promise<void>;\n /**\n * Re-runs the assistant turn following the matching user message.\n * If `messageId` is omitted, regenerates the last assistant message.\n * If `messageId` targets an assistant message, the matching user prompt is replayed.\n * If `messageId` targets a user message, the existing assistant reply for that turn is discarded and re-generated.\n */\n regenerate: (messageId?: string) => Promise<void>;\n /**\n * Replaces the content of an existing user message and re-runs from that point.\n * Truncates everything after the edited message and re-invokes the handler.\n */\n editMessage: (messageId: string, newContent: string) => Promise<void>;\n scrollToBottom: () => void;\n /** Pre-binds navigator.clipboard.writeText + the onCopy prop callback. */\n handleCopy: (content: string) => void;\n\n // ── Message state ─────────────────────────────────────────────────────────\n messages: ChatMessage[];\n setMessages: React.Dispatch<React.SetStateAction<ChatMessage[]>>;\n\n // ── Input state ───────────────────────────────────────────────────────────\n input: string;\n setInput: React.Dispatch<React.SetStateAction<string>>;\n\n // ── Generation state ──────────────────────────────────────────────────────\n isTyping: boolean;\n isRetrying: boolean;\n isInterrupted: boolean;\n streamingReasoning: string;\n /** Name from the latest streamed `status` chunk — picks the thinking-indicator word pool. */\n streamingStatus?: string;\n /** Forwarded from Chat.Canvas thinkingStatus prop so Chat.Messages can read it. */\n thinkingStatus?: string;\n\n // ── Scroll / layout ───────────────────────────────────────────────────────\n showScrollButton: boolean;\n /** Called by Chat.Input to report its measured height so Canvas positions the scroll button. */\n setInputHeight: (height: number) => void;\n\n // ── Refs exposed to children ──────────────────────────────────────────────\n messagesContainerRef: React.RefObject<HTMLDivElement | null>;\n /** Called by Chat.Messages on mount/unmount so Canvas can attach scroll listener lazily. */\n registerMessagesContainer: (el: HTMLDivElement | null) => void;\n bottomRef: React.RefObject<HTMLDivElement | null>;\n lastUserInputRef: React.MutableRefObject<string>;\n hasEverSentRef: React.MutableRefObject<boolean>;\n shouldStopRef: React.MutableRefObject<boolean>;\n\n // ── Attachments ───────────────────────────────────────────────────────────\n attachments: ChatAttachment[];\n addAttachments: (files: File[]) => void;\n removeAttachment: (id: string) => void;\n /** Declarative list of allowed attachment kinds; renders the `+` menu in Chat.Input when set. */\n allowedAttachments?: Array<\"files\" | \"photos\">;\n\n // ── Approval (HITL) ───────────────────────────────────────────────────────\n /** Latest unanswered approval request from the assistant, or null. */\n pendingApproval: ChatApprovalRequest | null;\n /**\n * Set when the user clicks an option marked `freeform: true`. While this is\n * non-null, Chat.Input is unlocked and the next submission resolves the\n * approval (carrying the typed text) instead of being sent as a normal turn.\n */\n awaitingFreeformApproval: { approvalId: string; optionId: string } | null;\n /**\n * Resolves an approval request. If the option is `freeform`, transitions\n * into the awaiting-freeform state instead of resolving immediately.\n */\n resolveApproval: (approvalId: string, optionId: string) => void;\n\n // ── Callbacks forwarded from Canvas props ─────────────────────────────────\n onStop?: () => void;\n}\n\nexport const ChatContext = createContext<ChatContextValue>({} as ChatContextValue);\n\nexport function useChatContext(): ChatContextValue {\n return useContext(ChatContext);\n}\n","import React from \"react\";\nimport { Body1, Button, makeStyles, tokens } from \"@fluentui/react-components\";\nimport {\n ErrorCircle20Regular,\n Clock20Regular,\n LockClosed20Regular,\n PlugDisconnected20Regular,\n Warning20Regular,\n ArrowCounterclockwise16Regular,\n} from \"@fluentui/react-icons\";\n\n// ---- Error normalization ----\n\nexport type ErrorCategory =\n | \"auth_billing\"\n | \"rate_limit\"\n | \"overloaded\"\n | \"bad_input\"\n | \"not_found\"\n | \"server_error\"\n | \"unknown\";\n\n/**\n * A categorized, user-friendly error. This shape is JSON-serializable so it\n * can be stored on a `ChatMessage` and survive persistence / rehydration.\n */\nexport interface NormalizedChatError {\n category: ErrorCategory;\n message: string;\n}\n\nconst ERROR_CATEGORIES: ErrorCategory[] = [\n \"auth_billing\",\n \"rate_limit\",\n \"overloaded\",\n \"bad_input\",\n \"not_found\",\n \"server_error\",\n \"unknown\",\n];\n\n/** True when `err` is already a `NormalizedChatError` (e.g. rehydrated from storage). */\nfunction isNormalizedChatError(err: unknown): err is NormalizedChatError {\n return (\n !!err &&\n typeof err === \"object\" &&\n typeof (err as NormalizedChatError).message === \"string\" &&\n ERROR_CATEGORIES.includes((err as NormalizedChatError).category)\n );\n}\n\n/**\n * Normalizes raw errors from Anthropic, OpenAI, and Google Gemini into a\n * common category + user-friendly message. Safe to call with any unknown value.\n * Idempotent — passing an already-normalized error returns it unchanged.\n */\nexport function normalizeChatError(err: unknown): NormalizedChatError {\n // Already normalized (persisted error rehydrated from storage) — pass through.\n if (isNormalizedChatError(err)) return err;\n\n const anyErr = err as Record<string, unknown>;\n const rawMessage = String(\n anyErr?.message ?? (anyErr?.error as Record<string, unknown>)?.message ?? err ?? \"\"\n ).toLowerCase();\n\n const status = Number(anyErr?.status ?? anyErr?.statusCode ?? 0);\n const errorType = String(\n (anyErr?.error as Record<string, unknown>)?.type ?? anyErr?.type ?? anyErr?.code ?? \"\"\n );\n const errorCode = String(\n (anyErr?.error as Record<string, unknown>)?.code ?? anyErr?.code ?? \"\"\n );\n\n // Auth / billing — Anthropic \"credit\", OpenAI \"insufficient_quota\", Gemini PERMISSION_DENIED\n if (\n rawMessage.includes(\"credit\") ||\n rawMessage.includes(\"billing\") ||\n rawMessage.includes(\"insufficient_quota\") ||\n errorCode === \"insufficient_quota\" ||\n errorType === \"PERMISSION_DENIED\"\n ) {\n return {\n category: \"auth_billing\",\n message: \"API credits exhausted. Add credits in your provider's billing dashboard.\",\n };\n }\n\n // Rate limit — Anthropic rate_limit_error, OpenAI 429, Gemini RESOURCE_EXHAUSTED\n if (\n errorType === \"rate_limit_error\" ||\n rawMessage.includes(\"rate limit\") ||\n rawMessage.includes(\"too many requests\")\n ) {\n return {\n category: \"rate_limit\",\n message: \"You're being rate limited. Wait a moment and try again.\",\n };\n }\n\n // Overloaded — Anthropic overloaded_error (529), OpenAI 503\n if (\n status === 529 ||\n status === 503 ||\n errorType === \"overloaded_error\" ||\n errorType === \"RESOURCE_EXHAUSTED\" ||\n rawMessage.includes(\"overload\") ||\n rawMessage.includes(\"capacity\")\n ) {\n return {\n category: \"overloaded\",\n message: \"The AI service is overloaded right now. Try again in a few seconds.\",\n };\n }\n\n // Not found — OpenAI 404 / model_not_found, Gemini NOT_FOUND\n if (\n status === 404 ||\n errorType === \"NOT_FOUND\" ||\n rawMessage.includes(\"model_not_found\") ||\n rawMessage.includes(\"not found\")\n ) {\n return {\n category: \"not_found\",\n message: \"Model not found. Check the model name in your configuration.\",\n };\n }\n\n // Bad input — Anthropic/OpenAI invalid_request_error (400), Gemini INVALID_ARGUMENT\n if (\n status === 400 ||\n errorType === \"invalid_request_error\" ||\n errorType === \"INVALID_ARGUMENT\"\n ) {\n return {\n category: \"bad_input\",\n message: \"The request was invalid. Check your message or API configuration.\",\n };\n }\n\n // Server error — 5xx, Anthropic api_error, Gemini INTERNAL\n if (status >= 500 || errorType === \"api_error\" || errorType === \"INTERNAL\") {\n return {\n category: \"server_error\",\n message: \"The AI service hit an internal error. Try again shortly.\",\n };\n }\n\n return {\n category: \"unknown\",\n message: \"Something went wrong. Check your connection and try again.\",\n };\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n root: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"8px\",\n padding: \"12px\",\n borderRadius: tokens.borderRadiusXLarge,\n backgroundColor: tokens.colorNeutralBackground3,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n color: tokens.colorNeutralForeground3,\n width: \"100%\",\n boxSizing: \"border-box\",\n margin: \"8px 0\",\n },\n left: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n minWidth: 0,\n },\n message: {\n fontFamily: \"var(--fontFamilyMonospace)\",\n },\n});\n\nconst categoryIcon: Record<ErrorCategory, React.ReactElement> = {\n auth_billing: <LockClosed20Regular />,\n rate_limit: <Clock20Regular />,\n overloaded: <PlugDisconnected20Regular />,\n bad_input: <Warning20Regular />,\n not_found: <ErrorCircle20Regular />,\n server_error: <ErrorCircle20Regular />,\n unknown: <Warning20Regular />,\n};\n\n// ---- Component ----\n\nexport interface ChatErrorProps {\n /** Raw error thrown by your onSendMessage handler — any provider shape works. */\n error: unknown;\n /** Optional retry callback shown as a button. */\n onRetry?: () => void;\n}\n\nconst ChatError: React.FC<ChatErrorProps> = ({ error, onRetry }) => {\n const styles = useStyles();\n const { category, message } = normalizeChatError(error);\n\n return (\n <div className={styles.root}>\n <span className={styles.left}>\n {categoryIcon[category]}\n <Body1 className={styles.message}>{message}</Body1>\n </span>\n {onRetry && (\n <Button\n size=\"small\"\n appearance=\"primary\"\n onClick={onRetry}\n >\n Retry\n </Button>\n )}\n </div>\n );\n};\n\nexport default ChatError;\n","/**\n * Reads a browser `File` and returns its raw base64 payload (without the\n * `data:<mime>;base64,` prefix).\n *\n * Used by Coral's built-in `api` handler to serialize attachments before\n * POSTing them to the engineer's backend, and exported so consumers writing\n * a custom `onSendMessage` can reuse the same encoding.\n */\nexport function fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const comma = dataUrl.indexOf(\",\");\n resolve(comma === -1 ? dataUrl : dataUrl.slice(comma + 1));\n };\n reader.onerror = () => reject(reader.error ?? new Error(\"FileReader failed\"));\n reader.readAsDataURL(file);\n });\n}\n","import React, { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Body1,\n Button,\n Caption1,\n makeStyles,\n tokens,\n} from \"@fluentui/react-components\";\nimport {\n ArrowClockwise,\n Copy,\n Edit as EditIcon,\n Info,\n Warning,\n} from \"@coral-ai/bundleicons\";\nimport {\n CoralMarkdown,\n type ChatFontSize,\n type ChatFontFamily,\n} from \"@coral-ai/markdown\";\nimport { useChatContext } from \"./Chat.Context\";\nimport ThinkingIndicator from \"./Chat.ThinkingIndicator\";\nimport { resolveTaskMessages } from \"./Chat.TaskMessages\";\nimport ChatCallout from \"./Chat.Callout\";\nimport ChatError from \"./Chat.Error\";\nimport ReasoningBlock from \"./Chat.ReasoningBlock\";\nimport ChatTodoList from \"./Chat.TodoList\";\nimport { CoralChart } from \"@coral-ai/charts\";\nimport type { ChatBlock, ChatMessage, ChatComponents } from \"./Chat\";\n\n// Resolves an assistant message to its renderable block list.\n//\n// New messages stream a `blocks` array in agent emission order. Older\n// persisted messages only have `content` / `charts` / `todos` fields — we\n// synthesize blocks from them on the fly so saved conversations keep\n// rendering correctly without a data migration.\nfunction resolveBlocks(msg: ChatMessage): ChatBlock[] {\n if (msg.blocks) return msg.blocks;\n const legacy: ChatBlock[] = [];\n if (msg.todos && msg.todos.length > 0) {\n legacy.push({ type: \"todos\", todos: msg.todos });\n }\n if (msg.charts) {\n for (const spec of msg.charts) legacy.push({ type: \"chart\", spec });\n }\n if (msg.content) legacy.push({ type: \"text\", content: msg.content });\n return legacy;\n}\nimport { CheckmarkCircle20Filled } from \"@fluentui/react-icons\";\n\n// ---- Props ----\n\nexport interface ChatMessagesProps {\n /**\n * Custom renderers keyed by message type.\n * Falls back to default markdown rendering if no match.\n */\n components?: ChatComponents;\n /** Called when the user copies an assistant message. */\n onCopy?: (content: string) => void;\n /** Called when the user clicks an internal link (href starts with \"/\"). */\n onNavigate?: (path: string) => void;\n /** Font size for assistant message markdown. */\n fontSize?: ChatFontSize;\n /** Font family for assistant message markdown. */\n fontFamily?: ChatFontFamily;\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n messages: {\n flex: \"1\",\n overflowY: \"auto\",\n overflowX: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n padding: \"40px 0\",\n boxSizing: \"border-box\",\n scrollbarGutter: \"stable both-edges\",\n },\n messageWrapper: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"24px\",\n width: \"100%\",\n maxWidth: \"768px\",\n padding: \"0 16px\",\n boxSizing: \"border-box\",\n },\n // ── User message column: holds attachments + bubble + hover-only footer ──\n userRow: {\n alignSelf: \"flex-end\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n maxWidth: \"80%\",\n \"&:hover .coral-user-footer, &:focus-within .coral-user-footer\": {\n opacity: 1,\n },\n },\n userBubble: {\n backgroundColor: tokens.colorNeutralBackground2,\n color: tokens.colorNeutralForeground2,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n padding: \"8px 12px\",\n borderRadius: tokens.borderRadiusXLarge,\n wordBreak: \"break-word\",\n boxSizing: \"border-box\",\n },\n userFooter: {\n display: \"flex\",\n justifyContent: \"flex-end\",\n marginTop: \"6px\",\n marginRight: \"-10px\",\n opacity: 0,\n transition: \"opacity 120ms ease-in-out\",\n },\n userActions: {\n display: \"flex\",\n },\n // ── Inline edit mode ──\n userEditWrap: {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"stretch\",\n // width: \"min(640px, 80vw)\",\n gap: \"8px\",\n },\n userEditTextarea: {\n backgroundColor: tokens.colorNeutralBackground2,\n color: tokens.colorNeutralForeground2,\n border: `1px solid ${tokens.colorNeutralStroke1}`,\n padding: \"8px 12px\",\n borderRadius: tokens.borderRadiusLarge,\n fontFamily: tokens.fontFamilyBase,\n fontSize: tokens.fontSizeBase300,\n lineHeight: tokens.lineHeightBase300,\n resize: \"none\",\n outline: \"none\",\n width: \"100%\",\n boxSizing: \"border-box\",\n minHeight: \"40px\",\n \"&:focus\": {\n border: `1px solid ${tokens.colorNeutralStroke3}`,\n },\n },\n userEditFooter: {\n display: \"flex\",\n marginTop: \"8px\",\n // marginLeft: \"12px\",\n color: `${tokens.colorNeutralForeground3}`,\n gap: \"12px\",\n alignItems: \"center\",\n },\n userEditActions: {\n display: \"flex\",\n justifyContent: \"flex-end\",\n gap: \"8px\",\n },\n // ── Assistant message ──\n messageAssistant: {\n alignSelf: \"flex-start\",\n width: \"100%\",\n color: tokens.colorNeutralForeground2,\n wordBreak: \"break-word\",\n boxSizing: \"border-box\",\n \"&:hover .coral-assistant-footer, &:focus-within .coral-assistant-footer\": {\n opacity: 1,\n },\n },\n assistantFooter: {\n display: \"flex\",\n justifyContent: \"space-between\",\n marginTop: \"6px\",\n marginLeft: \"-10px\",\n // Hover-only by default; the latest message overrides this to stay visible.\n opacity: 0,\n transition: \"opacity 120ms ease-in-out\",\n },\n assistantActions: {\n display: \"flex\",\n },\n copiedBadge: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"32px\",\n height: \"32px\",\n color: tokens.colorPaletteSeafoamForeground2,\n },\n footerIconButton: {\n color: tokens.colorNeutralForeground3,\n },\n});\n\n// ---- Component ----\n\nconst ChatMessages: React.FC<ChatMessagesProps> = ({\n components,\n onCopy,\n onNavigate,\n fontSize,\n fontFamily,\n}) => {\n const styles = useStyles();\n const ctx = useChatContext();\n const {\n messages,\n setMessages,\n isTyping,\n isRetrying,\n isInterrupted,\n streamingReasoning,\n streamingStatus,\n thinkingStatus,\n sendMessage,\n regenerate,\n editMessage,\n handleCopy,\n lastUserInputRef,\n registerMessagesContainer,\n bottomRef,\n } = ctx;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const [surface, setSurface] = useState<string | null>(null);\n useLayoutEffect(() => {\n const el = containerRef.current?.closest(\"[data-coral-surface]\");\n setSurface(el?.getAttribute(\"data-coral-surface\") ?? null);\n }, []);\n const isSidecar = surface === \"panel-right\";\n const [copiedKey, setCopiedKey] = useState<string | null>(null);\n const copiedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // ── Edit mode state ──────────────────────────────────────────────────────\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editDraft, setEditDraft] = useState(\"\");\n const editTextareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n registerMessagesContainer(containerRef.current);\n return () => registerMessagesContainer(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Auto-grow + focus the edit textarea when entering edit mode.\n useLayoutEffect(() => {\n if (editingId && editTextareaRef.current) {\n const ta = editTextareaRef.current;\n ta.focus();\n ta.setSelectionRange(ta.value.length, ta.value.length);\n ta.style.height = \"auto\";\n ta.style.height = `${ta.scrollHeight}px`;\n }\n }, [editingId]);\n\n const startEdit = (msg: ChatMessage) => {\n if (!msg.id) return;\n setEditingId(msg.id);\n setEditDraft(msg.content);\n };\n\n const cancelEdit = () => {\n setEditingId(null);\n setEditDraft(\"\");\n };\n\n const saveEdit = async () => {\n if (!editingId) return;\n const trimmed = editDraft.trim();\n if (!trimmed) return;\n const id = editingId;\n setEditingId(null);\n setEditDraft(\"\");\n await editMessage(id, trimmed);\n };\n\n const handleEditTextareaInput = (\n e: React.ChangeEvent<HTMLTextAreaElement>,\n ) => {\n setEditDraft(e.target.value);\n const ta = e.target;\n ta.style.height = \"auto\";\n ta.style.height = `${ta.scrollHeight}px`;\n };\n\n const handleEditKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n cancelEdit();\n } else if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n void saveEdit();\n }\n };\n\n const onCopyMerged = (content: string, key: string) => {\n handleCopy(content);\n onCopy?.(content);\n if (copiedTimerRef.current) clearTimeout(copiedTimerRef.current);\n setCopiedKey(key);\n copiedTimerRef.current = setTimeout(() => setCopiedKey(null), 1500);\n };\n\n // ── Renderers ────────────────────────────────────────────────────────────\n\n const renderUserMessage = (msg: ChatMessage, index: number) => {\n const key = msg.id ?? `idx-${index}`;\n const isEditing = !!msg.id && editingId === msg.id;\n const attachments = Array.isArray(msg.metadata?.attachments)\n ? (msg.metadata!.attachments as Array<{\n name: string;\n type: string;\n preview?: string;\n }>)\n : null;\n\n return (\n <div key={key} className={styles.userRow}>\n {attachments && (\n <div\n style={{\n display: \"flex\",\n gap: \"6px\",\n flexWrap: \"wrap\",\n marginBottom: \"6px\",\n }}\n >\n {attachments.map((a, i) =>\n a.type.startsWith(\"image/\") && a.preview ? (\n <img\n key={i}\n src={a.preview}\n alt={a.name}\n style={{\n width: 64,\n height: 64,\n borderRadius: tokens.borderRadiusMedium,\n objectFit: \"cover\",\n }}\n />\n ) : (\n <span\n key={i}\n style={{\n fontSize: 12,\n padding: \"2px 8px\",\n borderRadius: tokens.borderRadiusSmall,\n backgroundColor: tokens.colorNeutralBackground3,\n color: tokens.colorNeutralForeground2,\n }}\n >\n 📄 {a.name}\n </span>\n ),\n )}\n </div>\n )}\n\n {isEditing ? (\n <div className={styles.userEditWrap}>\n <textarea\n ref={editTextareaRef}\n className={styles.userEditTextarea}\n value={editDraft}\n onChange={handleEditTextareaInput}\n onKeyDown={handleEditKeyDown}\n rows={1}\n />\n\n <div className={styles.userEditFooter}>\n <Info\n style={{\n marginRight: \"6px\",\n color: `${tokens.colorNeutralForeground3}`,\n fontSize: \"20px\",\n boxSizing: \"border-box\",\n flexShrink: 0,\n }}\n />\n <Caption1>\n Editing this message will discard the current response and\n regenerate from here.\n </Caption1>\n <div className={styles.userEditActions}>\n <Button appearance=\"subtle\" onClick={cancelEdit}>\n Cancel\n </Button>\n <Button\n appearance=\"primary\"\n onClick={saveEdit}\n disabled={!editDraft.trim()}\n >\n Save\n </Button>\n </div>\n </div>\n </div>\n ) : (\n <>\n <div className={styles.userBubble}>\n <Body1>\n {msg.content.split(\"\\n\").map((line, i, arr) => (\n <React.Fragment key={i}>\n {line}\n {i < arr.length - 1 && <br />}\n </React.Fragment>\n ))}\n </Body1>\n </div>\n {msg.id && (\n <div className={`${styles.userFooter} coral-user-footer`}>\n <div className={styles.userActions}>\n {copiedKey === `user-${key}` ? (\n <span className={styles.copiedBadge}>\n <CheckmarkCircle20Filled />\n </span>\n ) : (\n <Button\n onClick={() => onCopyMerged(msg.content, `user-${key}`)}\n title=\"Copy message\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<Copy />}\n />\n )}\n <Button\n onClick={() => startEdit(msg)}\n title=\"Edit message\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<EditIcon />}\n />\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n };\n\n const renderAssistantMessage = (msg: ChatMessage, index: number) => {\n const isLatest = index === messages.length - 1;\n const reasoning =\n isLatest && isTyping\n ? streamingReasoning\n : (msg.metadata?.reasoning as string | undefined);\n\n if (msg.type && components?.[msg.type]) {\n const CustomRenderer = components[msg.type];\n return (\n <CustomRenderer\n message={msg}\n onReply={(content) => {\n const updatedMessages: ChatMessage[] = [\n ...messages.slice(0, index + 1),\n { role: \"user\", content },\n ];\n setMessages(updatedMessages);\n sendMessage(content);\n }}\n />\n );\n }\n\n const key = msg.id ?? `idx-${index}`;\n\n return (\n <div>\n {reasoning && (\n <ReasoningBlock\n content={reasoning}\n isStreaming={isLatest && isTyping && !msg.content}\n />\n )}\n {resolveBlocks(msg).map((block, i) => {\n if (block.type === \"todos\") {\n return <ChatTodoList key={`todos-${i}`} todos={block.todos} />;\n }\n if (block.type === \"chart\") {\n return <CoralChart key={`chart-${i}`} spec={block.spec} />;\n }\n return (\n <CoralMarkdown\n key={`text-${i}`}\n onNavigate={onNavigate}\n fontSize={fontSize}\n fontFamily={fontFamily}\n >\n {block.content}\n </CoralMarkdown>\n );\n })}\n {msg.error && (\n <ChatError\n error={msg.error}\n onRetry={() => {\n const userMsg = messages[index - 1];\n if (userMsg?.role === \"user\") sendMessage(userMsg.content);\n }}\n />\n )}\n {isInterrupted && !isTyping && isLatest && (\n <ChatCallout\n message=\"Response was interrupted\"\n onRetry={() => sendMessage(lastUserInputRef.current)}\n />\n )}\n {!(isTyping && isLatest) && msg.content.trim() && (\n <div\n className={`${styles.assistantFooter} coral-assistant-footer`}\n // Latest message keeps its footer pinned visible; older ones\n // fall back to the hover-only rule on `.messageAssistant`.\n style={isLatest ? { opacity: 1 } : undefined}\n >\n <div className={styles.assistantActions}>\n {copiedKey === `assistant-${key}` ? (\n <span className={styles.copiedBadge}>\n <CheckmarkCircle20Filled />\n </span>\n ) : (\n <Button\n onClick={() => onCopyMerged(msg.content, `assistant-${key}`)}\n title=\"Copy response\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<Copy />}\n />\n )}\n {isLatest && (\n <Button\n onClick={() => regenerate(msg.id)}\n title=\"Regenerate response\"\n appearance=\"subtle\"\n className={styles.footerIconButton}\n icon={<ArrowClockwise />}\n />\n )}\n </div>\n </div>\n )}\n </div>\n );\n };\n\n return (\n <div className={styles.messages} ref={containerRef}>\n <div\n className={styles.messageWrapper}\n style={isSidecar ? { padding: \"0 8px\" } : undefined}\n >\n {messages.map((msg, index) => {\n if (msg.role === \"user\") {\n return renderUserMessage(msg, index);\n }\n const key = msg.id ?? `idx-${index}`;\n const isLatest = index === messages.length - 1;\n return (\n <div\n key={key}\n className={`${styles.messageAssistant} coral-message-assistant${isLatest ? \" is-latest\" : \"\"}`}\n >\n {renderAssistantMessage(msg, index)}\n </div>\n );\n })}\n\n {isTyping && (\n <ThinkingIndicator\n isRetrying={isRetrying}\n status={thinkingStatus}\n messages={resolveTaskMessages(streamingStatus)}\n />\n )}\n <div ref={bottomRef} />\n </div>\n </div>\n );\n};\n\nexport default ChatMessages;\n","import React, { useState, useEffect, useRef } from \"react\";\nimport { makeStyles, Spinner, tokens } from \"@fluentui/react-components\";\n\nconst thinkingMessages = [\n \"Generating\",\n \"Thinking\",\n \"Optimizing\",\n \"Processing\",\n \"Analyzing\",\n \"Drafting\",\n \"Evaluating\",\n \"Computing\",\n \"Synthesizing\",\n \"Reviewing\",\n \"Refining\",\n];\n\nconst retryingMessages = [\n \"Still working\",\n \"Awaiting\",\n \"Hang tight\",\n \"One moment\",\n \"Almost there\",\n \"Just a moment\",\n \"Reconnecting\",\n];\n\nconst TYPING_SPEED = 80; // ms per character\nconst HOLD_DURATION = 1300; // ms to hold the full word before moving on\n\nconst useStyles = makeStyles({\n root: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n width: \"100%\",\n color: tokens.colorNeutralForeground3,\n },\n text: {\n // fontFamily: tokens.fontFamilyBase,\n // fontSize: tokens.fontSizeBase200,\n // color: tokens.colorNeutralForeground3,\n fontFamily: \"var(--fontFamilyMonospace)\",\n minWidth: \"0\",\n },\n cursor: {\n display: \"inline-block\",\n width: \"6px\",\n height: \"1em\",\n backgroundColor: tokens.colorNeutralForeground3,\n marginLeft: \"1px\",\n verticalAlign: \"text-bottom\",\n animationName: {\n \"0%, 100%\": { opacity: \"1\" },\n \"50%\": { opacity: \"0\" },\n },\n animationDuration: \"0.9s\",\n animationTimingFunction: \"step-end\",\n animationIterationCount: \"infinite\",\n },\n});\n\ninterface ThinkingIndicatorProps {\n isRetrying?: boolean;\n /** Override the cycling animation with a static status string. The animated icon is retained. */\n status?: string;\n /**\n * Override the pool of cycling words. Falls back to the default `thinkingMessages`\n * pool when omitted. Ignored while `isRetrying` is true (retry uses its own pool).\n */\n messages?: string[];\n}\n\nconst ThinkingIndicator: React.FC<ThinkingIndicatorProps> = ({ isRetrying = false, status, messages }) => {\n const styles = useStyles();\n const [displayText, setDisplayText] = useState(\"\");\n const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const msgIdxRef = useRef(0);\n const charIdxRef = useRef(0);\n\n useEffect(() => {\n const pool = isRetrying ? retryingMessages : (messages && messages.length > 0 ? messages : thinkingMessages);\n // Reset animation when mode switches\n msgIdxRef.current = 0;\n charIdxRef.current = 0;\n\n const tick = () => {\n const word = pool[msgIdxRef.current];\n\n if (charIdxRef.current < word.length) {\n charIdxRef.current += 1;\n setDisplayText(word.slice(0, charIdxRef.current));\n timerRef.current = setTimeout(tick, TYPING_SPEED);\n } else {\n // Finished typing the word — hold, then advance\n timerRef.current = setTimeout(() => {\n msgIdxRef.current = (msgIdxRef.current + 1) % pool.length;\n charIdxRef.current = 0;\n tick();\n }, HOLD_DURATION);\n }\n };\n\n tick();\n return () => clearTimeout(timerRef.current);\n }, [isRetrying, messages]);\n\n return (\n <div className={styles.root}>\n <Spinner size=\"tiny\" />\n <span className={styles.text}>\n {status ?? displayText}\n <span className={styles.cursor} />\n </span>\n </div>\n );\n};\n\nexport default ThinkingIndicator;\n","/**\n * Built-in task vocabulary for the thinking indicator's per-task word pools.\n *\n * A handler streams a `{ type: \"status\", name }` chunk to tell the indicator\n * which pool to cycle while it works. `name` is matched against these keys;\n * anything unrecognized falls back to the `text` pool.\n *\n * - `text` — default text-only response.\n * - `photo` — vision / image-reading responses.\n * - `file` — document / PDF responses.\n * - `voice` — audio transcription responses.\n */\nexport type CoralTaskType = \"text\" | \"photo\" | \"file\" | \"voice\";\n\nexport const DEFAULT_TASK_MESSAGES: Record<CoralTaskType, string[]> = {\n text: [\n \"Generating\",\n \"Thinking\",\n \"Optimizing\",\n \"Processing\",\n \"Analyzing\",\n \"Drafting\",\n \"Evaluating\",\n \"Computing\",\n \"Synthesizing\",\n \"Reviewing\",\n \"Refining\",\n ],\n photo: [\"Looking\", \"Examining\", \"Reading image\", \"Analyzing visuals\"],\n file: [\"Reading document\", \"Parsing\", \"Reviewing\", \"Scanning\"],\n voice: [\"Listening\", \"Transcribing\", \"Processing audio\"],\n};\n\n/**\n * Picks the thinking-indicator word pool for a streamed status name. If `name`\n * matches a built-in task type, its pool is used; otherwise the `text` pool is\n * the fallback. For bespoke copy, use the `thinkingStatus` prop on `<Chat>`.\n */\nexport function resolveTaskMessages(name?: string): string[] {\n if (name && name in DEFAULT_TASK_MESSAGES) {\n return DEFAULT_TASK_MESSAGES[name as CoralTaskType];\n }\n return DEFAULT_TASK_MESSAGES.text;\n}\n","import React from \"react\";\nimport { Body1, Button, makeStyles, mergeClasses, tokens } from \"@fluentui/react-components\";\nimport { ChatWarning20Regular } from \"@fluentui/react-icons\";\n\ninterface ChatCalloutProps {\n message: string;\n onRetry?: () => void;\n className?: string;\n}\n\nconst useStyles = makeStyles({\n root: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"8px\",\n padding: \"12px 12px\",\n borderRadius: tokens.borderRadiusXLarge,\n backgroundColor: tokens.colorNeutralBackground3,\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n color: tokens.colorNeutralForeground3,\n width: \"100%\",\n boxSizing: \"border-box\",\n margin: \"24px 0\",\n },\n left: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n },\n label: {\n fontFamily: \"var(--fontFamilyMonospace)\",\n },\n retryButton: {\n minWidth: 0,\n },\n});\n\nconst ChatCallout: React.FC<ChatCalloutProps> = ({ message, onRetry, className }) => {\n const styles = useStyles();\n\n return (\n <div className={mergeClasses(styles.root, className)}>\n <span className={styles.left}>\n <ChatWarning20Regular />\n <Body1 className={styles.label}>{message}</Body1>\n </span>\n {onRetry && (\n <Button\n onClick={onRetry}\n className={styles.retryButton}\n size=\"small\"\n appearance=\"primary\"\n >\n Retry\n </Button>\n )}\n </div>\n );\n};\n\nexport default ChatCallout;\n","import React, { useState, useEffect, useRef } from \"react\";\nimport { Body1, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { ChevronDown16Regular, ChevronRight16Regular } from \"@fluentui/react-icons\";\n\nexport interface ReasoningBlockProps {\n /** Full accumulated reasoning content. */\n content: string;\n /** True while the model is still streaming reasoning tokens. */\n isStreaming?: boolean;\n}\n\nconst useStyles = makeStyles({\n root: {\n display: \"flex\",\n flexDirection: \"column\",\n overflow: \"hidden\",\n margin: \"12px 0 40px 0\",\n },\n header: {\n display: \"flex\",\n alignItems: \"center\",\n padding: \"0\",\n cursor: \"pointer\",\n background: \"none\",\n border: \"none\",\n width: \"100%\",\n textAlign: \"left\",\n gap: \"8px\",\n },\n labelRow: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n minWidth: 0,\n },\n pulseContainer: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"16px\",\n height: \"16px\",\n },\n pulse: {\n flexShrink: 0,\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: tokens.colorNeutralForeground3,\n animationName: {\n \"0%, 100%\": { opacity: \"1\" },\n \"50%\": { opacity: \"0.2\" },\n },\n animationDuration: \"1.2s\",\n animationTimingFunction: \"ease-in-out\",\n animationIterationCount: \"infinite\",\n },\n pulseDone: {\n flexShrink: 0,\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: tokens.colorBrandForeground1,\n },\n label: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n marginBottom: \"2px\",\n },\n chevron: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n transition: \"transform 0.2s ease\",\n },\n chevronExpanded: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n transition: \"transform 0.2s ease\",\n transform: \"rotate(90deg)\",\n },\n expanded: {\n padding: \"16px 0 0 0\",\n marginLeft: \"22px\",\n fontSize: tokens.fontSizeBase300,\n color: tokens.colorNeutralForeground3,\n fontFamily: \"var(--fontFamilyMonospace)\",\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n // maxHeight: \"320px\",\n // overflowY: \"auto\",\n },\n});\n\nconst ReasoningBlock: React.FC<ReasoningBlockProps> = ({\n content,\n isStreaming = false,\n}) => {\n const styles = useStyles();\n const [expanded, setExpanded] = useState(false);\n const [duration, setDuration] = useState<number | null>(null);\n const startTimeRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (isStreaming) {\n startTimeRef.current = Date.now();\n setDuration(null);\n } else if (startTimeRef.current !== null) {\n setDuration(Math.round((Date.now() - startTimeRef.current) / 1000));\n startTimeRef.current = null;\n }\n }, [isStreaming]);\n\n const label = isStreaming\n ? \"Thinking\"\n : duration !== null\n ? `Thought for ${duration}s`\n : \"Thought\";\n\n return (\n <div className={styles.root}>\n <button className={styles.header} onClick={() => setExpanded((e) => !e)}>\n <div className={styles.labelRow}>\n <div className={styles.pulseContainer}>\n <span className={isStreaming ? styles.pulse : styles.pulseDone} />\n </div>\n <Body1 className={styles.label}>{label}</Body1>\n <ChevronRight16Regular\n className={expanded ? styles.chevronExpanded : styles.chevron}\n />\n </div>\n </button>\n\n {expanded && (\n <div className={styles.expanded}>{content}</div>\n )}\n </div>\n );\n};\n\nexport default ReasoningBlock;\n","import React, { useState } from \"react\";\nimport {\n Body1,\n Caption1,\n makeStyles,\n tokens,\n} from \"@fluentui/react-components\";\nimport {\n CheckboxCheckedFilled,\n CheckboxUncheckedRegular,\n ChevronRightRegular,\n SquareHintRegular,\n} from \"@fluentui/react-icons\";\nimport type { ChatTodo } from \"./Chat\";\n\nexport interface ChatTodoListProps {\n /** The current task plan. The whole list is replaced on each agent update. */\n todos: ChatTodo[];\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst useStyles = makeStyles({\n root: {\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n margin: \"12px 0\",\n borderRadius: \"var(--borderRadiusXLarge)\",\n backgroundColor: \"var(--colorNeutralBackgroundAlpha2)\",\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n overflow: \"hidden\",\n },\n header: {\n display: \"flex\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"10px 14px\",\n cursor: \"pointer\",\n background: \"none\",\n border: \"none\",\n width: \"100%\",\n textAlign: \"left\",\n },\n label: {\n color: tokens.colorNeutralForeground2,\n flexShrink: 0,\n },\n count: {\n color: tokens.colorNeutralForeground3,\n marginLeft: \"auto\",\n flexShrink: 0,\n },\n chevron: {\n color: tokens.colorNeutralForeground3,\n flexShrink: 0,\n fontSize: \"16px\",\n transition: \"transform 0.2s ease\",\n },\n chevronExpanded: {\n transform: \"rotate(90deg)\",\n },\n list: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"8px\",\n padding: \"2px 14px 14px 14px\",\n },\n item: {\n display: \"flex\",\n alignItems: \"flex-start\",\n gap: \"8px\",\n },\n iconCell: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"20px\",\n height: \"20px\",\n fontSize: \"20px\",\n flexShrink: 0,\n },\n pendingIcon: {\n color: tokens.colorNeutralForegroundDisabled,\n },\n activeIcon: {\n color: tokens.colorNeutralForeground2,\n },\n doneIcon: {\n color: tokens.colorPaletteSeafoamForeground2,\n },\n text: {\n minWidth: 0,\n wordBreak: \"break-word\",\n },\n pendingText: {\n color: tokens.colorNeutralForeground3,\n },\n activeText: {\n color: tokens.colorNeutralForeground1,\n fontWeight: tokens.fontWeightSemibold,\n },\n doneText: {\n color: tokens.colorNeutralForeground3,\n textDecorationLine: \"line-through\",\n },\n});\n\nconst ChatTodoList: React.FC<ChatTodoListProps> = ({\n todos,\n className,\n style,\n}) => {\n const styles = useStyles();\n\n const total = todos.length;\n const completed = todos.filter((t) => t.status === \"completed\").length;\n // The list stays open as the agent works — collapsing is the user's call,\n // never the chat's. Defaults open; the header toggle is the only thing that\n // changes it, so streaming todo updates can't make it flash open/closed.\n const [expanded, setExpanded] = useState(true);\n\n if (total === 0) return null;\n\n return (\n <div\n className={`${styles.root}${className ? ` ${className}` : \"\"}`}\n style={style}\n role=\"group\"\n aria-label={`Task plan, ${completed} of ${total} done`}\n >\n <button\n type=\"button\"\n className={styles.header}\n onClick={() => setExpanded((e) => !e)}\n aria-expanded={expanded}\n >\n <ChevronRightRegular\n className={`${styles.chevron}${expanded ? ` ${styles.chevronExpanded}` : \"\"}`}\n />\n <Body1 className={styles.label}>Tasks</Body1>\n <Caption1 className={styles.count}>\n {completed}/{total}\n </Caption1>\n </button>\n\n {expanded && (\n <div className={styles.list} role=\"list\">\n {todos.map((todo, index) => {\n const text =\n todo.status === \"in_progress\"\n ? (todo.activeForm ?? todo.content)\n : todo.content;\n const textClass =\n todo.status === \"completed\"\n ? styles.doneText\n : todo.status === \"in_progress\"\n ? styles.activeText\n : styles.pendingText;\n return (\n <div\n key={todo.id ?? `todo-${index}`}\n className={styles.item}\n role=\"listitem\"\n >\n <span className={styles.iconCell}>\n {todo.status === \"completed\" ? (\n <CheckboxCheckedFilled className={styles.doneIcon} />\n ) : todo.status === \"in_progress\" ? (\n <CheckboxUncheckedRegular className={styles.activeIcon} />\n ) : (\n <SquareHintRegular className={styles.pendingIcon} />\n )}\n </span>\n <Body1 className={`${styles.text} ${textClass}`}>{text}</Body1>\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n};\n\nexport default ChatTodoList;\n","import React, {\n useRef,\n useState,\n useEffect,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport { Body1, Button, Tag, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { Dismiss, Send, Stop } from \"@coral-ai/bundleicons\";\nimport { useChatContext } from \"./Chat.Context\";\nimport ChatAttachButton, { type ChatAttachType } from \"./Chat.AttachButton\";\nimport type { ChatAttachment } from \"./Chat\";\n\n// ---- Props ----\n\nexport interface ChatInputProps {\n /** Current input value. Optional inside Chat.Canvas — auto-wired from context. */\n value?: string;\n /** Change handler. Optional inside Chat.Canvas — auto-wired from context. */\n onChange?: (val: string) => void;\n /** Called on Enter. Optional inside Chat.Canvas — auto-wired to sendMessage. */\n onEnter?: () => void;\n placeholder?: string;\n /** Disabled state. */\n disabled?: boolean;\n style?: React.CSSProperties;\n /** Slot rendered at the left of the bottom toolbar. */\n actionsStart?: React.ReactNode;\n /** Slot rendered at the right of the bottom toolbar, just before Send/Stop. */\n actionsEnd?: React.ReactNode;\n /** Override attachments when used outside a Chat.Canvas. */\n attachments?: ChatAttachment[];\n /** Override remove handler when used outside a Chat.Canvas. */\n removeAttachment?: (id: string) => void;\n /**\n * Renders the `+` (Chat.AttachButton) menu before `actionsStart` content.\n * When omitted, falls back to the value in `useChatContext().allowedAttachments`\n * (set by Chat / Chat.Canvas via the `allowedAttachments` prop). When both are\n * undefined, no `+` button renders — current behavior preserved.\n */\n allowedAttachments?: ChatAttachType[];\n}\n\n// ---- Styles ----\n\nconst useStyles = makeStyles({\n wrapper: {\n width: \"100%\",\n margin: \"0 auto\",\n },\n card: {\n display: \"inline-flex\",\n flexDirection: \"column\",\n gap: \"8px\",\n alignItems: \"stretch\",\n width: \"100%\",\n padding: \"8px\",\n borderRadius: \"var(--borderRadiusXLarge)\",\n backgroundColor: \"var(--colorNeutralBackgroundAlpha2)\",\n transition: \"border-color 0.2s ease-in-out\",\n position: \"relative\",\n boxSizing: \"border-box\",\n overflow: \"hidden\",\n },\n cardFocused: {\n boxShadow: tokens.shadow28,\n },\n cardDisabled: {\n opacity: \"0.3\",\n pointerEvents: \"none\",\n },\n attachmentsRow: {\n display: \"flex\",\n gap: \"8px\",\n overflowX: \"auto\",\n padding: \"0 4px\",\n },\n attachmentItem: {\n position: \"relative\",\n flexShrink: 0,\n width: \"128px\",\n height: \"128px\",\n borderRadius: \"var(--borderRadiusMedium)\",\n overflow: \"hidden\",\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n backgroundColor: \"var(--colorNeutralBackground3)\",\n display: \"flex\",\n flexDirection: \"column\",\n },\n attachmentImage: {\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n },\n attachmentFile: {\n padding: \"12px\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"4px\",\n justifyContent: \"space-between\",\n },\n attachmentFileName: {\n wordBreak: \"break-all\",\n color: \"var(--colorNeutralForeground2)\",\n overflow: \"hidden\",\n maxHeight: \"36px\",\n lineHeight: \"1.2\",\n },\n attachmentDismiss: {\n position: \"absolute\",\n top: \"6px\",\n right: \"6px\",\n },\n textarea: {\n resize: \"none\",\n overflowY: \"auto\",\n height: \"auto\",\n minHeight: \"24px\",\n maxHeight: \"150px\",\n padding: \"8px\",\n backgroundColor: \"transparent\",\n border: \"none\",\n outline: \"none\",\n fontFamily: \"var(--fontFamilyBase)\",\n fontSize: \"var(--fontSizeBase300)\",\n fontWeight: \"var(--fontWeightRegular)\",\n color: \"var(--colorNeutralForeground1)\",\n lineHeight: \"1.5\",\n boxSizing: \"border-box\",\n width: \"100%\",\n },\n toolbar: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n maxHeight: \"32px\",\n },\n toolbarSide: {\n display: \"flex\",\n alignItems: \"center\",\n },\n focusBar: {\n position: \"absolute\",\n bottom: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"2px\",\n backgroundColor: \"var(--colorCompoundBrandStroke)\",\n transition: \"transform 0.2s ease-in-out\",\n textAlign: \"center\",\n },\n focusBarVisible: {\n transform: \"scaleX(1)\",\n },\n focusBarHidden: {\n transform: \"scaleX(0)\",\n },\n});\n\n// ---- Component ----\n\nconst ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(\n (\n {\n value: valueProp,\n onChange: onChangeProp,\n onEnter: onEnterProp,\n placeholder = \"Type a message...\",\n disabled: disabledProp,\n style,\n actionsStart,\n actionsEnd,\n attachments: attachmentsProp,\n removeAttachment: removeAttachmentProp,\n allowedAttachments: allowedAttachmentsProp,\n },\n ref,\n ) => {\n const styles = useStyles();\n const [isFocused, setIsFocused] = useState(false);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useImperativeHandle(ref, () => textareaRef.current as HTMLTextAreaElement);\n\n // ── Context wiring ────────────────────────────────────────────────────────\n const ctx = useChatContext();\n const isInsideCanvas = ctx.setInput !== undefined;\n const attachments = isInsideCanvas ? ctx.attachments : (attachmentsProp ?? []);\n const removeAttachment = isInsideCanvas ? ctx.removeAttachment : (removeAttachmentProp ?? (() => {}));\n const allowedAttachments = allowedAttachmentsProp ?? (isInsideCanvas ? ctx.allowedAttachments : undefined);\n\n const value = valueProp ?? (isInsideCanvas ? ctx.input : \"\");\n const onChange = onChangeProp ?? (isInsideCanvas ? ctx.setInput : () => {});\n const disabled = disabledProp ?? false;\n const onEnter =\n onEnterProp ??\n (isInsideCanvas\n ? () => {\n if (!ctx.isTyping) ctx.sendMessage();\n }\n : undefined);\n\n // ── Height reporting to Canvas (for scroll-button positioning) ────────────\n useEffect(() => {\n if (!isInsideCanvas) return;\n const el = containerRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n ctx.setInputHeight(el.offsetHeight);\n });\n ro.observe(el);\n ctx.setInputHeight(el.offsetHeight);\n return () => ro.disconnect();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isInsideCanvas]);\n\n // ── Auto-grow textarea ────────────────────────────────────────────────────\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;\n }\n }, [value]);\n\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => {\n el.style.height = \"auto\";\n el.style.height = `${el.scrollHeight}px`;\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n // ── Send / Stop (always present in Canvas mode) ───────────────────────────\n const sendStopButton = isInsideCanvas ? (\n ctx.isTyping ? (\n <Button\n appearance=\"transparent\"\n onClick={() => {\n ctx.shouldStopRef.current = true;\n ctx.onStop?.();\n }}\n icon={<Stop />}\n style={{ cursor: \"default\" }}\n />\n ) : (\n <Button\n appearance=\"transparent\"\n onClick={() => ctx.sendMessage()}\n icon={<Send />}\n disabled={!value.trim()}\n style={{ cursor: \"default\" }}\n />\n )\n ) : null;\n\n return (\n <div ref={containerRef} className={styles.wrapper} style={style}>\n <div\n className={`${styles.card}${isFocused ? ` ${styles.cardFocused}` : \"\"}${disabled ? ` ${styles.cardDisabled}` : \"\"}`}\n style={{\n border: isFocused\n ? `1px solid ${tokens.colorNeutralStroke1}`\n : `1px solid ${tokens.colorNeutralStroke2}`,\n }}\n >\n {attachments.length > 0 && (\n <div className={styles.attachmentsRow}>\n {attachments.map((a) => {\n const ext = a.file.name.split(\".\").pop()?.toUpperCase() ?? \"FILE\";\n return (\n <div key={a.id} className={styles.attachmentItem}>\n {a.preview ? (\n <img\n src={a.preview}\n alt={a.file.name}\n className={styles.attachmentImage}\n />\n ) : (\n <div className={styles.attachmentFile}>\n <Body1 className={styles.attachmentFileName}>\n {a.file.name}\n </Body1>\n <Tag appearance=\"outline\" size=\"small\">\n {ext}\n </Tag>\n </div>\n )}\n <Button\n icon={<Dismiss />}\n size=\"small\"\n onClick={() => removeAttachment(a.id)}\n className={styles.attachmentDismiss}\n />\n </div>\n );\n })}\n </div>\n )}\n\n <textarea\n disabled={disabled}\n ref={textareaRef}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n onEnter?.();\n }\n }}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n placeholder={placeholder}\n rows={1}\n className={styles.textarea}\n />\n\n <div className={styles.toolbar}>\n <div className={styles.toolbarSide}>\n {allowedAttachments && allowedAttachments.length > 0 && (\n <ChatAttachButton types={allowedAttachments} />\n )}\n {actionsStart}\n </div>\n <div className={styles.toolbarSide}>\n {actionsEnd}\n {sendStopButton}\n </div>\n </div>\n\n <span\n className={`${styles.focusBar} ${isFocused ? styles.focusBarVisible : styles.focusBarHidden}`}\n />\n </div>\n </div>\n );\n },\n);\n\nexport default ChatInput;\n","import React, { useRef } from \"react\";\nimport {\n Button,\n Menu,\n MenuTrigger,\n MenuPopover,\n MenuList,\n MenuItem,\n} from \"@fluentui/react-components\";\nimport { Add, DocumentAdd, ImageAdd } from \"@coral-ai/bundleicons\";\nimport { useChatContext } from \"./Chat.Context\";\n\nexport type ChatAttachType = \"files\" | \"photos\";\n\nexport interface ChatAttachButtonProps {\n /**\n * Which entries to render in the `+` menu. Order in the array is the order\n * shown in the menu. Defaults to `['files', 'photos']`.\n */\n types?: ChatAttachType[];\n}\n\n/**\n * The \"+\" button rendered by default to the left of the chat input toolbar.\n *\n * Opens a Fluent menu with \"Add files\" / \"Add photos\" entries (subset\n * controlled by `types`). Selecting one opens the native OS file picker via a\n * hidden `<input type=\"file\">` and pushes the resulting `File[]` through\n * `addAttachments` on `useChatContext`. From there the existing chat pipeline\n * stages the files, renders preview tiles above the textarea, and hands the\n * raw `File[]` to the agent handler on send.\n *\n * Engineers don't typically render this directly — `<Chat allowedAttachments>`\n * does it for them. It's exported so the same component can be dropped into\n * `actionsStart` for fully custom layouts.\n */\nconst ChatAttachButton: React.FC<ChatAttachButtonProps> = ({\n types = [\"files\", \"photos\"],\n}) => {\n const { addAttachments } = useChatContext();\n const fileRef = useRef<HTMLInputElement>(null);\n const photoRef = useRef<HTMLInputElement>(null);\n\n const showFiles = types.includes(\"files\");\n const showPhotos = types.includes(\"photos\");\n\n return (\n <>\n {showFiles && (\n <input\n ref={fileRef}\n type=\"file\"\n hidden\n multiple\n onChange={(e) => {\n if (e.target.files) addAttachments([...e.target.files]);\n e.target.value = \"\";\n }}\n />\n )}\n {showPhotos && (\n <input\n ref={photoRef}\n type=\"file\"\n hidden\n multiple\n accept=\"image/*\"\n onChange={(e) => {\n if (e.target.files) addAttachments([...e.target.files]);\n e.target.value = \"\";\n }}\n />\n )}\n <Menu>\n <MenuTrigger>\n <Button appearance=\"subtle\" icon={<Add />} />\n </MenuTrigger>\n <MenuPopover>\n <MenuList>\n {types.map((t) =>\n t === \"files\" ? (\n <MenuItem\n key=\"files\"\n icon={<DocumentAdd />}\n onClick={() => fileRef.current?.click()}\n >\n Add files\n </MenuItem>\n ) : (\n <MenuItem\n key=\"photos\"\n icon={<ImageAdd />}\n onClick={() => photoRef.current?.click()}\n >\n Add photos\n </MenuItem>\n ),\n )}\n </MenuList>\n </MenuPopover>\n </Menu>\n </>\n );\n};\n\nexport default ChatAttachButton;\n","import React from \"react\";\nimport { Body1, Body1Strong, Body2, Button, Caption1, makeStyles, tokens } from \"@fluentui/react-components\";\nimport { useChatContext } from \"./Chat.Context\";\nimport type { ApprovalOption, ChatApprovalRequest } from \"./Chat\";\n\nexport interface ChatApprovalProps {\n /**\n * Override the approval request to render. Defaults to `pendingApproval`\n * from context. Useful for storybook / standalone previews.\n */\n approval?: ChatApprovalRequest | null;\n /**\n * Override the resolver. Defaults to `resolveApproval` from context.\n */\n onSelect?: (optionId: string) => void;\n /** Disable all buttons. Defaults to false. */\n disabled?: boolean;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst useStyles = makeStyles({\n root: {\n width: \"100%\",\n boxSizing: \"border-box\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"24px\",\n padding: \"12px 14px\",\n marginBottom: \"8px\",\n borderRadius: \"var(--borderRadiusXLarge)\",\n backgroundColor: \"var(--colorNeutralBackgroundAlpha2)\",\n border: `1px solid ${tokens.colorNeutralStroke2}`,\n },\n header: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"2px\",\n },\n description: {\n color: tokens.colorNeutralForeground3,\n },\n optionsRow: {\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"6px\",\n\n },\n optionsColumn: {\n display: \"flex\",\n flexDirection: \"column\",\n gap: \"6px\",\n\n },\n optionStacked: {\n justifyContent: \"flex-start\",\n },\n hint: {\n color: tokens.colorNeutralForeground3,\n // fontStyle: \"italic\",\n },\n});\n\nfunction shouldStackVertically(options: ApprovalOption[]): boolean {\n if (options.length > 3) return true;\n const totalLength = options.reduce((sum, o) => sum + o.label.length, 0);\n if (totalLength > 40) return true;\n if (options.some((o) => !!o.description)) return true;\n return false;\n}\n\nconst ChatApproval: React.FC<ChatApprovalProps> = ({\n approval: approvalProp,\n onSelect: onSelectProp,\n disabled = false,\n className,\n style,\n}) => {\n const styles = useStyles();\n const ctx = useChatContext();\n const approval = approvalProp ?? ctx.pendingApproval;\n if (!approval) return null;\n\n const onSelect = onSelectProp ?? ((optionId: string) => ctx.resolveApproval(approval.id, optionId));\n const answeredId = approval.answer?.optionId;\n const isAnswered = answeredId !== undefined;\n const awaitingFreeform =\n ctx.awaitingFreeformApproval?.approvalId === approval.id\n ? ctx.awaitingFreeformApproval\n : null;\n const stack = shouldStackVertically(approval.options);\n\n return (\n <div\n className={`${styles.root}${className ? ` ${className}` : \"\"}`}\n style={style}\n role=\"group\"\n aria-label={approval.question}\n >\n <div className={styles.header}>\n <Body1Strong>{approval.question}</Body1Strong>\n {approval.description && (\n <Body1 className={styles.description}>{approval.description}</Body1>\n )}\n </div>\n <div className={stack ? styles.optionsColumn : styles.optionsRow}>\n {approval.options.map((opt) => {\n const selected =\n answeredId === opt.id || awaitingFreeform?.optionId === opt.id;\n const baseAppearance = opt.appearance ?? (opt.freeform ? \"subtle\" : \"outline\");\n const appearance = selected ? \"primary\" : baseAppearance;\n return (\n <Button\n key={opt.id}\n appearance={appearance}\n disabled={disabled || isAnswered}\n onClick={() => onSelect(opt.id)}\n className={stack ? styles.optionStacked : undefined}\n style={{\n height:'40px'\n }}\n >\n {opt.label}\n </Button>\n );\n })}\n </div>\n {awaitingFreeform && !isAnswered && (\n <Caption1 className={styles.hint}>\n Type your reply in the message box below.\n </Caption1>\n )}\n </div>\n );\n};\n\nexport default ChatApproval;\n","import type { AgentHandler, ChatChunk } from \"./Chat\";\nimport { fileToBase64 } from \"./fileToBase64\";\n\ntype CreateHandlerOptions = {\n /** Your backend endpoint. Receives POST { input, history, attachments }. */\n endpoint: string;\n /** Additional headers (e.g. Authorization). */\n headers?: HeadersInit;\n};\n\n/**\n * Wraps a fetch endpoint into an AgentHandler.\n *\n * On send it POSTs JSON to `endpoint`:\n *\n * ```json\n * {\n * \"input\": \"the user's latest message\",\n * \"history\": [{ \"role\": \"user\", \"content\": \"...\" }],\n * \"attachments\": [{ \"name\": \"cat.jpg\", \"mediaType\": \"image/jpeg\", \"data\": \"<base64>\" }]\n * }\n * ```\n *\n * Attached files are base64-encoded with `fileToBase64` (same encoding as\n * Coral's built-in `api` handler); `attachments` is `[]` when none are staged.\n *\n * The endpoint should stream newline-delimited responses where each line is either:\n * - A plain text chunk (yielded as a string)\n * - A JSON-encoded ChatChunk object (e.g. `{\"type\":\"reasoning\",\"content\":\"...\"}`)\n * - An SSE `data: ...` line (the `data: ` prefix is stripped automatically)\n * - `[DONE]` to signal end-of-stream\n *\n * @example\n * <Chat onSendMessage={createHandler({ endpoint: '/api/chat' })} />\n */\nexport function createHandler({ endpoint, headers }: CreateHandlerOptions): AgentHandler {\n return async function* (input, history, files) {\n const attachments = await Promise.all(\n files.map(async (file) => ({\n name: file.name,\n mediaType: file.type,\n data: await fileToBase64(file),\n })),\n );\n\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify({ input, history, attachments }),\n });\n\n if (!res.ok || !res.body) {\n throw Object.assign(new Error(`${res.status} ${res.statusText}`), {\n status: res.status,\n statusText: res.statusText,\n });\n }\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\"; // keep any incomplete final line\n\n for (const line of lines) {\n // Strip SSE prefix\n const text = line.startsWith(\"data: \") ? line.slice(6) : line;\n if (!text || text === \"[DONE]\") continue;\n\n try {\n const chunk = JSON.parse(text) as ChatChunk;\n yield chunk;\n } catch {\n // Plain text line\n yield text;\n }\n }\n }\n };\n}\n","import type { CoralChartSpec } from \"@coral-ai/charts\";\nimport type {\n AgentHandler,\n ChatChunk,\n ChatMessage,\n ChatTodo,\n ChatApprovalRequest,\n ApprovalOption,\n} from \"./Chat\";\n\n/**\n * Model-agnostic agent tool-use runner.\n *\n * `createAgentHandler` turns a provider-neutral `callModel` adapter into a\n * Coral `AgentHandler`. Coral owns the tool-use loop, the built-in\n * `update_todos` / `request_approval` tools, and the approval pause/resume\n * bridge. The engineer owns exactly one function — `callModel` — which is the\n * only provider-specific code (Claude, Azure OpenAI, …).\n */\n\n// ---- Neutral types ----------------------------------------------------------\n\n/** A tool definition. `parameters` is standard JSON Schema for the tool input. */\nexport type ToolSpec = {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n};\n\n/** A tool invocation emitted by the model. */\nexport type ToolCall = { id: string; name: string; input: unknown };\n\n/**\n * One message in the neutral agent conversation. `raw` on assistant messages\n * is an opaque passthrough for provider-native content blocks (e.g. Claude\n * `thinking` + `tool_use` blocks that must replay verbatim across the loop) —\n * the runner never inspects it; the adapter prefers it when rebuilding.\n */\nexport type AgentMessage =\n | { role: \"user\"; content: string }\n | { role: \"assistant\"; content: string; toolCalls?: ToolCall[]; raw?: unknown }\n | { role: \"tool\"; toolCallId: string; content: string };\n\n/** What the runner hands the `callModel` adapter for each model call. */\nexport type ModelRequest = {\n system?: string;\n messages: AgentMessage[];\n tools: ToolSpec[];\n /** Present only on the first model call of a turn. */\n attachments?: File[];\n};\n\n/** A streamed event from the `callModel` adapter. */\nexport type ModelStreamEvent =\n | { type: \"text\"; delta: string }\n | { type: \"reasoning\"; delta: string }\n | { type: \"tool_call\"; toolCall: ToolCall }\n /** Opaque provider-native representation of the assistant turn, for replay. */\n | { type: \"raw\"; raw: unknown };\n\n/** The one function an engineer implements per provider. */\nexport type CallModel = (req: ModelRequest) => AsyncIterable<ModelStreamEvent>;\n\n/** Result of executing a custom tool — fed back to the model. */\nexport type ToolResult = { content: string };\n\n/** A custom tool the engineer registers alongside the built-ins. */\nexport type AgentTool = {\n spec: ToolSpec;\n execute: (input: unknown) => ToolResult | Promise<ToolResult>;\n};\n\n/** Paused-agent state, stashed while waiting for an approval answer. */\nexport type AgentSnapshot = {\n messages: AgentMessage[];\n pendingToolCallId: string;\n};\n\n/**\n * Where paused agent state is stored between the approval request and the\n * user's answer. Defaults to an in-memory Map — for a server handler that\n * spans processes, supply a Redis/db-backed implementation.\n */\nexport type AgentSessionStore = {\n get(id: string): AgentSnapshot | undefined | Promise<AgentSnapshot | undefined>;\n set(id: string, snap: AgentSnapshot): void | Promise<void>;\n delete(id: string): void | Promise<void>;\n};\n\n// ---- Built-in tool specs ----------------------------------------------------\n\n/** Built-in tool: render / update the inline task checklist. */\nexport const UPDATE_TODOS_TOOL: ToolSpec = {\n name: \"update_todos\",\n description:\n \"Display or update the multi-step task plan shown to the user as an inline \" +\n \"checklist. Call this when you begin a task that takes 3 or more distinct \" +\n \"steps, and again every time a step changes status. Always send the COMPLETE \" +\n \"list of todos — it replaces the previous one. Keep exactly one item \" +\n \"'in_progress' at a time.\",\n parameters: {\n type: \"object\",\n properties: {\n todos: {\n type: \"array\",\n description: \"The full task list, in order.\",\n items: {\n type: \"object\",\n properties: {\n content: {\n type: \"string\",\n description: \"Imperative title, e.g. 'Optimize images'.\",\n },\n activeForm: {\n type: \"string\",\n description:\n \"Present-tense title shown while this step is in progress, \" +\n \"e.g. 'Optimizing images'.\",\n },\n status: {\n type: \"string\",\n enum: [\"pending\", \"in_progress\", \"completed\"],\n },\n },\n required: [\"content\", \"status\"],\n },\n },\n },\n required: [\"todos\"],\n },\n};\n\n/** Built-in tool: pause and ask the user to approve / choose before continuing. */\nexport const REQUEST_APPROVAL_TOOL: ToolSpec = {\n name: \"request_approval\",\n description:\n \"Pause and ask the user to approve an action or choose between options \" +\n \"before continuing. The conversation halts until the user responds — their \" +\n \"choice comes back as this tool's result. Use this before any consequential \" +\n \"or irreversible action (deleting, sending, purchasing, etc).\",\n parameters: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question or action to confirm.\",\n },\n description: {\n type: \"string\",\n description: \"Optional extra context shown below the question.\",\n },\n options: {\n type: \"array\",\n description: \"The choices offered to the user.\",\n items: {\n type: \"object\",\n properties: {\n id: { type: \"string\" },\n label: { type: \"string\" },\n description: { type: \"string\" },\n freeform: {\n type: \"boolean\",\n description:\n \"If true, choosing this option lets the user type a free-text \" +\n \"reply instead of a canned choice.\",\n },\n },\n required: [\"id\", \"label\"],\n },\n },\n },\n required: [\"question\", \"options\"],\n },\n};\n\n/** Built-in tool: render a chart inline as part of the assistant message. */\nexport const RENDER_CHART_TOOL: ToolSpec = {\n name: \"render_chart\",\n description:\n \"Render a chart inline in the assistant message. Call this when a \" +\n \"visualization (bar or line) communicates the data more clearly than \" +\n \"prose or a table. The chart appears above your text — refer to it \" +\n \"naturally (\\\"as the chart above shows…\\\") and do NOT also produce ASCII \" +\n \"charts or code blocks for the same data. May be called multiple times \" +\n \"in a turn to render multiple charts.\",\n parameters: {\n type: \"object\",\n properties: {\n kind: {\n type: \"string\",\n enum: [\"bar\", \"line\"],\n description: \"Use 'bar' for categorical comparisons, 'line' for trends over an ordered axis.\",\n },\n title: { type: \"string\", description: \"Title shown above the chart.\" },\n xKey: {\n type: \"string\",\n description: \"Key in each `data` row that supplies the x-axis label.\",\n },\n series: {\n type: \"array\",\n description: \"One entry per data series (one bar group / one line).\",\n items: {\n type: \"object\",\n properties: {\n dataKey: {\n type: \"string\",\n description: \"Key in each `data` row holding this series' numeric value.\",\n },\n label: {\n type: \"string\",\n description: \"Display label shown in the legend and tooltip.\",\n },\n },\n required: [\"dataKey\", \"label\"],\n },\n },\n data: {\n type: \"array\",\n description:\n \"Rows of data containing the xKey and every series' dataKey. \" +\n \"Example: `[{ quarter: 'Q1', alice: 92, bob: 78 }, …]`.\",\n items: { type: \"object\" },\n },\n },\n required: [\"kind\", \"title\", \"xKey\", \"series\", \"data\"],\n },\n};\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction createMemoryStore(): AgentSessionStore {\n const map = new Map<string, AgentSnapshot>();\n return {\n get: (id) => map.get(id),\n set: (id, snap) => {\n map.set(id, snap);\n },\n delete: (id) => {\n map.delete(id);\n },\n };\n}\n\n/** Coral message history → neutral agent messages (system messages dropped). */\nfunction historyToAgentMessages(history: ChatMessage[]): AgentMessage[] {\n const out: AgentMessage[] = [];\n for (const m of history) {\n if (m.role === \"user\") out.push({ role: \"user\", content: m.content });\n else if (m.role === \"assistant\") out.push({ role: \"assistant\", content: m.content });\n }\n return out;\n}\n\n/** Coerce a model-supplied `update_todos` input into ChatTodo[]. */\nfunction extractTodos(input: unknown): ChatTodo[] {\n const todos = (input as { todos?: unknown } | null)?.todos;\n if (!Array.isArray(todos)) return [];\n return todos.map((t, i): ChatTodo => {\n const o = (t ?? {}) as Record<string, unknown>;\n return {\n id: typeof o.id === \"string\" ? o.id : `todo-${i}`,\n content: String(o.content ?? \"\"),\n activeForm: typeof o.activeForm === \"string\" ? o.activeForm : undefined,\n status:\n o.status === \"in_progress\" || o.status === \"completed\"\n ? o.status\n : \"pending\",\n };\n });\n}\n\n/** Coerce a model-supplied `render_chart` input into a CoralChartSpec. */\nfunction buildChartSpec(input: unknown): CoralChartSpec | null {\n const o = (input ?? {}) as Record<string, unknown>;\n const kind = o.kind === \"line\" ? \"line\" : \"bar\";\n const title = typeof o.title === \"string\" ? o.title : \"\";\n const xKey = typeof o.xKey === \"string\" ? o.xKey : \"\";\n const rawSeries = Array.isArray(o.series) ? o.series : [];\n const series = rawSeries\n .map((s, i) => {\n const obj = (s ?? {}) as Record<string, unknown>;\n const dataKey = typeof obj.dataKey === \"string\" ? obj.dataKey : \"\";\n const label = typeof obj.label === \"string\" ? obj.label : dataKey || `series-${i}`;\n return dataKey ? { dataKey, label } : null;\n })\n .filter((s): s is { dataKey: string; label: string } => s !== null);\n const data = Array.isArray(o.data)\n ? (o.data.filter(\n (r) => r && typeof r === \"object\",\n ) as Array<Record<string, string | number>>)\n : [];\n if (!xKey || series.length === 0 || data.length === 0) return null;\n return { kind, title, xKey, series, data };\n}\n\n/** Coerce a model-supplied `request_approval` input into a ChatApprovalRequest. */\nfunction buildApproval(tc: ToolCall): ChatApprovalRequest {\n const input = (tc.input ?? {}) as Record<string, unknown>;\n const rawOptions = Array.isArray(input.options) ? input.options : [];\n const options: ApprovalOption[] = rawOptions.map((o, i) => {\n const obj = (o ?? {}) as Record<string, unknown>;\n return {\n id: typeof obj.id === \"string\" ? obj.id : `opt-${i}`,\n label: String(obj.label ?? `Option ${i + 1}`),\n description: typeof obj.description === \"string\" ? obj.description : undefined,\n freeform: obj.freeform === true ? true : undefined,\n };\n });\n return {\n // The tool-call id is the approval id — Coral round-trips it as\n // metadata.approvalId, which is the session-store key on resume.\n id: tc.id,\n question: String(input.question ?? \"Approve?\"),\n description:\n typeof input.description === \"string\" ? input.description : undefined,\n options,\n };\n}\n\n// ---- The runner -------------------------------------------------------------\n\nexport type CreateAgentHandlerOptions = {\n /** Provider adapter — the only provider-specific code. */\n callModel: CallModel;\n /** Base system prompt. Merged with any `systemPrompt` Coral injects. */\n system?: string;\n /** Custom tools, registered alongside the built-in update_todos / request_approval. */\n tools?: AgentTool[];\n /** Max tool-loop iterations per turn. Default 8. */\n maxSteps?: number;\n /** Where paused-agent state lives. Default: in-memory Map. */\n sessionStore?: AgentSessionStore;\n};\n\n/**\n * Builds a Coral `AgentHandler` that runs a provider-agnostic tool-use loop.\n *\n * @example\n * <Chat onSendMessage={createAgentHandler({ callModel: claudeCallModel })} />\n */\nexport function createAgentHandler(options: CreateAgentHandlerOptions): AgentHandler {\n const { callModel, system, tools = [], maxSteps = 8 } = options;\n const store = options.sessionStore ?? createMemoryStore();\n const customByName = new Map(tools.map((t) => [t.spec.name, t]));\n const toolSpecs: ToolSpec[] = [\n UPDATE_TODOS_TOOL,\n REQUEST_APPROVAL_TOOL,\n RENDER_CHART_TOOL,\n ...tools.map((t) => t.spec),\n ];\n\n return async function* (\n _input: string,\n history: ChatMessage[],\n attachments: File[],\n ): AsyncGenerator<ChatChunk> {\n const sysFromHistory = history\n .filter((m) => m.role === \"system\")\n .map((m) => m.content);\n const effectiveSystem =\n [system, ...sysFromHistory].filter(Boolean).join(\"\\n\\n\") || undefined;\n\n // --- A. Resume an approval, or start a fresh turn ---\n const last = history[history.length - 1];\n let messages: AgentMessage[];\n let firstCallAttachments: File[] | undefined;\n\n const resumeId =\n last?.role === \"user\" &&\n last.type === \"approval_response\" &&\n typeof last.metadata?.approvalId === \"string\"\n ? (last.metadata.approvalId as string)\n : undefined;\n const snapshot = resumeId ? await store.get(resumeId) : undefined;\n\n if (resumeId && snapshot) {\n await store.delete(resumeId);\n const meta = last!.metadata as Record<string, unknown>;\n const answer =\n (typeof meta.text === \"string\" && meta.text) ||\n (typeof meta.label === \"string\" && meta.label) ||\n last!.content;\n messages = [\n ...snapshot.messages,\n {\n role: \"tool\",\n toolCallId: snapshot.pendingToolCallId,\n content: `The user chose: ${answer}`,\n },\n ];\n } else {\n // Coral appends the new user message to history before calling the\n // handler, so converting history is enough — don't re-append `input`.\n messages = historyToAgentMessages(history);\n firstCallAttachments = attachments.length > 0 ? attachments : undefined;\n }\n\n // --- B. Tool-use loop ---\n for (let step = 0; step < maxSteps; step++) {\n const events = callModel({\n system: effectiveSystem,\n messages,\n tools: toolSpecs,\n attachments: step === 0 ? firstCallAttachments : undefined,\n });\n\n let assistantText = \"\";\n let assistantRaw: unknown;\n const toolCalls: ToolCall[] = [];\n\n for await (const ev of events) {\n if (ev.type === \"text\") {\n assistantText += ev.delta;\n yield ev.delta;\n } else if (ev.type === \"reasoning\") {\n yield { type: \"reasoning\", content: ev.delta };\n } else if (ev.type === \"tool_call\") {\n toolCalls.push(ev.toolCall);\n } else if (ev.type === \"raw\") {\n assistantRaw = ev.raw;\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: assistantText,\n ...(toolCalls.length > 0 ? { toolCalls } : {}),\n ...(assistantRaw !== undefined ? { raw: assistantRaw } : {}),\n });\n\n // No tool calls — the model gave its final answer.\n if (toolCalls.length === 0) return;\n\n for (const tc of toolCalls) {\n if (tc.name === UPDATE_TODOS_TOOL.name) {\n yield { type: \"todos\", todos: extractTodos(tc.input) };\n messages.push({\n role: \"tool\",\n toolCallId: tc.id,\n content: \"Task list updated and shown to the user.\",\n });\n } else if (tc.name === REQUEST_APPROVAL_TOOL.name) {\n yield { type: \"approval\", approval: buildApproval(tc) };\n // Pause: stash state keyed by the tool-call id and end the turn.\n // It resumes when the user answers (see the resume branch above).\n await store.set(tc.id, { messages, pendingToolCallId: tc.id });\n return;\n } else if (tc.name === RENDER_CHART_TOOL.name) {\n const spec = buildChartSpec(tc.input);\n if (spec) {\n yield { type: \"chart\", spec };\n messages.push({\n role: \"tool\",\n toolCallId: tc.id,\n content: \"Chart rendered and shown to the user above your text.\",\n });\n } else {\n messages.push({\n role: \"tool\",\n toolCallId: tc.id,\n content:\n \"Error: chart spec was invalid. Need non-empty `xKey`, \" +\n \"at least one entry in `series`, and at least one row in `data`.\",\n });\n }\n } else {\n const tool = customByName.get(tc.name);\n let content: string;\n if (!tool) {\n content = `Error: unknown tool \"${tc.name}\".`;\n } else {\n try {\n content = (await tool.execute(tc.input)).content;\n } catch (err) {\n content = `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n }\n messages.push({ role: \"tool\", toolCallId: tc.id, content });\n }\n }\n }\n\n yield \"\\n\\n_(Reached the tool-step limit for this turn.)_\";\n };\n}\n","import * as React from \"react\";\nimport type { ChatMessage } from \"./Chat\";\n\n/**\n * A stored conversation. Consumers typically persist this shape via the\n * adapter they pass to `ChatThreadsProvider`.\n */\nexport interface ChatThread {\n id: string;\n title: string;\n messages: ChatMessage[];\n createdAt?: number;\n updatedAt?: number;\n}\n\n/**\n * Storage seam. Implement this against your backend (REST, IndexedDB,\n * Firestore, etc.). The provider handles in-memory state so UI updates are\n * synchronous; your adapter only needs to persist.\n */\nexport interface ChatThreadsAdapter {\n list(): Promise<ChatThread[]> | ChatThread[];\n get?(id: string): Promise<ChatThread | undefined> | ChatThread | undefined;\n create(initial?: Partial<ChatThread>): Promise<ChatThread> | ChatThread;\n save(thread: ChatThread): Promise<void> | void;\n rename(id: string, newTitle: string): Promise<void> | void;\n remove(id: string): Promise<void> | void;\n}\n\nexport interface ChatThreadsContextValue {\n threads: ChatThread[];\n activeThreadId?: string;\n activeThread?: ChatThread;\n setActiveThreadId: (id: string | undefined) => void;\n createThread: (initial?: Partial<ChatThread>) => Promise<ChatThread>;\n renameThread: (id: string, newTitle: string) => Promise<void>;\n removeThread: (id: string) => Promise<void>;\n updateThreadMessages: (id: string, messages: ChatMessage[]) => void;\n isLoading: boolean;\n}\n\nconst ChatThreadsContext = React.createContext<ChatThreadsContextValue | null>(\n null,\n);\n\nexport function useChatThreads(): ChatThreadsContextValue {\n const value = React.useContext(ChatThreadsContext);\n if (!value) {\n throw new Error(\n \"useChatThreads must be used inside <ChatThreadsProvider>.\",\n );\n }\n return value;\n}\n\n/** Default adapter — holds threads in a module-less closure. Use for demos or unit tests. */\nexport function createMemoryThreadsAdapter(\n initialThreads: ChatThread[] = [],\n): ChatThreadsAdapter {\n let threads: ChatThread[] = [...initialThreads];\n return {\n list: () => threads,\n get: (id) => threads.find((t) => t.id === id),\n create: (initial) => {\n const thread: ChatThread = {\n id: initial?.id ?? crypto.randomUUID(),\n title: initial?.title ?? \"New chat\",\n messages: initial?.messages ?? [],\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n threads = [thread, ...threads];\n return thread;\n },\n save: (thread) => {\n const idx = threads.findIndex((t) => t.id === thread.id);\n const next: ChatThread = { ...thread, updatedAt: Date.now() };\n threads = idx >= 0\n ? threads.map((t, i) => (i === idx ? next : t))\n : [next, ...threads];\n },\n rename: (id, newTitle) => {\n threads = threads.map((t) =>\n t.id === id ? { ...t, title: newTitle, updatedAt: Date.now() } : t,\n );\n },\n remove: (id) => {\n threads = threads.filter((t) => t.id !== id);\n },\n };\n}\n\nexport interface ChatThreadsProviderProps {\n /** Storage adapter. Defaults to an in-memory adapter if omitted. */\n adapter?: ChatThreadsAdapter;\n /** Controlled active thread id. */\n activeThreadId?: string;\n /** Uncontrolled initial active thread id. */\n defaultActiveThreadId?: string;\n /** Fired when the active thread changes (both controlled and uncontrolled). */\n onActiveThreadChange?: (id: string | undefined) => void;\n children?: React.ReactNode;\n}\n\nexport function ChatThreadsProvider({\n adapter: providedAdapter,\n activeThreadId: controlledId,\n defaultActiveThreadId,\n onActiveThreadChange,\n children,\n}: ChatThreadsProviderProps) {\n const adapter = React.useMemo(\n () => providedAdapter ?? createMemoryThreadsAdapter(),\n [providedAdapter],\n );\n\n const [threads, setThreads] = React.useState<ChatThread[]>([]);\n const [uncontrolledId, setUncontrolledId] = React.useState<string | undefined>(\n defaultActiveThreadId,\n );\n const [isLoading, setIsLoading] = React.useState(true);\n\n const isControlled = controlledId !== undefined;\n const activeThreadId = isControlled ? controlledId : uncontrolledId;\n\n const setActiveThreadId = React.useCallback(\n (id: string | undefined) => {\n if (!isControlled) setUncontrolledId(id);\n onActiveThreadChange?.(id);\n },\n [isControlled, onActiveThreadChange],\n );\n\n React.useEffect(() => {\n let cancelled = false;\n (async () => {\n setIsLoading(true);\n const result = await adapter.list();\n if (cancelled) return;\n setThreads(result);\n setIsLoading(false);\n })();\n return () => {\n cancelled = true;\n };\n }, [adapter]);\n\n const createThread = React.useCallback(\n async (initial?: Partial<ChatThread>) => {\n const thread = await adapter.create(initial);\n setThreads((prev) => [thread, ...prev.filter((t) => t.id !== thread.id)]);\n return thread;\n },\n [adapter],\n );\n\n const renameThread = React.useCallback(\n async (id: string, newTitle: string) => {\n await adapter.rename(id, newTitle);\n setThreads((prev) =>\n prev.map((t) =>\n t.id === id ? { ...t, title: newTitle, updatedAt: Date.now() } : t,\n ),\n );\n },\n [adapter],\n );\n\n const removeThread = React.useCallback(\n async (id: string) => {\n await adapter.remove(id);\n setThreads((prev) => prev.filter((t) => t.id !== id));\n if (activeThreadId === id) setActiveThreadId(undefined);\n },\n [adapter, activeThreadId, setActiveThreadId],\n );\n\n const threadsRef = React.useRef(threads);\n threadsRef.current = threads;\n\n const updateThreadMessages = React.useCallback(\n (id: string, messages: ChatMessage[]) => {\n const existing = threadsRef.current.find((t) => t.id === id);\n if (!existing) return;\n const next: ChatThread = {\n ...existing,\n messages,\n updatedAt: Date.now(),\n };\n setThreads((prev) => prev.map((t) => (t.id === id ? next : t)));\n void adapter.save(next);\n },\n [adapter],\n );\n\n const activeThread = React.useMemo(\n () => threads.find((t) => t.id === activeThreadId),\n [threads, activeThreadId],\n );\n\n const value = React.useMemo<ChatThreadsContextValue>(\n () => ({\n threads,\n activeThreadId,\n activeThread,\n setActiveThreadId,\n createThread,\n renameThread,\n removeThread,\n updateThreadMessages,\n isLoading,\n }),\n [\n threads,\n activeThreadId,\n activeThread,\n setActiveThreadId,\n createThread,\n renameThread,\n removeThread,\n updateThreadMessages,\n isLoading,\n ],\n );\n\n return (\n <ChatThreadsContext.Provider value={value}>\n {children}\n </ChatThreadsContext.Provider>\n );\n}\n","import _ChatRoot from \"./Chat\";\nimport _ChatCanvas from \"./Chat.Canvas\";\nimport _ChatMessages from \"./Chat.Messages\";\nimport _ChatInput from \"./Chat.Input\";\nimport _ChatError, { normalizeChatError as _normalizeChatError } from \"./Chat.Error\";\nimport _ChatCallout from \"./Chat.Callout\";\nimport _ChatApproval from \"./Chat.Approval\";\nimport _ChatTodoList from \"./Chat.TodoList\";\nimport _ChatAttachButton from \"./Chat.AttachButton\";\nimport _ChatThinkingIndicator from \"./Chat.ThinkingIndicator\";\nimport { createHandler as _createHandler } from \"./createHandler\";\n\nexport const Chat: typeof _ChatRoot & {\n Canvas: typeof _ChatCanvas;\n Messages: typeof _ChatMessages;\n Input: typeof _ChatInput;\n Error: typeof _ChatError;\n Callout: typeof _ChatCallout;\n Approval: typeof _ChatApproval;\n TodoList: typeof _ChatTodoList;\n AttachButton: typeof _ChatAttachButton;\n ThinkingIndicator: typeof _ChatThinkingIndicator;\n} = Object.assign(_ChatRoot, {\n Canvas: _ChatCanvas,\n Messages: _ChatMessages,\n Input: _ChatInput,\n Error: _ChatError,\n Callout: _ChatCallout,\n Approval: _ChatApproval,\n TodoList: _ChatTodoList,\n AttachButton: _ChatAttachButton,\n ThinkingIndicator: _ChatThinkingIndicator,\n});\n\nexport const normalizeChatError = _normalizeChatError;\nexport const createHandler = _createHandler;\n\nexport {\n createAgentHandler,\n UPDATE_TODOS_TOOL,\n REQUEST_APPROVAL_TOOL,\n RENDER_CHART_TOOL,\n} from \"./Chat.Agent\";\nexport type {\n CallModel,\n ModelRequest,\n ModelStreamEvent,\n AgentMessage,\n ToolCall,\n ToolSpec,\n AgentTool,\n ToolResult,\n AgentSnapshot,\n AgentSessionStore,\n CreateAgentHandlerOptions,\n} from \"./Chat.Agent\";\n\nexport { useChatContext } from \"./Chat.Context\";\nexport { fileToBase64 } from \"./fileToBase64\";\nexport {\n DEFAULT_TASK_MESSAGES,\n resolveTaskMessages,\n} from \"./Chat.TaskMessages\";\n\nexport {\n ChatThreadsProvider,\n useChatThreads,\n createMemoryThreadsAdapter,\n} from \"./Chat.Threads\";\nexport type {\n ChatThread,\n ChatThreadsAdapter,\n ChatThreadsContextValue,\n ChatThreadsProviderProps,\n} from \"./Chat.Threads\";\n\nexport type {\n ChatMessage,\n ChatChunk,\n ChatResponse,\n AgentHandler,\n ChatAttachment,\n ChatMessageRendererProps,\n ChatComponents,\n ApprovalOption,\n ChatApprovalRequest,\n ChatTodo,\n} from \"./Chat\";\nexport type { ChatApprovalProps } from \"./Chat.Approval\";\nexport type { ChatTodoListProps } from \"./Chat.TodoList\";\nexport type { ChatCanvasProps } from \"./Chat.Canvas\";\nexport type { ChatMessagesProps } from \"./Chat.Messages\";\nexport type { ChatInputProps } from \"./Chat.Input\";\nexport type { ChatErrorProps, NormalizedChatError, ErrorCategory } from \"./Chat.Error\";\nexport type { ChatAttachButtonProps, ChatAttachType } from \"./Chat.AttachButton\";\nexport type { CoralTaskType } from \"./Chat.TaskMessages\";\n"],"mappings":";AAAA,SAAgB,mBAAAA,kBAAiB,UAAAC,SAAQ,YAAAC,iBAAgB;AACzD;AAAA,EACE,YAAAC;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA;AAAA,OACK;AAEP,SAAS,sBAAsB;;;ACR/B,SAAgB,UAAU,WAAW,iBAAiB,QAAQ,mBAA8B;AAC5F,SAAS,UAAAC,SAAQ,cAAAC,aAAY,UAAAC,eAAc;AAC3C,SAAS,iBAAiB;;;ACF1B,SAAS,eAAe,kBAAkB;AAiFnC,IAAM,cAAc,cAAgC,CAAC,CAAqB;AAE1E,SAAS,iBAAmC;AACjD,SAAO,WAAW,WAAW;AAC/B;;;ACpFA,SAAS,OAAO,QAAQ,YAAY,cAAc;AAClD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA6KS,cAwBV,YAxBU;AAvJhB,IAAM,mBAAoC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,sBAAsB,KAA0C;AACvE,SACE,CAAC,CAAC,OACF,OAAO,QAAQ,YACf,OAAQ,IAA4B,YAAY,YAChD,iBAAiB,SAAU,IAA4B,QAAQ;AAEnE;AAOO,SAAS,mBAAmB,KAAmC;AAEpE,MAAI,sBAAsB,GAAG,EAAG,QAAO;AAEvC,QAAM,SAAS;AACf,QAAM,aAAa;AAAA,IACjB,QAAQ,WAAY,QAAQ,OAAmC,WAAW,OAAO;AAAA,EACnF,EAAE,YAAY;AAEd,QAAM,SAAS,OAAO,QAAQ,UAAU,QAAQ,cAAc,CAAC;AAC/D,QAAM,YAAY;AAAA,IACf,QAAQ,OAAmC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,EACtF;AACA,QAAM,YAAY;AAAA,IACf,QAAQ,OAAmC,QAAQ,QAAQ,QAAQ;AAAA,EACtE;AAGA,MACE,WAAW,SAAS,QAAQ,KAC5B,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,oBAAoB,KACxC,cAAc,wBACd,cAAc,qBACd;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MACE,cAAc,sBACd,WAAW,SAAS,YAAY,KAChC,WAAW,SAAS,mBAAmB,GACvC;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MACE,WAAW,OACX,WAAW,OACX,cAAc,sBACd,cAAc,wBACd,WAAW,SAAS,UAAU,KAC9B,WAAW,SAAS,UAAU,GAC9B;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MACE,WAAW,OACX,cAAc,eACd,WAAW,SAAS,iBAAiB,KACrC,WAAW,SAAS,WAAW,GAC/B;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MACE,WAAW,OACX,cAAc,2BACd,cAAc,oBACd;AACA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MAAI,UAAU,OAAO,cAAc,eAAe,cAAc,YAAY;AAC1E,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AACF;AAIA,IAAM,YAAY,WAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,KAAK;AAAA,IACL,SAAS;AAAA,IACT,cAAc,OAAO;AAAA,IACrB,iBAAiB,OAAO;AAAA,IACxB,QAAQ,aAAa,OAAO,mBAAmB;AAAA,IAC/C,OAAO,OAAO;AAAA,IACd,OAAO;AAAA,IACP,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,YAAY;AAAA,EACd;AACF,CAAC;AAED,IAAM,eAA0D;AAAA,EAC9D,cAAc,oBAAC,uBAAoB;AAAA,EACnC,YAAY,oBAAC,kBAAe;AAAA,EAC5B,YAAY,oBAAC,6BAA0B;AAAA,EACvC,WAAW,oBAAC,oBAAiB;AAAA,EAC7B,WAAW,oBAAC,wBAAqB;AAAA,EACjC,cAAc,oBAAC,wBAAqB;AAAA,EACpC,SAAS,oBAAC,oBAAiB;AAC7B;AAWA,IAAM,YAAsC,CAAC,EAAE,OAAO,QAAQ,MAAM;AAClE,QAAM,SAAS,UAAU;AACzB,QAAM,EAAE,UAAU,QAAQ,IAAI,mBAAmB,KAAK;AAEtD,SACE,qBAAC,SAAI,WAAW,OAAO,MACrB;AAAA,yBAAC,UAAK,WAAW,OAAO,MACrB;AAAA,mBAAa,QAAQ;AAAA,MACtB,oBAAC,SAAM,WAAW,OAAO,SAAU,mBAAQ;AAAA,OAC7C;AAAA,IACC,WACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,YAAW;AAAA,QACX,SAAS;AAAA,QACV;AAAA;AAAA,IAED;AAAA,KAEJ;AAEJ;AAEA,IAAO,qBAAQ;;;ACvNR,SAAS,aAAa,MAA6B;AACxD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,SAAS,MAAM;AACpB,YAAM,UAAU,OAAO;AACvB,YAAM,QAAQ,QAAQ,QAAQ,GAAG;AACjC,cAAQ,UAAU,KAAK,UAAU,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAAA,IAC3D;AACA,WAAO,UAAU,MAAM,OAAO,OAAO,SAAS,IAAI,MAAM,mBAAmB,CAAC;AAC5E,WAAO,cAAc,IAAI;AAAA,EAC3B,CAAC;AACH;;;AHuvBM,SAaY,OAAAC,MAbZ,QAAAC,aAAA;AAxtBN,IAAMC,aAAYC,YAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,SAAS;AAAA,IACT,eAAe;AAAA,IACf,MAAM;AAAA,IACN,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,MAAM;AAAA,IACN,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAWC,QAAO;AAAA,IAClB,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,EAClB;AACF,CAAC;AAID,SAAS,gBAAgB,OAAmD;AAC1E,SACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAO,iBAAkB;AAE7B;AAEA,SAAS,iBAAiB,KAAuB;AAC/C,QAAM,IAAI;AACV,QAAM,SAAS,OAAO,GAAG,UAAU,GAAG,cAAc,CAAC;AACrD,QAAM,MAAM,OAAO,GAAG,WAAW,EAAE,EAAE,YAAY;AACjD,SACE,WAAW,OACX,IAAI,SAAS,YAAY,KACzB,IAAI,SAAS,mBAAmB;AAEpC;AAQA,gBAAgB,oBACd,UACA,OAC0B;AAC1B,QAAM,EAAE,MAAM,UAAU,MAAM,SAAS;AACvC,MAAI,MAAO,OAAM;AACnB;AAOA,gBAAgB,YAAY,KAAyC;AACnE,QAAM,SAAS,IAAI,MAAM,UAAU;AACnC,MAAI,CAAC,OAAQ;AACb,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AACb,SAAO,MAAM;AACX,UAAM,EAAE,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AACV,cAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,UAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,aAAS,MAAM,IAAI,KAAK;AACxB,eAAW,OAAO,OAAO;AACvB,YAAM,OAAO,IAAI,WAAW,OAAO,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,IAAI,KAAK;AACtE,UAAI,CAAC,QAAQ,SAAS,SAAU;AAChC,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,YAAI,OAAO,WAAW,UAAU;AAC9B,gBAAM;AAAA,QACR,WAAW,UAAU,OAAO,WAAW,YAAY,UAAU,QAAQ;AACnE,gBAAM;AAAA,QACR,WAAW,UAAU,OAAO,WAAW,YAAY,OAAQ,OAA+B,UAAU,UAAU;AAC5G,cAAI,OAAQ,OAA8B,SAAS,UAAU;AAC3D,kBAAM,EAAE,MAAM,UAAU,MAAO,OAA4B,KAAK;AAAA,UAClE;AACA,gBAAO,OAA6B;AAAA,QACtC;AAAA,MACF,QAAQ;AAEN,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,KAAK,GAAG;AACjB,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,MAAM;AAChC,UAAI,OAAO,WAAW,SAAU,OAAM;AAAA,eAC7B,UAAU,OAAO,WAAW,YAAY,UAAU,OAAQ,OAAM;AAAA,IAC3E,QAAQ;AACN,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAIA,IAAM,aAAwC,CAAC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAASF,WAAU;AAMzB,QAAM,aAAuC,MACzC,eAAgBG,QAAO,SAAS,OAAO;AACrC,UAAMC,eAAc,MAAM,QAAQ;AAAA,MAChC,MAAM,IAAI,OAAO,UAAU;AAAA,QACzB,MAAM,KAAK;AAAA,QACX,WAAW,KAAK;AAAA,QAChB,MAAM,MAAM,aAAa,IAAI;AAAA,MAC/B,EAAE;AAAA,IACJ;AACA,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU;AAAA,QACnB,MAAMD;AAAA,QACN;AAAA,QACA,aAAAC;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,YAAM,OAAO;AAAA,QACX,IAAI,MAAM,4BAA4B,IAAI,MAAM,MAAM,QAAQ,IAAI,UAAU,EAAE;AAAA,QAC9E,EAAE,QAAQ,IAAI,OAAO;AAAA,MACvB;AAAA,IACF;AACA,UAAM,cAAc,IAAI,QAAQ,IAAI,cAAc,KAAK;AACvD,QAAI,YAAY,SAAS,mBAAmB,KAAK,YAAY,SAAS,sBAAsB,GAAG;AAC7F,aAAO,YAAY,GAAG;AAAA,IACxB;AACA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,QAAQ,OAAO,SAAS,UAAU;AAKpC,UAAI,OAAO,KAAK,SAAS,UAAU;AACjC,eAAO,oBAAoB,KAAK,MAAM,OAAO,KAAK,SAAS,EAAE,CAAC;AAAA,MAChE;AACA,UAAI,OAAO,KAAK,UAAU,SAAU,QAAO,KAAK;AAAA,IAClD;AACA,WAAO,OAAO,SAAS,WAAW,OAAO;AAAA,EAC3C,IACA;AAEJ,QAAM,kBAA4C,iBAAiB;AAEnE,QAAM,CAAC,UAAU,WAAW,IAAI;AAAA,IAC9B,OAAO,mBAAmB,CAAC,GAAG,IAAI,CAAC,MAAO,EAAE,KAAK,IAAI,EAAE,GAAG,GAAG,IAAI,OAAO,WAAW,EAAE,CAAE;AAAA,EACzF;AACA,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAC9D,QAAM,CAAC,aAAa,mBAAmB,IAAI,SAAS,CAAC;AACrD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,EAAE;AAC/D,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAA6B;AAC3E,QAAM,CAAC,aAAa,cAAc,IAAI,SAA2B,CAAC,CAAC;AACnE,QAAM,CAAC,0BAA0B,2BAA2B,IAAI,SAE9D,IAAI;AAGN,QAAM,mBAA+C,MAAM;AACzD,aAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,YAAM,IAAI,SAAS,CAAC;AACpB,UAAI,EAAE,SAAS,YAAa;AAC5B,UAAI,EAAE,YAAY,CAAC,EAAE,SAAS,OAAQ,QAAO,EAAE;AAE/C,UAAI,EAAE,YAAY,EAAE,SAAS,OAAQ,QAAO;AAAA,IAC9C;AACA,WAAO;AAAA,EACT,GAAG;AAEH,QAAM,eAAe,OAAO,EAAE;AAC9B,QAAM,mBAAmB,OAAO,EAAE;AAClC,QAAM,iBAAiB,OAAO,KAAK;AACnC,QAAM,2BAA2B,OAAO,cAAc;AACtD,QAAM,uBAAuB,OAAuB,IAAI;AACxD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAgC,IAAI;AACxE,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,gBAAgB,OAAO,KAAK;AAClC,QAAM,oBAAoB,OAAO,KAAK;AAGtC,YAAU,MAAM;AACd,gBAAY,CAAC,YAAY;AACvB,WAAK,iBAAiB,UAAU,KAAK,KAAK,QAAQ,WAAW,GAAG;AAC9D,gBAAQ,mBAAmB,CAAC,GAAG;AAAA,UAAI,CAAC,MAClC,EAAE,KAAK,IAAI,EAAE,GAAG,GAAG,IAAI,OAAO,WAAW,EAAE;AAAA,QAC7C;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,eAAe,CAAC;AAGpB,YAAU,MAAM;AACd,6BAAyB,UAAU;AAAA,EACrC,GAAG,CAAC,cAAc,CAAC;AAGnB,QAAM,cAAc,OAAO,KAAK;AAChC,YAAU,MAAM;AACd,QAAI,iBAAiB,KAAK,KAAK,CAAC,YAAY,SAAS;AACnD,kBAAY,UAAU;AACtB,kBAAY,eAAe;AAAA,IAC7B;AAAA,EAEF,GAAG,CAAC,CAAC;AAEL,QAAM,4BAA4B,YAAY,CAAC,OAA8B;AAC3E,yBAAqB,UAAU;AAC/B,kBAAc,EAAE;AAAA,EAClB,GAAG,CAAC,CAAC;AAGL,kBAAgB,MAAM;AACpB,QAAI,CAAC,kBAAkB,SAAS;AAC9B,UAAI,YAAY;AACd,mBAAW,YAAY,WAAW;AAAA,MACpC;AACA,0BAAoB,KAAK;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,UAAU,UAAU,CAAC;AAGzB,YAAU,MAAM;AACd,UAAM,YAAY;AAClB,QAAI,CAAC,UAAW;AAChB,UAAM,eAAe,MAAM;AACzB,YAAM,EAAE,WAAW,cAAc,aAAa,IAAI;AAClD,YAAM,WAAW,YAAY,gBAAgB,eAAe;AAC5D,wBAAkB,UAAU,CAAC;AAC7B,0BAAoB,CAAC,QAAQ;AAAA,IAC/B;AACA,cAAU,iBAAiB,UAAU,cAAc,EAAE,SAAS,KAAK,CAAC;AACpE,WAAO,MAAM,UAAU,oBAAoB,UAAU,YAAY;AAAA,EACnE,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,iBAAiB,MAAM;AAC3B,sBAAkB,UAAU;AAC5B,cAAU,SAAS,eAAe,EAAE,UAAU,SAAS,CAAC;AACxD,wBAAoB,KAAK;AAAA,EAC3B;AAEA,QAAM,aAAa,CAAC,YAAoB;AACtC,cAAU,UAAU,UAAU,OAAO,EAAE,MAAM,QAAQ,KAAK;AAAA,EAC5D;AAEA,QAAM,iBAAiB,CAAC,UAAkB;AACxC,UAAM,WAA6B,MAAM,IAAI,CAAC,SAAS;AACrD,YAAM,aAA6B,EAAE,IAAI,OAAO,WAAW,GAAG,KAAK;AACnE,UAAI,KAAK,KAAK,WAAW,QAAQ,GAAG;AAClC,cAAM,SAAS,IAAI,WAAW;AAC9B,eAAO,SAAS,CAAC,MAAM;AACrB,gBAAM,UAAU,EAAE,QAAQ;AAC1B;AAAA,YAAe,CAAC,SACd,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,WAAW,KAAK,EAAE,GAAG,GAAG,QAAQ,IAAI,CAAE;AAAA,UAClE;AAAA,QACF;AACA,eAAO,cAAc,IAAI;AAAA,MAC3B;AACA,aAAO;AAAA,IACT,CAAC;AACD,mBAAe,CAAC,SAAS,CAAC,GAAG,MAAM,GAAG,QAAQ,CAAC;AAAA,EACjD;AAEA,QAAM,mBAAmB,CAAC,OAAe;AACvC,mBAAe,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,EAC1D;AAOA,QAAM,aAAa,OACjB,YACA,iBACA,wBACG;AACH,UAAM,gBAAgB;AAEtB,qBAAiB,UAAU;AAC3B,sBAAkB,UAAU;AAC5B,gBAAY,eAAe;AAC3B,uBAAmB,iBAAiB,aAAa;AACjD,gBAAY,IAAI;AAChB,qBAAiB,KAAK;AACtB,kBAAc,UAAU;AACxB,iBAAa,UAAU;AACvB,0BAAsB,EAAE;AACxB,uBAAmB,MAAS;AAE5B,UAAM,eAA8B,eAChC,CAAC,EAAE,MAAM,UAAU,SAAS,aAAa,GAAG,GAAG,eAAe,IAC9D;AAEJ,UAAM,cAAc;AAEpB,QAAI;AACF,UAAI,iBAAiB;AACnB,iBAAS,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,cAAI;AACF,kBAAM,cAAc,OAAO,WAAW;AACtC,kBAAM,cAA6B,CAAC,GAAG,iBAAiB,EAAE,IAAI,aAAa,MAAM,aAAa,SAAS,GAAG,CAAC;AAC3G,wBAAY,WAAW;AACvB,+BAAmB,aAAa,aAAa;AAC7C,kBAAM,WAAW,MAAM,gBAAgB,YAAY,cAAc,oBAAoB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEvG,gBAAI,gBAAgB,QAAQ,GAAG;AAM7B,kBAAI,mBAAmB;AACvB,oBAAM,SAAsB,CAAC;AAI7B,kBAAI,WAAW;AAIf,kBAAI,aAA4B;AAChC,kBAAI,QAAuB;AAC3B,kBAAI;AAEJ,oBAAM,iBAAiB,MACrB,WACI,CAAC,GAAG,QAAQ,EAAE,MAAM,QAAQ,SAAS,SAAS,CAAC,IAC/C;AACN,oBAAM,gBAAgB,MAAM;AAC1B,oBAAI,UAAU;AACZ,yBAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,SAAS,CAAC;AAC/C,6BAAW;AAAA,gBACb;AAAA,cACF;AACA,oBAAM,SAAS,MAAM;AACnB,sBAAM,aAAa,eAAe;AAClC,oBAAI,UAAuB;AAAA,kBACzB,IAAI;AAAA,kBACJ,MAAM;AAAA,kBACN,SAAS;AAAA,kBACT,QAAQ;AAAA,gBACV;AACA,4BAAY,CAAC,SAAS;AACpB,wBAAM,UAAU,CAAC,GAAG,IAAI;AACxB,wBAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,sBAAI,QAAQ,KAAK,OAAO,aAAa;AACnC,8BAAU;AAAA,sBACR,GAAG;AAAA,sBACH,SAAS;AAAA,sBACT,QAAQ;AAAA,oBACV;AAAA,kBACF;AACA,0BAAQ,QAAQ,SAAS,CAAC,IAAI;AAC9B,yBAAO;AAAA,gBACT,CAAC;AACD;AAAA,kBACE,CAAC,GAAG,iBAAiB,OAAO;AAAA,kBAC5B;AAAA,gBACF;AAAA,cACF;AAEA,+BAAiB,SAAS,UAAU;AAClC,oBAAI,cAAc,QAAS;AAI3B,oBACE,kBAAkB,UAClB,yBAAyB,YAAY,cACrC;AACF,oBAAI,OAAO,UAAU,UAAU;AAC7B,sCAAoB;AACpB,8BAAY;AAIZ,sBAAI,UAAU,MAAM;AAClB,4BAAQ,sBAAsB,MAAM;AAClC,8BAAQ;AACR,6BAAO;AAAA,oBACT,CAAC;AAAA,kBACH;AAAA,gBACF,WAAW,MAAM,SAAS,aAAa;AACrC,+BAAa,WAAW,MAAM;AAC9B,wCAAsB,aAAa,OAAO;AAAA,gBAC5C,WAAW,MAAM,SAAS,UAAU;AAClC,qCAAmB,MAAM,IAAI;AAAA,gBAC/B,WAAW,MAAM,SAAS,YAAY;AACpC,qCAAmB,MAAM;AACzB,8BAAY,CAAC,SAAS;AACpB,0BAAM,UAAU,CAAC,GAAG,IAAI;AACxB,0BAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,wBAAI,QAAQ,KAAK,OAAO,aAAa;AACnC,8BAAQ,QAAQ,SAAS,CAAC,IAAI,EAAE,GAAG,MAAM,UAAU,MAAM,SAAS;AAAA,oBACpE;AACA,2BAAO;AAAA,kBACT,CAAC;AAAA,gBACH,WAAW,MAAM,SAAS,SAAS;AACjC,sBAAI,eAAe,MAAM;AACvB,kCAAc;AACd,iCAAa,OAAO;AACpB,2BAAO,KAAK,EAAE,MAAM,SAAS,OAAO,MAAM,MAAM,CAAC;AAAA,kBACnD,OAAO;AACL,2BAAO,UAAU,IAAI,EAAE,MAAM,SAAS,OAAO,MAAM,MAAM;AAAA,kBAC3D;AACA,yBAAO;AAAA,gBACT,WAAW,MAAM,SAAS,SAAS;AACjC,gCAAc;AACd,yBAAO,KAAK,EAAE,MAAM,SAAS,MAAM,MAAM,KAAK,CAAC;AAC/C,yBAAO;AAAA,gBACT;AAAA,cACF;AAEA,kBAAI,UAAU,KAAM,sBAAqB,KAAK;AAC9C,kBAAI,cAAc,QAAS,kBAAiB,IAAI;AAEhD,kBACE,kBAAkB,UAClB,yBAAyB,YAAY,eACrC;AACA;AAAA,cACF;AAEA,4BAAc;AACd,oBAAM,WAAwB;AAAA,gBAC5B,IAAI;AAAA,gBACJ,MAAM;AAAA,gBACN,SAAS;AAAA,gBACT;AAAA,gBACA,GAAI,aAAa,UAAU,EAAE,UAAU,EAAE,WAAW,aAAa,QAAQ,EAAE,IAAI,CAAC;AAAA,gBAChF,GAAI,mBAAmB,EAAE,UAAU,iBAAiB,IAAI,CAAC;AAAA,cAC3D;AACA,oBAAM,gBAAgB,CAAC,GAAG,iBAAiB,QAAQ;AACnD,0BAAY,aAAa;AACzB,iCAAmB,eAAe,aAAa;AAC/C,kCAAoB,eAAe,aAAa;AAAA,YAClD,WAAW,OAAO,aAAa,UAAU;AACvC,kBAAI,yBAAyB,YAAY,cAAe;AACxD,oBAAM,gBAA+B,CAAC,GAAG,iBAAiB,EAAE,IAAI,aAAa,MAAM,aAAsB,SAAS,SAAS,CAAC;AAC5H,0BAAY,aAAa;AACzB,iCAAmB,eAAe,aAAa;AAC/C,kCAAoB,eAAe,aAAa;AAAA,YAClD,OAAO;AACL,kBAAI,yBAAyB,YAAY,cAAe;AACxD,oBAAM,eAA4B;AAAA,gBAChC,IAAI;AAAA,gBACJ,MAAM;AAAA,gBACN,SAAS,SAAS;AAAA,gBAClB,MAAM,SAAS;AAAA,gBACf,UAAU,SAAS;AAAA,gBACnB,OAAO,SAAS;AAAA,cAClB;AACA,oBAAM,gBAAgB,CAAC,GAAG,iBAAiB,YAAY;AACvD,0BAAY,aAAa;AACzB,iCAAmB,eAAe,aAAa;AAC/C,kCAAoB,eAAe,aAAa;AAAA,YAClD;AAEA;AAAA,UACF,SAAS,KAAK;AACZ,gBAAI,iBAAiB,GAAG,KAAK,UAAU,cAAc,GAAG;AACtD,4BAAc,IAAI;AAClB,oBAAM,IAAI,QAAc,CAAC,MAAM,WAAW,IAAI,UAAU,KAAK,GAAI,CAAC;AAClE;AAAA,YACF;AACA,kBAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,gBAAU,GAAG;AAIb,UACE,kBAAkB,UAClB,yBAAyB,YAAY,eACrC;AACA,cAAM,kBAAiC;AAAA,UACrC,GAAG;AAAA,UACH;AAAA,YACE,IAAI,OAAO,WAAW;AAAA,YACtB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO,mBAAmB,GAAG;AAAA,UAC/B;AAAA,QACF;AACA,oBAAY,eAAe;AAC3B,2BAAmB,iBAAiB,aAAa;AAAA,MACnD;AAAA,IACF,UAAE;AACA,oBAAc,KAAK;AACnB,kBAAY,KAAK;AAAA,IACnB;AAAA,EACF;AASA,QAAM,kBAAkB,CAAC,YAAoB,aAAqB;AAChE,UAAM,SAAS,SAAS;AAAA,MACtB,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,UAAU,OAAO;AAAA,IACtD;AACA,QAAI,CAAC,UAAU,CAAC,OAAO,SAAU;AACjC,QAAI,OAAO,SAAS,OAAQ;AAE5B,UAAM,SAAS,OAAO,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACpE,QAAI,CAAC,OAAQ;AAEb,QAAI,OAAO,UAAU;AACnB,kCAA4B,EAAE,YAAY,SAAS,CAAC;AACpD;AAAA,IACF;AAGA,UAAM,UAAU,SAAS;AAAA,MAAI,CAAC,MAC5B,EAAE,SAAS,eAAe,EAAE,UAAU,OAAO,aACzC,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,EAAE,UAAW,QAAQ,EAAE,SAAS,EAAE,EAAE,IAC3D;AAAA,IACN;AACA,UAAM,YAAY,OAAO;AACzB,UAAM,UAAuB;AAAA,MAC3B,IAAI,OAAO,WAAW;AAAA,MACtB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU,EAAE,YAAY,UAAU,OAAO,OAAO,MAAM;AAAA,IACxD;AACA,UAAM,OAAO,CAAC,GAAG,SAAS,OAAO;AACjC,SAAK,WAAW,WAAW,MAAM,CAAC,CAAC;AAAA,EACrC;AAEA,QAAM,cAAc,OAAO,kBAA2B;AACpD,UAAM,aAAa,iBAAiB;AACpC,QAAI,CAAC,WAAW,KAAK,EAAG;AAGxB,QAAI,0BAA0B;AAC5B,YAAM,EAAE,YAAY,SAAS,IAAI;AACjC,YAAM,SAAS,SAAS;AAAA,QACtB,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,UAAU,OAAO;AAAA,MACtD;AACA,UAAI,UAAU,OAAO,UAAU;AAC7B,cAAM,SAAS,OAAO,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACpE,cAAM,UAAU,SAAS;AAAA,UAAI,CAAC,MAC5B,EAAE,SAAS,eAAe,EAAE,UAAU,OAAO,aACzC,EAAE,GAAG,GAAG,UAAU,EAAE,GAAG,EAAE,UAAW,QAAQ,EAAE,UAAU,MAAM,WAAW,EAAE,EAAE,IAC7E;AAAA,QACN;AACA,cAAM,UAAuB;AAAA,UAC3B,IAAI,OAAO,WAAW;AAAA,UACtB,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,WAAW,QAAQ,sBAAsB,EAAE;AAAA,UACpD,UAAU,EAAE,YAAY,UAAU,OAAO,QAAQ,OAAO,MAAM,WAAW;AAAA,QAC3E;AACA,cAAM,OAAO,CAAC,GAAG,SAAS,OAAO;AACjC,YAAI,CAAC,cAAe,UAAS,EAAE;AAC/B,oCAA4B,IAAI;AAChC,uBAAe,UAAU;AACzB,cAAM,WAAW,YAAY,MAAM,CAAC,CAAC;AACrC;AAAA,MACF;AAEA,kCAA4B,IAAI;AAAA,IAClC;AAEA,mBAAe,UAAU;AAMzB,UAAM,cAAc,SAAS,SAAS,SAAS,CAAC;AAChD,UAAM,eAAe,gBACjB,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,SAAS,SAAS,CAAC,IACjD,aAAa,SAAS,eAAe,YAAY,QAC/C,SAAS,MAAM,GAAG,EAAE,IACpB;AAEN,UAAM,sBAAsB;AAC5B,UAAM,iBAAiB,oBAAoB,IAAI,CAAC,OAAO;AAAA,MACrD,MAAM,EAAE,KAAK;AAAA,MACb,MAAM,EAAE,KAAK;AAAA,MACb,SAAS,EAAE;AAAA,IACb,EAAE;AAEF,UAAM,kBAAiC;AAAA,MACrC,GAAG;AAAA,MACH;AAAA,QACE,IAAI,OAAO,WAAW;AAAA,QACtB,MAAM;AAAA,QACN,SAAS,WAAW,QAAQ,sBAAsB,EAAE;AAAA,QACpD,GAAI,eAAe,SAAS,IAAI,EAAE,UAAU,EAAE,aAAa,eAAe,EAAE,IAAI,CAAC;AAAA,MACnF;AAAA,IACF;AAEA,QAAI,CAAC,cAAe,UAAS,EAAE;AAC/B,mBAAe,CAAC,CAAC;AAEjB,UAAM,WAAW,YAAY,iBAAiB,mBAAmB;AAAA,EACnE;AASA,QAAM,0BAA0B,CAAC,cAA+B;AAC9D,QAAI,CAAC,WAAW;AACd,eAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,YAAI,SAAS,CAAC,EAAE,SAAS,OAAQ,QAAO;AAAA,MAC1C;AACA,aAAO;AAAA,IACT;AACA,UAAM,MAAM,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AACxD,QAAI,QAAQ,GAAI,QAAO;AACvB,QAAI,SAAS,GAAG,EAAE,SAAS,OAAQ,QAAO;AAC1C,QAAI,SAAS,GAAG,EAAE,SAAS,aAAa;AACtC,eAAS,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;AACjC,YAAI,SAAS,CAAC,EAAE,SAAS,OAAQ,QAAO;AAAA,MAC1C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,OAAO,cAAuB;AAC/C,UAAM,UAAU,wBAAwB,SAAS;AACjD,QAAI,YAAY,GAAI;AACpB,UAAM,UAAU,SAAS,OAAO;AAChC,UAAM,eAAe,SAAS,MAAM,GAAG,UAAU,CAAC;AAClD,UAAM,WAAW,QAAQ,SAAS,cAAc,CAAC,CAAC;AAAA,EACpD;AAEA,QAAM,cAAc,OAAO,WAAmB,eAAuB;AACnE,UAAM,MAAM,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS;AACxD,QAAI,QAAQ,GAAI;AAChB,QAAI,SAAS,GAAG,EAAE,SAAS,OAAQ;AACnC,UAAM,UAAU,WAAW,QAAQ,sBAAsB,EAAE;AAC3D,QAAI,CAAC,QAAQ,KAAK,EAAG;AAErB,UAAM,gBAA6B;AAAA,MACjC,GAAG,SAAS,GAAG;AAAA,MACf,SAAS;AAAA,IACX;AACA,UAAM,eAA8B;AAAA,MAClC,GAAG,SAAS,MAAM,GAAG,GAAG;AAAA,MACxB;AAAA,IACF;AACA,UAAM,WAAW,SAAS,cAAc,CAAC,CAAC;AAAA,EAC5C;AAEA,SACE,gBAAAN;AAAA,IAAC,YAAY;AAAA,IAAZ;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEA,0BAAAC,MAAC,SAAI,WAAW,OAAO,MACpB;AAAA;AAAA,QACA,oBACC,gBAAAD;AAAA,UAACO;AAAA,UAAA;AAAA,YACC,SAAS;AAAA,YACT,WAAW,OAAO;AAAA,YAClB,OAAM;AAAA,YACN,OAAO;AAAA,cACL,QAAQ,cAAc;AAAA,cACtB,iBAAiB;AAAA,cACjB,QAAQ,aAAaH,QAAO,mBAAmB;AAAA,cAC/C,gBAAgB;AAAA,YAClB;AAAA,YACA,MAAM,gBAAAJ,KAAC,aAAU,OAAO,EAAE,UAAU,OAAO,GAAG;AAAA;AAAA,QAChD;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,sBAAQ;;;AI/xBf,OAAOQ,UAAS,aAAAC,YAAW,mBAAAC,kBAAiB,UAAAC,SAAQ,YAAAC,iBAAgB;AACpE;AAAA,EACE,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,OAEK;AACP;AAAA,EACE;AAAA,OAGK;;;ACnBP,SAAgB,YAAAC,WAAU,aAAAC,YAAW,UAAAC,eAAc;AACnD,SAAS,cAAAC,aAAY,SAAS,UAAAC,eAAc;AA4GtC,gBAAAC,MACA,QAAAC,aADA;AA1GN,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,eAAe;AACrB,IAAM,gBAAgB;AAEtB,IAAMC,aAAYJ,YAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,OAAO;AAAA,IACP,OAAOC,QAAO;AAAA,EAChB;AAAA,EACA,MAAM;AAAA;AAAA;AAAA;AAAA,IAIJ,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,iBAAiBA,QAAO;AAAA,IACxB,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,eAAe;AAAA,MACb,YAAY,EAAE,SAAS,IAAI;AAAA,MAC3B,OAAO,EAAE,SAAS,IAAI;AAAA,IACxB;AAAA,IACA,mBAAmB;AAAA,IACnB,yBAAyB;AAAA,IACzB,yBAAyB;AAAA,EAC3B;AACF,CAAC;AAaD,IAAM,oBAAsD,CAAC,EAAE,aAAa,OAAO,QAAQ,SAAS,MAAM;AACxG,QAAM,SAASG,WAAU;AACzB,QAAM,CAAC,aAAa,cAAc,IAAIP,UAAS,EAAE;AACjD,QAAM,WAAWE,QAAkD,MAAS;AAC5E,QAAM,YAAYA,QAAO,CAAC;AAC1B,QAAM,aAAaA,QAAO,CAAC;AAE3B,EAAAD,WAAU,MAAM;AACd,UAAM,OAAO,aAAa,mBAAoB,YAAY,SAAS,SAAS,IAAI,WAAW;AAE3F,cAAU,UAAU;AACpB,eAAW,UAAU;AAErB,UAAM,OAAO,MAAM;AACjB,YAAM,OAAO,KAAK,UAAU,OAAO;AAEnC,UAAI,WAAW,UAAU,KAAK,QAAQ;AACpC,mBAAW,WAAW;AACtB,uBAAe,KAAK,MAAM,GAAG,WAAW,OAAO,CAAC;AAChD,iBAAS,UAAU,WAAW,MAAM,YAAY;AAAA,MAClD,OAAO;AAEL,iBAAS,UAAU,WAAW,MAAM;AAClC,oBAAU,WAAW,UAAU,UAAU,KAAK,KAAK;AACnD,qBAAW,UAAU;AACrB,eAAK;AAAA,QACP,GAAG,aAAa;AAAA,MAClB;AAAA,IACF;AAEA,SAAK;AACL,WAAO,MAAM,aAAa,SAAS,OAAO;AAAA,EAC5C,GAAG,CAAC,YAAY,QAAQ,CAAC;AAEzB,SACE,gBAAAK,MAAC,SAAI,WAAW,OAAO,MACrB;AAAA,oBAAAD,KAAC,WAAQ,MAAK,QAAO;AAAA,IACrB,gBAAAC,MAAC,UAAK,WAAW,OAAO,MACrB;AAAA,gBAAU;AAAA,MACX,gBAAAD,KAAC,UAAK,WAAW,OAAO,QAAQ;AAAA,OAClC;AAAA,KACF;AAEJ;AAEA,IAAO,iCAAQ;;;ACxGR,IAAM,wBAAyD;AAAA,EACpE,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,OAAO,CAAC,WAAW,aAAa,iBAAiB,mBAAmB;AAAA,EACpE,MAAM,CAAC,oBAAoB,WAAW,aAAa,UAAU;AAAA,EAC7D,OAAO,CAAC,aAAa,gBAAgB,kBAAkB;AACzD;AAOO,SAAS,oBAAoB,MAAyB;AAC3D,MAAI,QAAQ,QAAQ,uBAAuB;AACzC,WAAO,sBAAsB,IAAqB;AAAA,EACpD;AACA,SAAO,sBAAsB;AAC/B;;;AC1CA,SAAS,SAAAG,QAAO,UAAAC,SAAQ,cAAAC,aAAY,cAAc,UAAAC,eAAc;AAChE,SAAS,4BAA4B;AAyC/B,SACE,OAAAC,MADF,QAAAC,aAAA;AAjCN,IAAMC,aAAYJ,YAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,KAAK;AAAA,IACL,SAAS;AAAA,IACT,cAAcC,QAAO;AAAA,IACrB,iBAAiBA,QAAO;AAAA,IACxB,QAAQ,aAAaA,QAAO,mBAAmB;AAAA,IAC/C,OAAOA,QAAO;AAAA,IACd,OAAO;AAAA,IACP,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,EACP;AAAA,EACA,OAAO;AAAA,IACL,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,UAAU;AAAA,EACZ;AACF,CAAC;AAED,IAAM,cAA0C,CAAC,EAAE,SAAS,SAAS,UAAU,MAAM;AACnF,QAAM,SAASG,WAAU;AAEzB,SACE,gBAAAD,MAAC,SAAI,WAAW,aAAa,OAAO,MAAM,SAAS,GACjD;AAAA,oBAAAA,MAAC,UAAK,WAAW,OAAO,MACtB;AAAA,sBAAAD,KAAC,wBAAqB;AAAA,MACtB,gBAAAA,KAACJ,QAAA,EAAM,WAAW,OAAO,OAAQ,mBAAQ;AAAA,OAC3C;AAAA,IACC,WACC,gBAAAI;AAAA,MAACH;AAAA,MAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAW,OAAO;AAAA,QAClB,MAAK;AAAA,QACL,YAAW;AAAA,QACZ;AAAA;AAAA,IAED;AAAA,KAEJ;AAEJ;AAEA,IAAO,uBAAQ;;;AC7Df,SAAgB,YAAAM,WAAU,aAAAC,YAAW,UAAAC,eAAc;AACnD,SAAS,SAAAC,QAAO,cAAAC,aAAY,UAAAC,eAAc;AAC1C,SAA+B,6BAA6B;AAsHpD,SAEI,OAAAC,MAFJ,QAAAC,aAAA;AA7GR,IAAMC,aAAYJ,YAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,KAAK;AAAA,EACP;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,UAAU;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA,OAAO;AAAA,IACL,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,iBAAiBC,QAAO;AAAA,IACxB,eAAe;AAAA,MACb,YAAY,EAAE,SAAS,IAAI;AAAA,MAC3B,OAAO,EAAE,SAAS,MAAM;AAAA,IAC1B;AAAA,IACA,mBAAmB;AAAA,IACnB,yBAAyB;AAAA,IACzB,yBAAyB;AAAA,EAC3B;AAAA,EACA,WAAW;AAAA,IACT,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,iBAAiBA,QAAO;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA,IACL,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AAAA,IACP,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EACA,iBAAiB;AAAA,IACf,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,UAAUA,QAAO;AAAA,IACjB,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,WAAW;AAAA;AAAA;AAAA,EAGb;AACF,CAAC;AAED,IAAM,iBAAgD,CAAC;AAAA,EACrD;AAAA,EACA,cAAc;AAChB,MAAM;AACJ,QAAM,SAASG,WAAU;AACzB,QAAM,CAAC,UAAU,WAAW,IAAIR,UAAS,KAAK;AAC9C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAwB,IAAI;AAC5D,QAAM,eAAeE,QAAsB,IAAI;AAE/C,EAAAD,WAAU,MAAM;AACd,QAAI,aAAa;AACf,mBAAa,UAAU,KAAK,IAAI;AAChC,kBAAY,IAAI;AAAA,IAClB,WAAW,aAAa,YAAY,MAAM;AACxC,kBAAY,KAAK,OAAO,KAAK,IAAI,IAAI,aAAa,WAAW,GAAI,CAAC;AAClE,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,QAAQ,cACV,aACA,aAAa,OACX,eAAe,QAAQ,MACvB;AAEN,SACE,gBAAAM,MAAC,SAAI,WAAW,OAAO,MACrB;AAAA,oBAAAD,KAAC,YAAO,WAAW,OAAO,QAAQ,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,GACpE,0BAAAC,MAAC,SAAI,WAAW,OAAO,UACrB;AAAA,sBAAAD,KAAC,SAAI,WAAW,OAAO,gBACrB,0BAAAA,KAAC,UAAK,WAAW,cAAc,OAAO,QAAQ,OAAO,WAAW,GAClE;AAAA,MACA,gBAAAA,KAACH,QAAA,EAAM,WAAW,OAAO,OAAQ,iBAAM;AAAA,MACvC,gBAAAG;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,WAAW,OAAO,kBAAkB,OAAO;AAAA;AAAA,MACxD;AAAA,OACF,GACF;AAAA,IAEC,YACC,gBAAAA,KAAC,SAAI,WAAW,OAAO,UAAW,mBAAQ;AAAA,KAE9C;AAEJ;AAEA,IAAO,8BAAQ;;;AC1If,SAAgB,YAAAG,iBAAgB;AAChC;AAAA,EACE,SAAAC;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA6HC,gBAAAC,MAIA,QAAAC,aAJA;AAnHR,IAAMC,aAAYJ,YAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,QAAQ,aAAaC,QAAO,mBAAmB;AAAA,IAC/C,UAAU;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA,OAAO;AAAA,IACL,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,EACd;AAAA,EACA,OAAO;AAAA,IACL,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EACA,SAAS;AAAA,IACP,OAAOA,QAAO;AAAA,IACd,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,iBAAiB;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,IACL,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,KAAK;AAAA,EACP;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,OAAOA,QAAO;AAAA,EAChB;AAAA,EACA,YAAY;AAAA,IACV,OAAOA,QAAO;AAAA,EAChB;AAAA,EACA,UAAU;AAAA,IACR,OAAOA,QAAO;AAAA,EAChB;AAAA,EACA,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,OAAOA,QAAO;AAAA,EAChB;AAAA,EACA,YAAY;AAAA,IACV,OAAOA,QAAO;AAAA,IACd,YAAYA,QAAO;AAAA,EACrB;AAAA,EACA,UAAU;AAAA,IACR,OAAOA,QAAO;AAAA,IACd,oBAAoB;AAAA,EACtB;AACF,CAAC;AAED,IAAM,eAA4C,CAAC;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAASG,WAAU;AAEzB,QAAM,QAAQ,MAAM;AACpB,QAAM,YAAY,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EAAE;AAIhE,QAAM,CAAC,UAAU,WAAW,IAAIN,UAAS,IAAI;AAE7C,MAAI,UAAU,EAAG,QAAO;AAExB,SACE,gBAAAK;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,OAAO,IAAI,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE;AAAA,MAC5D;AAAA,MACA,MAAK;AAAA,MACL,cAAY,cAAc,SAAS,OAAO,KAAK;AAAA,MAE/C;AAAA,wBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAW,OAAO;AAAA,YAClB,SAAS,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;AAAA,YACpC,iBAAe;AAAA,YAEf;AAAA,8BAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,GAAG,OAAO,OAAO,GAAG,WAAW,IAAI,OAAO,eAAe,KAAK,EAAE;AAAA;AAAA,cAC7E;AAAA,cACA,gBAAAA,KAACH,QAAA,EAAM,WAAW,OAAO,OAAO,mBAAK;AAAA,cACrC,gBAAAI,MAAC,YAAS,WAAW,OAAO,OACzB;AAAA;AAAA,gBAAU;AAAA,gBAAE;AAAA,iBACf;AAAA;AAAA;AAAA,QACF;AAAA,QAEC,YACC,gBAAAD,KAAC,SAAI,WAAW,OAAO,MAAM,MAAK,QAC/B,gBAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,gBAAM,OACJ,KAAK,WAAW,gBACX,KAAK,cAAc,KAAK,UACzB,KAAK;AACX,gBAAM,YACJ,KAAK,WAAW,cACZ,OAAO,WACP,KAAK,WAAW,gBACd,OAAO,aACP,OAAO;AACf,iBACE,gBAAAC;AAAA,YAAC;AAAA;AAAA,cAEC,WAAW,OAAO;AAAA,cAClB,MAAK;AAAA,cAEL;AAAA,gCAAAD,KAAC,UAAK,WAAW,OAAO,UACrB,eAAK,WAAW,cACf,gBAAAA,KAAC,yBAAsB,WAAW,OAAO,UAAU,IACjD,KAAK,WAAW,gBAClB,gBAAAA,KAAC,4BAAyB,WAAW,OAAO,YAAY,IAExD,gBAAAA,KAAC,qBAAkB,WAAW,OAAO,aAAa,GAEtD;AAAA,gBACA,gBAAAA,KAACH,QAAA,EAAM,WAAW,GAAG,OAAO,IAAI,IAAI,SAAS,IAAK,gBAAK;AAAA;AAAA;AAAA,YAblD,KAAK,MAAM,QAAQ,KAAK;AAAA,UAc/B;AAAA,QAEJ,CAAC,GACH;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAO,wBAAQ;;;AL7Jf,SAAS,kBAAkB;AAqB3B,SAAS,+BAA+B;AA4RxB,SAqEN,UArEM,OAAAM,MAYA,QAAAC,aAZA;AAxShB,SAAS,cAAc,KAA+B;AACpD,MAAI,IAAI,OAAQ,QAAO,IAAI;AAC3B,QAAM,SAAsB,CAAC;AAC7B,MAAI,IAAI,SAAS,IAAI,MAAM,SAAS,GAAG;AACrC,WAAO,KAAK,EAAE,MAAM,SAAS,OAAO,IAAI,MAAM,CAAC;AAAA,EACjD;AACA,MAAI,IAAI,QAAQ;AACd,eAAW,QAAQ,IAAI,OAAQ,QAAO,KAAK,EAAE,MAAM,SAAS,KAAK,CAAC;AAAA,EACpE;AACA,MAAI,IAAI,QAAS,QAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,CAAC;AACnE,SAAO;AACT;AAuBA,IAAMC,aAAYC,YAAW;AAAA,EAC3B,UAAU;AAAA,IACR,MAAM;AAAA,IACN,WAAW;AAAA,IACX,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,WAAW;AAAA,IACX,iBAAiB;AAAA,EACnB;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,IACL,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA;AAAA,EAEA,SAAS;AAAA,IACP,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,iEAAiE;AAAA,MAC/D,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,iBAAiBC,QAAO;AAAA,IACxB,OAAOA,QAAO;AAAA,IACd,QAAQ,aAAaA,QAAO,mBAAmB;AAAA,IAC/C,SAAS;AAAA,IACT,cAAcA,QAAO;AAAA,IACrB,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,EACX;AAAA;AAAA,EAEA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA;AAAA,IAEZ,KAAK;AAAA,EACP;AAAA,EACA,kBAAkB;AAAA,IAChB,iBAAiBA,QAAO;AAAA,IACxB,OAAOA,QAAO;AAAA,IACd,QAAQ,aAAaA,QAAO,mBAAmB;AAAA,IAC/C,SAAS;AAAA,IACT,cAAcA,QAAO;AAAA,IACrB,YAAYA,QAAO;AAAA,IACnB,UAAUA,QAAO;AAAA,IACjB,YAAYA,QAAO;AAAA,IACnB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IACP,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,MACT,QAAQ,aAAaA,QAAO,mBAAmB;AAAA,IACjD;AAAA,EACF;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,WAAW;AAAA;AAAA,IAEX,OAAO,GAAGA,QAAO,uBAAuB;AAAA,IACxC,KAAK;AAAA,IACL,YAAY;AAAA,EACd;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,KAAK;AAAA,EACP;AAAA;AAAA,EAEA,kBAAkB;AAAA,IAChB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAOA,QAAO;AAAA,IACd,WAAW;AAAA,IACX,WAAW;AAAA,IACX,2EAA2E;AAAA,MACzE,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,YAAY;AAAA;AAAA,IAEZ,SAAS;AAAA,IACT,YAAY;AAAA,EACd;AAAA,EACA,kBAAkB;AAAA,IAChB,SAAS;AAAA,EACX;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAOA,QAAO;AAAA,EAChB;AAAA,EACA,kBAAkB;AAAA,IAChB,OAAOA,QAAO;AAAA,EAChB;AACF,CAAC;AAID,IAAM,eAA4C,CAAC;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAASF,WAAU;AACzB,QAAM,MAAM,eAAe;AAC3B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,eAAeG,QAAuB,IAAI;AAChD,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAwB,IAAI;AAC1D,EAAAC,iBAAgB,MAAM;AACpB,UAAM,KAAK,aAAa,SAAS,QAAQ,sBAAsB;AAC/D,eAAW,IAAI,aAAa,oBAAoB,KAAK,IAAI;AAAA,EAC3D,GAAG,CAAC,CAAC;AACL,QAAM,YAAY,YAAY;AAC9B,QAAM,CAAC,WAAW,YAAY,IAAID,UAAwB,IAAI;AAC9D,QAAM,iBAAiBD,QAA6C,IAAI;AAGxE,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAwB,IAAI;AAC9D,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,EAAE;AAC7C,QAAM,kBAAkBD,QAA4B,IAAI;AAExD,EAAAG,WAAU,MAAM;AACd,8BAA0B,aAAa,OAAO;AAC9C,WAAO,MAAM,0BAA0B,IAAI;AAAA,EAE7C,GAAG,CAAC,CAAC;AAGL,EAAAD,iBAAgB,MAAM;AACpB,QAAI,aAAa,gBAAgB,SAAS;AACxC,YAAM,KAAK,gBAAgB;AAC3B,SAAG,MAAM;AACT,SAAG,kBAAkB,GAAG,MAAM,QAAQ,GAAG,MAAM,MAAM;AACrD,SAAG,MAAM,SAAS;AAClB,SAAG,MAAM,SAAS,GAAG,GAAG,YAAY;AAAA,IACtC;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,YAAY,CAAC,QAAqB;AACtC,QAAI,CAAC,IAAI,GAAI;AACb,iBAAa,IAAI,EAAE;AACnB,iBAAa,IAAI,OAAO;AAAA,EAC1B;AAEA,QAAM,aAAa,MAAM;AACvB,iBAAa,IAAI;AACjB,iBAAa,EAAE;AAAA,EACjB;AAEA,QAAM,WAAW,YAAY;AAC3B,QAAI,CAAC,UAAW;AAChB,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,CAAC,QAAS;AACd,UAAM,KAAK;AACX,iBAAa,IAAI;AACjB,iBAAa,EAAE;AACf,UAAM,YAAY,IAAI,OAAO;AAAA,EAC/B;AAEA,QAAM,0BAA0B,CAC9B,MACG;AACH,iBAAa,EAAE,OAAO,KAAK;AAC3B,UAAM,KAAK,EAAE;AACb,OAAG,MAAM,SAAS;AAClB,OAAG,MAAM,SAAS,GAAG,GAAG,YAAY;AAAA,EACtC;AAEA,QAAM,oBAAoB,CAAC,MAAgD;AACzE,QAAI,EAAE,QAAQ,UAAU;AACtB,QAAE,eAAe;AACjB,iBAAW;AAAA,IACb,WAAW,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AAC3C,QAAE,eAAe;AACjB,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,SAAiB,QAAgB;AACrD,eAAW,OAAO;AAClB,aAAS,OAAO;AAChB,QAAI,eAAe,QAAS,cAAa,eAAe,OAAO;AAC/D,iBAAa,GAAG;AAChB,mBAAe,UAAU,WAAW,MAAM,aAAa,IAAI,GAAG,IAAI;AAAA,EACpE;AAIA,QAAM,oBAAoB,CAAC,KAAkB,UAAkB;AAC7D,UAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAClC,UAAM,YAAY,CAAC,CAAC,IAAI,MAAM,cAAc,IAAI;AAChD,UAAM,cAAc,MAAM,QAAQ,IAAI,UAAU,WAAW,IACtD,IAAI,SAAU,cAKf;AAEJ,WACE,gBAAAN,MAAC,SAAc,WAAW,OAAO,SAC9B;AAAA,qBACC,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,YACL,SAAS;AAAA,YACT,KAAK;AAAA,YACL,UAAU;AAAA,YACV,cAAc;AAAA,UAChB;AAAA,UAEC,sBAAY;AAAA,YAAI,CAAC,GAAG,MACnB,EAAE,KAAK,WAAW,QAAQ,KAAK,EAAE,UAC/B,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBAEC,KAAK,EAAE;AAAA,gBACP,KAAK,EAAE;AAAA,gBACP,OAAO;AAAA,kBACL,OAAO;AAAA,kBACP,QAAQ;AAAA,kBACR,cAAcI,QAAO;AAAA,kBACrB,WAAW;AAAA,gBACb;AAAA;AAAA,cARK;AAAA,YASP,IAEA,gBAAAH;AAAA,cAAC;AAAA;AAAA,gBAEC,OAAO;AAAA,kBACL,UAAU;AAAA,kBACV,SAAS;AAAA,kBACT,cAAcG,QAAO;AAAA,kBACrB,iBAAiBA,QAAO;AAAA,kBACxB,OAAOA,QAAO;AAAA,gBAChB;AAAA,gBACD;AAAA;AAAA,kBACK,EAAE;AAAA;AAAA;AAAA,cATD;AAAA,YAUP;AAAA,UAEJ;AAAA;AAAA,MACF;AAAA,MAGD,YACC,gBAAAH,MAAC,SAAI,WAAW,OAAO,cACrB;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,WAAW,OAAO;AAAA,YAClB,OAAO;AAAA,YACP,UAAU;AAAA,YACV,WAAW;AAAA,YACX,MAAM;AAAA;AAAA,QACR;AAAA,QAEA,gBAAAC,MAAC,SAAI,WAAW,OAAO,gBACrB;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,aAAa;AAAA,gBACb,OAAO,GAAGI,QAAO,uBAAuB;AAAA,gBACxC,UAAU;AAAA,gBACV,WAAW;AAAA,gBACX,YAAY;AAAA,cACd;AAAA;AAAA,UACF;AAAA,UACA,gBAAAJ,KAACS,WAAA,EAAS,8FAGV;AAAA,UACA,gBAAAR,MAAC,SAAI,WAAW,OAAO,iBACrB;AAAA,4BAAAD,KAACU,SAAA,EAAO,YAAW,UAAS,SAAS,YAAY,oBAEjD;AAAA,YACA,gBAAAV;AAAA,cAACU;AAAA,cAAA;AAAA,gBACC,YAAW;AAAA,gBACX,SAAS;AAAA,gBACT,UAAU,CAAC,UAAU,KAAK;AAAA,gBAC3B;AAAA;AAAA,YAED;AAAA,aACF;AAAA,WACF;AAAA,SACF,IAEA,gBAAAT,MAAA,YACE;AAAA,wBAAAD,KAAC,SAAI,WAAW,OAAO,YACrB,0BAAAA,KAACW,QAAA,EACE,cAAI,QAAQ,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,QACrC,gBAAAV,MAACW,OAAM,UAAN,EACE;AAAA;AAAA,UACA,IAAI,IAAI,SAAS,KAAK,gBAAAZ,KAAC,QAAG;AAAA,aAFR,CAGrB,CACD,GACH,GACF;AAAA,QACC,IAAI,MACH,gBAAAA,KAAC,SAAI,WAAW,GAAG,OAAO,UAAU,sBAClC,0BAAAC,MAAC,SAAI,WAAW,OAAO,aACpB;AAAA,wBAAc,QAAQ,GAAG,KACxB,gBAAAD,KAAC,UAAK,WAAW,OAAO,aACtB,0BAAAA,KAAC,2BAAwB,GAC3B,IAEA,gBAAAA;AAAA,YAACU;AAAA,YAAA;AAAA,cACC,SAAS,MAAM,aAAa,IAAI,SAAS,QAAQ,GAAG,EAAE;AAAA,cACtD,OAAM;AAAA,cACN,YAAW;AAAA,cACX,WAAW,OAAO;AAAA,cAClB,MAAM,gBAAAV,KAAC,QAAK;AAAA;AAAA,UACd;AAAA,UAEF,gBAAAA;AAAA,YAACU;AAAA,YAAA;AAAA,cACC,SAAS,MAAM,UAAU,GAAG;AAAA,cAC5B,OAAM;AAAA,cACN,YAAW;AAAA,cACX,WAAW,OAAO;AAAA,cAClB,MAAM,gBAAAV,KAAC,YAAS;AAAA;AAAA,UAClB;AAAA,WACF,GACF;AAAA,SAEJ;AAAA,SAtHM,GAwHV;AAAA,EAEJ;AAEA,QAAM,yBAAyB,CAAC,KAAkB,UAAkB;AAClE,UAAM,WAAW,UAAU,SAAS,SAAS;AAC7C,UAAM,YACJ,YAAY,WACR,qBACC,IAAI,UAAU;AAErB,QAAI,IAAI,QAAQ,aAAa,IAAI,IAAI,GAAG;AACtC,YAAM,iBAAiB,WAAW,IAAI,IAAI;AAC1C,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,SAAS,CAAC,YAAY;AACpB,kBAAM,kBAAiC;AAAA,cACrC,GAAG,SAAS,MAAM,GAAG,QAAQ,CAAC;AAAA,cAC9B,EAAE,MAAM,QAAQ,QAAQ;AAAA,YAC1B;AACA,wBAAY,eAAe;AAC3B,wBAAY,OAAO;AAAA,UACrB;AAAA;AAAA,MACF;AAAA,IAEJ;AAEA,UAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAElC,WACE,gBAAAC,MAAC,SACE;AAAA,mBACC,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,aAAa,YAAY,YAAY,CAAC,IAAI;AAAA;AAAA,MAC5C;AAAA,MAED,cAAc,GAAG,EAAE,IAAI,CAAC,OAAO,MAAM;AACpC,YAAI,MAAM,SAAS,SAAS;AAC1B,iBAAO,gBAAAA,KAAC,yBAAgC,OAAO,MAAM,SAA3B,SAAS,CAAC,EAAwB;AAAA,QAC9D;AACA,YAAI,MAAM,SAAS,SAAS;AAC1B,iBAAO,gBAAAA,KAAC,cAA8B,MAAM,MAAM,QAA1B,SAAS,CAAC,EAAsB;AAAA,QAC1D;AACA,eACE,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA;AAAA,YACA;AAAA,YAEC,gBAAM;AAAA;AAAA,UALF,QAAQ,CAAC;AAAA,QAMhB;AAAA,MAEJ,CAAC;AAAA,MACA,IAAI,SACH,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,IAAI;AAAA,UACX,SAAS,MAAM;AACb,kBAAM,UAAU,SAAS,QAAQ,CAAC;AAClC,gBAAI,SAAS,SAAS,OAAQ,aAAY,QAAQ,OAAO;AAAA,UAC3D;AAAA;AAAA,MACF;AAAA,MAED,iBAAiB,CAAC,YAAY,YAC7B,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,SAAS,MAAM,YAAY,iBAAiB,OAAO;AAAA;AAAA,MACrD;AAAA,MAED,EAAE,YAAY,aAAa,IAAI,QAAQ,KAAK,KAC3C,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,GAAG,OAAO,eAAe;AAAA,UAGpC,OAAO,WAAW,EAAE,SAAS,EAAE,IAAI;AAAA,UAEnC,0BAAAC,MAAC,SAAI,WAAW,OAAO,kBACpB;AAAA,0BAAc,aAAa,GAAG,KAC7B,gBAAAD,KAAC,UAAK,WAAW,OAAO,aACtB,0BAAAA,KAAC,2BAAwB,GAC3B,IAEA,gBAAAA;AAAA,cAACU;AAAA,cAAA;AAAA,gBACC,SAAS,MAAM,aAAa,IAAI,SAAS,aAAa,GAAG,EAAE;AAAA,gBAC3D,OAAM;AAAA,gBACN,YAAW;AAAA,gBACX,WAAW,OAAO;AAAA,gBAClB,MAAM,gBAAAV,KAAC,QAAK;AAAA;AAAA,YACd;AAAA,YAED,YACC,gBAAAA;AAAA,cAACU;AAAA,cAAA;AAAA,gBACC,SAAS,MAAM,WAAW,IAAI,EAAE;AAAA,gBAChC,OAAM;AAAA,gBACN,YAAW;AAAA,gBACX,WAAW,OAAO;AAAA,gBAClB,MAAM,gBAAAV,KAAC,kBAAe;AAAA;AAAA,YACxB;AAAA,aAEJ;AAAA;AAAA,MACF;AAAA,OAEJ;AAAA,EAEJ;AAEA,SACE,gBAAAA,KAAC,SAAI,WAAW,OAAO,UAAU,KAAK,cACpC,0BAAAC;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,OAAO;AAAA,MAClB,OAAO,YAAY,EAAE,SAAS,QAAQ,IAAI;AAAA,MAEzC;AAAA,iBAAS,IAAI,CAAC,KAAK,UAAU;AAC5B,cAAI,IAAI,SAAS,QAAQ;AACvB,mBAAO,kBAAkB,KAAK,KAAK;AAAA,UACrC;AACA,gBAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAClC,gBAAM,WAAW,UAAU,SAAS,SAAS;AAC7C,iBACE,gBAAAD;AAAA,YAAC;AAAA;AAAA,cAEC,WAAW,GAAG,OAAO,gBAAgB,2BAA2B,WAAW,eAAe,EAAE;AAAA,cAE3F,iCAAuB,KAAK,KAAK;AAAA;AAAA,YAH7B;AAAA,UAIP;AAAA,QAEJ,CAAC;AAAA,QAEA,YACC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,QAAQ;AAAA,YACR,UAAU,oBAAoB,eAAe;AAAA;AAAA,QAC/C;AAAA,QAEF,gBAAAA,KAAC,SAAI,KAAK,WAAW;AAAA;AAAA;AAAA,EACvB,GACF;AAEJ;AAEA,IAAO,wBAAQ;;;AMvkBf;AAAA,EACE,UAAAa;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAAC,QAAO,UAAAC,SAAQ,KAAK,cAAAC,aAAY,UAAAC,eAAc;AACvD,SAAS,SAAS,MAAM,YAAY;;;ACRpC,SAAgB,UAAAC,eAAc;AAC9B;AAAA,EACE,UAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,KAAK,aAAa,gBAAgB;AAsCvC,qBAAAC,WAEI,OAAAC,MAwBF,QAAAC,aA1BF;AAXJ,IAAM,mBAAoD,CAAC;AAAA,EACzD,QAAQ,CAAC,SAAS,QAAQ;AAC5B,MAAM;AACJ,QAAM,EAAE,eAAe,IAAI,eAAe;AAC1C,QAAM,UAAUC,QAAyB,IAAI;AAC7C,QAAM,WAAWA,QAAyB,IAAI;AAE9C,QAAM,YAAY,MAAM,SAAS,OAAO;AACxC,QAAM,aAAa,MAAM,SAAS,QAAQ;AAE1C,SACE,gBAAAD,MAAAF,WAAA,EACG;AAAA,iBACC,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,QAAM;AAAA,QACN,UAAQ;AAAA,QACR,UAAU,CAAC,MAAM;AACf,cAAI,EAAE,OAAO,MAAO,gBAAe,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC;AACtD,YAAE,OAAO,QAAQ;AAAA,QACnB;AAAA;AAAA,IACF;AAAA,IAED,cACC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,QAAM;AAAA,QACN,UAAQ;AAAA,QACR,QAAO;AAAA,QACP,UAAU,CAAC,MAAM;AACf,cAAI,EAAE,OAAO,MAAO,gBAAe,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC;AACtD,YAAE,OAAO,QAAQ;AAAA,QACnB;AAAA;AAAA,IACF;AAAA,IAEF,gBAAAC,MAAC,QACC;AAAA,sBAAAD,KAAC,eACC,0BAAAA,KAACG,SAAA,EAAO,YAAW,UAAS,MAAM,gBAAAH,KAAC,OAAI,GAAI,GAC7C;AAAA,MACA,gBAAAA,KAAC,eACC,0BAAAA,KAAC,YACE,gBAAM;AAAA,QAAI,CAAC,MACV,MAAM,UACJ,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,MAAM,gBAAAA,KAAC,eAAY;AAAA,YACnB,SAAS,MAAM,QAAQ,SAAS,MAAM;AAAA,YACvC;AAAA;AAAA,UAHK;AAAA,QAKN,IAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,MAAM,gBAAAA,KAAC,YAAS;AAAA,YAChB,SAAS,MAAM,SAAS,SAAS,MAAM;AAAA,YACxC;AAAA;AAAA,UAHK;AAAA,QAKN;AAAA,MAEJ,GACF,GACF;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,IAAO,4BAAQ;;;AD6IC,gBAAAI,MAqCM,QAAAC,aArCN;AAzMhB,IAAMC,aAAYC,YAAW;AAAA,EAC3B,SAAS;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,SAAS;AAAA,IACT,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA,aAAa;AAAA,IACX,WAAWC,QAAO;AAAA,EACpB;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,eAAe;AAAA,EACjB;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,KAAK;AAAA,IACL,WAAW;AAAA,IACX,SAAS;AAAA,EACX;AAAA,EACA,gBAAgB;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ,aAAaA,QAAO,mBAAmB;AAAA,IAC/C,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,eAAe;AAAA,EACjB;AAAA,EACA,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,IACL,gBAAgB;AAAA,EAClB;AAAA,EACA,oBAAoB;AAAA,IAClB,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,EACd;AAAA,EACA,mBAAmB;AAAA,IACjB,UAAU;AAAA,IACV,KAAK;AAAA,IACL,OAAO;AAAA,EACT;AAAA,EACA,UAAU;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,WAAW;AAAA,IACX,SAAS;AAAA,IACT,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,OAAO;AAAA,EACT;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,EACd;AAAA,EACA,UAAU;AAAA,IACR,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,iBAAiB;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA,gBAAgB;AAAA,IACd,WAAW;AAAA,EACb;AACF,CAAC;AAID,IAAM,YAAY;AAAA,EAChB,CACE;AAAA,IACE,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,IACT,cAAc;AAAA,IACd,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,EACtB,GACA,QACG;AACH,UAAM,SAASF,WAAU;AACzB,UAAM,CAAC,WAAW,YAAY,IAAIG,UAAS,KAAK;AAChD,UAAM,cAAcC,QAA4B,IAAI;AACpD,UAAM,eAAeA,QAAuB,IAAI;AAEhD,wBAAoB,KAAK,MAAM,YAAY,OAA8B;AAGzE,UAAM,MAAM,eAAe;AAC3B,UAAM,iBAAiB,IAAI,aAAa;AACxC,UAAM,cAAc,iBAAiB,IAAI,cAAe,mBAAmB,CAAC;AAC5E,UAAM,mBAAmB,iBAAiB,IAAI,mBAAoB,yBAAyB,MAAM;AAAA,IAAC;AAClG,UAAM,qBAAqB,2BAA2B,iBAAiB,IAAI,qBAAqB;AAEhG,UAAM,QAAQ,cAAc,iBAAiB,IAAI,QAAQ;AACzD,UAAM,WAAW,iBAAiB,iBAAiB,IAAI,WAAW,MAAM;AAAA,IAAC;AACzE,UAAM,WAAW,gBAAgB;AACjC,UAAM,UACJ,gBACC,iBACG,MAAM;AACJ,UAAI,CAAC,IAAI,SAAU,KAAI,YAAY;AAAA,IACrC,IACA;AAGN,IAAAC,WAAU,MAAM;AACd,UAAI,CAAC,eAAgB;AACrB,YAAM,KAAK,aAAa;AACxB,UAAI,CAAC,GAAI;AACT,YAAM,KAAK,IAAI,eAAe,MAAM;AAClC,YAAI,eAAe,GAAG,YAAY;AAAA,MACpC,CAAC;AACD,SAAG,QAAQ,EAAE;AACb,UAAI,eAAe,GAAG,YAAY;AAClC,aAAO,MAAM,GAAG,WAAW;AAAA,IAE7B,GAAG,CAAC,cAAc,CAAC;AAGnB,IAAAA,WAAU,MAAM;AACd,UAAI,YAAY,SAAS;AACvB,oBAAY,QAAQ,MAAM,SAAS;AACnC,oBAAY,QAAQ,MAAM,SAAS,GAAG,YAAY,QAAQ,YAAY;AAAA,MACxE;AAAA,IACF,GAAG,CAAC,KAAK,CAAC;AAEV,IAAAA,WAAU,MAAM;AACd,YAAM,KAAK,YAAY;AACvB,UAAI,CAAC,GAAI;AACT,YAAM,WAAW,IAAI,eAAe,MAAM;AACxC,WAAG,MAAM,SAAS;AAClB,WAAG,MAAM,SAAS,GAAG,GAAG,YAAY;AAAA,MACtC,CAAC;AACD,eAAS,QAAQ,EAAE;AACnB,aAAO,MAAM,SAAS,WAAW;AAAA,IACnC,GAAG,CAAC,CAAC;AAGL,UAAM,iBAAiB,iBACrB,IAAI,WACF,gBAAAP;AAAA,MAACQ;AAAA,MAAA;AAAA,QACC,YAAW;AAAA,QACX,SAAS,MAAM;AACb,cAAI,cAAc,UAAU;AAC5B,cAAI,SAAS;AAAA,QACf;AAAA,QACA,MAAM,gBAAAR,KAAC,QAAK;AAAA,QACZ,OAAO,EAAE,QAAQ,UAAU;AAAA;AAAA,IAC7B,IAEA,gBAAAA;AAAA,MAACQ;AAAA,MAAA;AAAA,QACC,YAAW;AAAA,QACX,SAAS,MAAM,IAAI,YAAY;AAAA,QAC/B,MAAM,gBAAAR,KAAC,QAAK;AAAA,QACZ,UAAU,CAAC,MAAM,KAAK;AAAA,QACtB,OAAO,EAAE,QAAQ,UAAU;AAAA;AAAA,IAC7B,IAEA;AAEJ,WACE,gBAAAA,KAAC,SAAI,KAAK,cAAc,WAAW,OAAO,SAAS,OACjD,0BAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,OAAO,IAAI,GAAG,YAAY,IAAI,OAAO,WAAW,KAAK,EAAE,GAAG,WAAW,IAAI,OAAO,YAAY,KAAK,EAAE;AAAA,QACjH,OAAO;AAAA,UACL,QAAQ,YACJ,aAAaG,QAAO,mBAAmB,KACvC,aAAaA,QAAO,mBAAmB;AAAA,QAC7C;AAAA,QAEC;AAAA,sBAAY,SAAS,KACpB,gBAAAJ,KAAC,SAAI,WAAW,OAAO,gBACpB,sBAAY,IAAI,CAAC,MAAM;AACtB,kBAAM,MAAM,EAAE,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY,KAAK;AAC3D,mBACE,gBAAAC,MAAC,SAAe,WAAW,OAAO,gBAC/B;AAAA,gBAAE,UACD,gBAAAD;AAAA,gBAAC;AAAA;AAAA,kBACC,KAAK,EAAE;AAAA,kBACP,KAAK,EAAE,KAAK;AAAA,kBACZ,WAAW,OAAO;AAAA;AAAA,cACpB,IAEA,gBAAAC,MAAC,SAAI,WAAW,OAAO,gBACrB;AAAA,gCAAAD,KAACS,QAAA,EAAM,WAAW,OAAO,oBACtB,YAAE,KAAK,MACV;AAAA,gBACA,gBAAAT,KAAC,OAAI,YAAW,WAAU,MAAK,SAC5B,eACH;AAAA,iBACF;AAAA,cAEF,gBAAAA;AAAA,gBAACQ;AAAA,gBAAA;AAAA,kBACC,MAAM,gBAAAR,KAAC,WAAQ;AAAA,kBACf,MAAK;AAAA,kBACL,SAAS,MAAM,iBAAiB,EAAE,EAAE;AAAA,kBACpC,WAAW,OAAO;AAAA;AAAA,cACpB;AAAA,iBAtBQ,EAAE,EAuBZ;AAAA,UAEJ,CAAC,GACH;AAAA,UAGF,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,KAAK;AAAA,cACL;AAAA,cACA,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK;AAAA,cACxC,WAAW,CAAC,MAAM;AAChB,oBAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,UAAU;AACpC,oBAAE,eAAe;AACjB,4BAAU;AAAA,gBACZ;AAAA,cACF;AAAA,cACA,SAAS,MAAM,aAAa,IAAI;AAAA,cAChC,QAAQ,MAAM,aAAa,KAAK;AAAA,cAChC;AAAA,cACA,MAAM;AAAA,cACN,WAAW,OAAO;AAAA;AAAA,UACpB;AAAA,UAEA,gBAAAC,MAAC,SAAI,WAAW,OAAO,SACrB;AAAA,4BAAAA,MAAC,SAAI,WAAW,OAAO,aACpB;AAAA,oCAAsB,mBAAmB,SAAS,KACjD,gBAAAD,KAAC,6BAAiB,OAAO,oBAAoB;AAAA,cAE9C;AAAA,eACH;AAAA,YACA,gBAAAC,MAAC,SAAI,WAAW,OAAO,aACpB;AAAA;AAAA,cACA;AAAA,eACH;AAAA,aACF;AAAA,UAEA,gBAAAD;AAAA,YAAC;AAAA;AAAA,cACC,WAAW,GAAG,OAAO,QAAQ,IAAI,YAAY,OAAO,kBAAkB,OAAO,cAAc;AAAA;AAAA,UAC7F;AAAA;AAAA;AAAA,IACF,GACF;AAAA,EAEJ;AACF;AAEA,IAAO,qBAAQ;;;AEvVf,SAAS,SAAAU,QAAO,aAAoB,UAAAC,SAAQ,YAAAC,WAAU,cAAAC,aAAY,UAAAC,eAAc;AAkG1E,SACE,OAAAC,OADF,QAAAC,cAAA;AA9EN,IAAMC,aAAYC,YAAW;AAAA,EAC3B,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,IACL,SAAS;AAAA,IACT,cAAc;AAAA,IACd,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,QAAQ,aAAaC,QAAO,mBAAmB;AAAA,EACjD;AAAA,EACA,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,EACP;AAAA,EACA,aAAa;AAAA,IACX,OAAOA,QAAO;AAAA,EAChB;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,UAAU;AAAA,IACV,KAAK;AAAA,EAEP;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,eAAe;AAAA,IACf,KAAK;AAAA,EAEP;AAAA,EACA,eAAe;AAAA,IACb,gBAAgB;AAAA,EAClB;AAAA,EACA,MAAM;AAAA,IACJ,OAAOA,QAAO;AAAA;AAAA,EAEhB;AACF,CAAC;AAED,SAAS,sBAAsB,SAAoC;AACjE,MAAI,QAAQ,SAAS,EAAG,QAAO;AAC/B,QAAM,cAAc,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtE,MAAI,cAAc,GAAI,QAAO;AAC7B,MAAI,QAAQ,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAG,QAAO;AACjD,SAAO;AACT;AAEA,IAAM,eAA4C,CAAC;AAAA,EACjD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AACF,MAAM;AACJ,QAAM,SAASF,WAAU;AACzB,QAAM,MAAM,eAAe;AAC3B,QAAM,WAAW,gBAAgB,IAAI;AACrC,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,WAAW,iBAAiB,CAAC,aAAqB,IAAI,gBAAgB,SAAS,IAAI,QAAQ;AACjG,QAAM,aAAa,SAAS,QAAQ;AACpC,QAAM,aAAa,eAAe;AAClC,QAAM,mBACJ,IAAI,0BAA0B,eAAe,SAAS,KAClD,IAAI,2BACJ;AACN,QAAM,QAAQ,sBAAsB,SAAS,OAAO;AAEpD,SACE,gBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,OAAO,IAAI,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE;AAAA,MAC5D;AAAA,MACA,MAAK;AAAA,MACL,cAAY,SAAS;AAAA,MAErB;AAAA,wBAAAA,OAAC,SAAI,WAAW,OAAO,QACrB;AAAA,0BAAAD,MAAC,eAAa,mBAAS,UAAS;AAAA,UAC/B,SAAS,eACR,gBAAAA,MAACK,QAAA,EAAM,WAAW,OAAO,aAAc,mBAAS,aAAY;AAAA,WAEhE;AAAA,QACA,gBAAAL,MAAC,SAAI,WAAW,QAAQ,OAAO,gBAAgB,OAAO,YACnD,mBAAS,QAAQ,IAAI,CAAC,QAAQ;AAC7B,gBAAM,WACJ,eAAe,IAAI,MAAM,kBAAkB,aAAa,IAAI;AAC9D,gBAAM,iBAAiB,IAAI,eAAe,IAAI,WAAW,WAAW;AACpE,gBAAM,aAAa,WAAW,YAAY;AAC1C,iBACE,gBAAAA;AAAA,YAACM;AAAA,YAAA;AAAA,cAEC;AAAA,cACA,UAAU,YAAY;AAAA,cACtB,SAAS,MAAM,SAAS,IAAI,EAAE;AAAA,cAC9B,WAAW,QAAQ,OAAO,gBAAgB;AAAA,cAC1C,OAAO;AAAA,gBACL,QAAO;AAAA,cACT;AAAA,cAEC,cAAI;AAAA;AAAA,YATA,IAAI;AAAA,UAUX;AAAA,QAEJ,CAAC,GACH;AAAA,QACC,oBAAoB,CAAC,cACpB,gBAAAN,MAACO,WAAA,EAAS,WAAW,OAAO,MAAM,uDAElC;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAO,wBAAQ;;;Ab2LT,SAuBF,YAAAC,WAvBE,OAAAC,OAoEE,QAAAC,cApEF;AAxFN,IAAMC,cAAYC,aAAW;AAAA,EAC3B,WAAW;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,EACd;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,eAAe;AAAA,IACf,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,gBAAgB;AAAA,EAClB;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,gBAAgB;AAAA,EAClB;AACF,CAAC;AAqBD,IAAM,0BAA0B,CAC9B,MACA,YAC6B;AAC7B,MAAI,YAAY,kBAAkB,SAAS,UAAa,SAAS,YAAY;AAC3E,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,IAAM,aAAwC,CAAC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,gBACJ,mBAAmB,UAAa,OAAO,mBAAmB;AAC5D,QAAM,cACJ,OAAO,mBAAmB,WACxB,gBAAAH,MAAC,UAAQ,0BAAe,IAExB;AAEJ,QAAM,SAASE,YAAU;AACzB,QAAM,kBAAkBE,QAAuB,IAAI;AACnD,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAwB,IAAI;AAC1D,EAAAC,iBAAgB,MAAM;AACpB,UAAM,KAAK,gBAAgB,SAAS,QAAQ,sBAAsB;AAClE,eAAW,IAAI,aAAa,oBAAoB,KAAK,IAAI;AAAA,EAC3D,GAAG,CAAC,CAAC;AACL,QAAM,oBAAoB,wBAAwB,UAAU,OAAO;AACnE,QAAM,EAAE,UAAU,UAAU,iBAAiB,yBAAyB,IAAI,eAAe;AACzF,QAAM,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,QAAQ,KAAK,CAAC;AAC7D,QAAM,qBAAqB,oBAAoB,QAAQ,6BAA6B;AACpF,QAAM,gBAAgB,YAAY;AAElC,QAAM,gBAAgB,kBAAkB;AACxC,QAAM,QAAQ,aAAa;AAC3B,QAAM,mBAAmB,gBAAgB,mBAAmB,KAAK,KAAK;AACtE,QAAM,gBAAgB,gBAAgB,gBAAgB,KAAK,KAAK;AAEhE,SACE,gBAAAL,OAAAF,WAAA,EACE;AAAA,oBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,OAAO;AAAA,UACL,UAAU,SAAS,CAAC,gBAAgB,IAAI;AAAA,UACxC,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,WAAW;AAAA,UACX,YAAY;AAAA,QACd;AAAA;AAAA,IACF;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,OAAO;AAAA,QAClB,OAAO;AAAA,UACL,MAAM,SAAS,CAAC,gBAAgB,SAAS;AAAA,UACzC,UAAU,SAAS,CAAC,gBAAgB,YAAY;AAAA,QAClD;AAAA,QAEC,kBACC,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,OAAO;AAAA,YAClB,OACE,gBACI;AAAA,cACE,MAAM;AAAA,cACN,gBAAgB;AAAA,cAChB,cAAc;AAAA,YAChB,IACA;AAAA,YAGL;AAAA;AAAA,QACH,IAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YACV;AAAA;AAAA,QACF;AAAA;AAAA,IAEJ;AAAA,IACA,gBAAAA,MAAC,SAAI,OAAO,EAAE,QAAQ,QAAQ,KAAK,GAAG,YAAY,cAAc,GAAG;AAAA,IACnE,gBAAAA,MAAC,SAAI,WAAW,OAAO,UACrB,0BAAAC,OAAC,SAAI,WAAW,OAAO,YAAY,OAAO,EAAE,eAAe,SAAS,GACjE;AAAA,yBAAmB,gBAAAD,MAAC,yBAAa;AAAA,MAClC,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,aACE,qBACI,0CACA;AAAA,UAEN,UAAU;AAAA,UACV;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OACF,GACF;AAAA,IACC,SAAS,qBACR,gBAAAA,MAAC,SAAI,WAAW,OAAO,gBAAiB,6BAAkB;AAAA,IAE5D,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU,SAAS,CAAC,gBAAgB,IAAI;AAAA,UACxC,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,WAAW;AAAA,UACX,YAAY;AAAA,QACd;AAAA;AAAA,IACF;AAAA,IACA,gBAAAA;AAAA,MAACO;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO;AAAA,UACP,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,SAAS;AAAA,QACX;AAAA,QACD;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;AAIA,IAAM,OAA4B,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AAIJ,QAAM,aAAa,eAAe,GAAG;AAErC,QAAM,cAAc,OAAO,YAAY;AAEvC,QAAM,6BAA6B,sBAAsB,YAAY;AAErE,SACE,gBAAAP;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,oBAAoB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,eAAQ;;;AcndR,SAAS,cAAc,EAAE,UAAU,QAAQ,GAAuC;AACvF,SAAO,iBAAiB,OAAO,SAAS,OAAO;AAC7C,UAAM,cAAc,MAAM,QAAQ;AAAA,MAChC,MAAM,IAAI,OAAO,UAAU;AAAA,QACzB,MAAM,KAAK;AAAA,QACX,WAAW,KAAK;AAAA,QAChB,MAAM,MAAM,aAAa,IAAI;AAAA,MAC/B,EAAE;AAAA,IACJ;AAEA,UAAM,MAAM,MAAM,MAAM,UAAU;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oBAAoB,GAAG,QAAQ;AAAA,MAC1D,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,YAAY,CAAC;AAAA,IACtD,CAAC;AAED,QAAI,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM;AACxB,YAAM,OAAO,OAAO,IAAI,MAAM,GAAG,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE,GAAG;AAAA,QAChE,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,MAClB,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,IAAI,KAAK,UAAU;AAClC,UAAM,UAAU,IAAI,YAAY;AAChC,QAAI,SAAS;AAEb,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,YAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,eAAS,MAAM,IAAI,KAAK;AAExB,iBAAW,QAAQ,OAAO;AAExB,cAAM,OAAO,KAAK,WAAW,QAAQ,IAAI,KAAK,MAAM,CAAC,IAAI;AACzD,YAAI,CAAC,QAAQ,SAAS,SAAU;AAEhC,YAAI;AACF,gBAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,gBAAM;AAAA,QACR,QAAQ;AAEN,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACOO,IAAM,oBAA8B;AAAA,EACzC,MAAM;AAAA,EACN,aACE;AAAA,EAKF,YAAY;AAAA,IACV,MAAM;AAAA,IACN,YAAY;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,YACV,SAAS;AAAA,cACP,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,YAAY;AAAA,cACV,MAAM;AAAA,cACN,aACE;AAAA,YAEJ;AAAA,YACA,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,MAAM,CAAC,WAAW,eAAe,WAAW;AAAA,YAC9C;AAAA,UACF;AAAA,UACA,UAAU,CAAC,WAAW,QAAQ;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU,CAAC,OAAO;AAAA,EACpB;AACF;AAGO,IAAM,wBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,aACE;AAAA,EAIF,YAAY;AAAA,IACV,MAAM;AAAA,IACN,YAAY;AAAA,MACV,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,aAAa;AAAA,QACX,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,YACV,IAAI,EAAE,MAAM,SAAS;AAAA,YACrB,OAAO,EAAE,MAAM,SAAS;AAAA,YACxB,aAAa,EAAE,MAAM,SAAS;AAAA,YAC9B,UAAU;AAAA,cACR,MAAM;AAAA,cACN,aACE;AAAA,YAEJ;AAAA,UACF;AAAA,UACA,UAAU,CAAC,MAAM,OAAO;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU,CAAC,YAAY,SAAS;AAAA,EAClC;AACF;AAGO,IAAM,oBAA8B;AAAA,EACzC,MAAM;AAAA,EACN,aACE;AAAA,EAMF,YAAY;AAAA,IACV,MAAM;AAAA,IACN,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,MAAM,CAAC,OAAO,MAAM;AAAA,QACpB,aAAa;AAAA,MACf;AAAA,MACA,OAAO,EAAE,MAAM,UAAU,aAAa,+BAA+B;AAAA,MACrE,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,YACV,SAAS;AAAA,cACP,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,YACA,OAAO;AAAA,cACL,MAAM;AAAA,cACN,aAAa;AAAA,YACf;AAAA,UACF;AAAA,UACA,UAAU,CAAC,WAAW,OAAO;AAAA,QAC/B;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,aACE;AAAA,QAEF,OAAO,EAAE,MAAM,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,UAAU,CAAC,QAAQ,SAAS,QAAQ,UAAU,MAAM;AAAA,EACtD;AACF;AAIA,SAAS,oBAAuC;AAC9C,QAAM,MAAM,oBAAI,IAA2B;AAC3C,SAAO;AAAA,IACL,KAAK,CAAC,OAAO,IAAI,IAAI,EAAE;AAAA,IACvB,KAAK,CAAC,IAAI,SAAS;AACjB,UAAI,IAAI,IAAI,IAAI;AAAA,IAClB;AAAA,IACA,QAAQ,CAAC,OAAO;AACd,UAAI,OAAO,EAAE;AAAA,IACf;AAAA,EACF;AACF;AAGA,SAAS,uBAAuB,SAAwC;AACtE,QAAM,MAAsB,CAAC;AAC7B,aAAW,KAAK,SAAS;AACvB,QAAI,EAAE,SAAS,OAAQ,KAAI,KAAK,EAAE,MAAM,QAAQ,SAAS,EAAE,QAAQ,CAAC;AAAA,aAC3D,EAAE,SAAS,YAAa,KAAI,KAAK,EAAE,MAAM,aAAa,SAAS,EAAE,QAAQ,CAAC;AAAA,EACrF;AACA,SAAO;AACT;AAGA,SAAS,aAAa,OAA4B;AAChD,QAAM,QAAS,OAAsC;AACrD,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,IAAI,CAAC,GAAG,MAAgB;AACnC,UAAM,IAAK,KAAK,CAAC;AACjB,WAAO;AAAA,MACL,IAAI,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK,QAAQ,CAAC;AAAA,MAC/C,SAAS,OAAO,EAAE,WAAW,EAAE;AAAA,MAC/B,YAAY,OAAO,EAAE,eAAe,WAAW,EAAE,aAAa;AAAA,MAC9D,QACE,EAAE,WAAW,iBAAiB,EAAE,WAAW,cACvC,EAAE,SACF;AAAA,IACR;AAAA,EACF,CAAC;AACH;AAGA,SAAS,eAAe,OAAuC;AAC7D,QAAM,IAAK,SAAS,CAAC;AACrB,QAAM,OAAO,EAAE,SAAS,SAAS,SAAS;AAC1C,QAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;AACtD,QAAM,OAAO,OAAO,EAAE,SAAS,WAAW,EAAE,OAAO;AACnD,QAAM,YAAY,MAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,SAAS,CAAC;AACxD,QAAM,SAAS,UACZ,IAAI,CAAC,GAAG,MAAM;AACb,UAAM,MAAO,KAAK,CAAC;AACnB,UAAM,UAAU,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU;AAChE,UAAM,QAAQ,OAAO,IAAI,UAAU,WAAW,IAAI,QAAQ,WAAW,UAAU,CAAC;AAChF,WAAO,UAAU,EAAE,SAAS,MAAM,IAAI;AAAA,EACxC,CAAC,EACA,OAAO,CAAC,MAA+C,MAAM,IAAI;AACpE,QAAM,OAAO,MAAM,QAAQ,EAAE,IAAI,IAC5B,EAAE,KAAK;AAAA,IACN,CAAC,MAAM,KAAK,OAAO,MAAM;AAAA,EAC3B,IACA,CAAC;AACL,MAAI,CAAC,QAAQ,OAAO,WAAW,KAAK,KAAK,WAAW,EAAG,QAAO;AAC9D,SAAO,EAAE,MAAM,OAAO,MAAM,QAAQ,KAAK;AAC3C;AAGA,SAAS,cAAc,IAAmC;AACxD,QAAM,QAAS,GAAG,SAAS,CAAC;AAC5B,QAAM,aAAa,MAAM,QAAQ,MAAM,OAAO,IAAI,MAAM,UAAU,CAAC;AACnE,QAAM,UAA4B,WAAW,IAAI,CAAC,GAAG,MAAM;AACzD,UAAM,MAAO,KAAK,CAAC;AACnB,WAAO;AAAA,MACL,IAAI,OAAO,IAAI,OAAO,WAAW,IAAI,KAAK,OAAO,CAAC;AAAA,MAClD,OAAO,OAAO,IAAI,SAAS,UAAU,IAAI,CAAC,EAAE;AAAA,MAC5C,aAAa,OAAO,IAAI,gBAAgB,WAAW,IAAI,cAAc;AAAA,MACrE,UAAU,IAAI,aAAa,OAAO,OAAO;AAAA,IAC3C;AAAA,EACF,CAAC;AACD,SAAO;AAAA;AAAA;AAAA,IAGL,IAAI,GAAG;AAAA,IACP,UAAU,OAAO,MAAM,YAAY,UAAU;AAAA,IAC7C,aACE,OAAO,MAAM,gBAAgB,WAAW,MAAM,cAAc;AAAA,IAC9D;AAAA,EACF;AACF;AAuBO,SAAS,mBAAmB,SAAkD;AACnF,QAAM,EAAE,WAAW,QAAQ,QAAQ,CAAC,GAAG,WAAW,EAAE,IAAI;AACxD,QAAM,QAAQ,QAAQ,gBAAgB,kBAAkB;AACxD,QAAM,eAAe,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC;AAC/D,QAAM,YAAwB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EAC5B;AAEA,SAAO,iBACL,QACA,SACA,aAC2B;AAC3B,UAAM,iBAAiB,QACpB,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EACjC,IAAI,CAAC,MAAM,EAAE,OAAO;AACvB,UAAM,kBACJ,CAAC,QAAQ,GAAG,cAAc,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM,KAAK;AAG9D,UAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,QAAI;AACJ,QAAI;AAEJ,UAAM,WACJ,MAAM,SAAS,UACf,KAAK,SAAS,uBACd,OAAO,KAAK,UAAU,eAAe,WAChC,KAAK,SAAS,aACf;AACN,UAAM,WAAW,WAAW,MAAM,MAAM,IAAI,QAAQ,IAAI;AAExD,QAAI,YAAY,UAAU;AACxB,YAAM,MAAM,OAAO,QAAQ;AAC3B,YAAM,OAAO,KAAM;AACnB,YAAM,SACH,OAAO,KAAK,SAAS,YAAY,KAAK,QACtC,OAAO,KAAK,UAAU,YAAY,KAAK,SACxC,KAAM;AACR,iBAAW;AAAA,QACT,GAAG,SAAS;AAAA,QACZ;AAAA,UACE,MAAM;AAAA,UACN,YAAY,SAAS;AAAA,UACrB,SAAS,mBAAmB,MAAM;AAAA,QACpC;AAAA,MACF;AAAA,IACF,OAAO;AAGL,iBAAW,uBAAuB,OAAO;AACzC,6BAAuB,YAAY,SAAS,IAAI,cAAc;AAAA,IAChE;AAGA,aAAS,OAAO,GAAG,OAAO,UAAU,QAAQ;AAC1C,YAAM,SAAS,UAAU;AAAA,QACvB,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,aAAa,SAAS,IAAI,uBAAuB;AAAA,MACnD,CAAC;AAED,UAAI,gBAAgB;AACpB,UAAI;AACJ,YAAM,YAAwB,CAAC;AAE/B,uBAAiB,MAAM,QAAQ;AAC7B,YAAI,GAAG,SAAS,QAAQ;AACtB,2BAAiB,GAAG;AACpB,gBAAM,GAAG;AAAA,QACX,WAAW,GAAG,SAAS,aAAa;AAClC,gBAAM,EAAE,MAAM,aAAa,SAAS,GAAG,MAAM;AAAA,QAC/C,WAAW,GAAG,SAAS,aAAa;AAClC,oBAAU,KAAK,GAAG,QAAQ;AAAA,QAC5B,WAAW,GAAG,SAAS,OAAO;AAC5B,yBAAe,GAAG;AAAA,QACpB;AAAA,MACF;AAEA,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,GAAI,UAAU,SAAS,IAAI,EAAE,UAAU,IAAI,CAAC;AAAA,QAC5C,GAAI,iBAAiB,SAAY,EAAE,KAAK,aAAa,IAAI,CAAC;AAAA,MAC5D,CAAC;AAGD,UAAI,UAAU,WAAW,EAAG;AAE5B,iBAAW,MAAM,WAAW;AAC1B,YAAI,GAAG,SAAS,kBAAkB,MAAM;AACtC,gBAAM,EAAE,MAAM,SAAS,OAAO,aAAa,GAAG,KAAK,EAAE;AACrD,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,YAAY,GAAG;AAAA,YACf,SAAS;AAAA,UACX,CAAC;AAAA,QACH,WAAW,GAAG,SAAS,sBAAsB,MAAM;AACjD,gBAAM,EAAE,MAAM,YAAY,UAAU,cAAc,EAAE,EAAE;AAGtD,gBAAM,MAAM,IAAI,GAAG,IAAI,EAAE,UAAU,mBAAmB,GAAG,GAAG,CAAC;AAC7D;AAAA,QACF,WAAW,GAAG,SAAS,kBAAkB,MAAM;AAC7C,gBAAM,OAAO,eAAe,GAAG,KAAK;AACpC,cAAI,MAAM;AACR,kBAAM,EAAE,MAAM,SAAS,KAAK;AAC5B,qBAAS,KAAK;AAAA,cACZ,MAAM;AAAA,cACN,YAAY,GAAG;AAAA,cACf,SAAS;AAAA,YACX,CAAC;AAAA,UACH,OAAO;AACL,qBAAS,KAAK;AAAA,cACZ,MAAM;AAAA,cACN,YAAY,GAAG;AAAA,cACf,SACE;AAAA,YAEJ,CAAC;AAAA,UACH;AAAA,QACF,OAAO;AACL,gBAAM,OAAO,aAAa,IAAI,GAAG,IAAI;AACrC,cAAI;AACJ,cAAI,CAAC,MAAM;AACT,sBAAU,wBAAwB,GAAG,IAAI;AAAA,UAC3C,OAAO;AACL,gBAAI;AACF,yBAAW,MAAM,KAAK,QAAQ,GAAG,KAAK,GAAG;AAAA,YAC3C,SAAS,KAAK;AACZ,wBAAU,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,YACtE;AAAA,UACF;AACA,mBAAS,KAAK,EAAE,MAAM,QAAQ,YAAY,GAAG,IAAI,QAAQ,CAAC;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAEA,UAAM;AAAA,EACR;AACF;;;ACpeA,YAAYQ,YAAW;AAkOnB,gBAAAC,aAAA;AAzLJ,IAAM,qBAA2B;AAAA,EAC/B;AACF;AAEO,SAAS,iBAA0C;AACxD,QAAM,QAAc,kBAAW,kBAAkB;AACjD,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,2BACd,iBAA+B,CAAC,GACZ;AACpB,MAAI,UAAwB,CAAC,GAAG,cAAc;AAC9C,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,KAAK,CAAC,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,IAC5C,QAAQ,CAAC,YAAY;AACnB,YAAM,SAAqB;AAAA,QACzB,IAAI,SAAS,MAAM,OAAO,WAAW;AAAA,QACrC,OAAO,SAAS,SAAS;AAAA,QACzB,UAAU,SAAS,YAAY,CAAC;AAAA,QAChC,WAAW,KAAK,IAAI;AAAA,QACpB,WAAW,KAAK,IAAI;AAAA,MACtB;AACA,gBAAU,CAAC,QAAQ,GAAG,OAAO;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,MAAM,CAAC,WAAW;AAChB,YAAM,MAAM,QAAQ,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE;AACvD,YAAM,OAAmB,EAAE,GAAG,QAAQ,WAAW,KAAK,IAAI,EAAE;AAC5D,gBAAU,OAAO,IACb,QAAQ,IAAI,CAAC,GAAG,MAAO,MAAM,MAAM,OAAO,CAAE,IAC5C,CAAC,MAAM,GAAG,OAAO;AAAA,IACvB;AAAA,IACA,QAAQ,CAAC,IAAI,aAAa;AACxB,gBAAU,QAAQ;AAAA,QAAI,CAAC,MACrB,EAAE,OAAO,KAAK,EAAE,GAAG,GAAG,OAAO,UAAU,WAAW,KAAK,IAAI,EAAE,IAAI;AAAA,MACnE;AAAA,IACF;AAAA,IACA,QAAQ,CAAC,OAAO;AACd,gBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AAAA,IAC7C;AAAA,EACF;AACF;AAcO,SAAS,oBAAoB;AAAA,EAClC,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AACF,GAA6B;AAC3B,QAAM,UAAgB;AAAA,IACpB,MAAM,mBAAmB,2BAA2B;AAAA,IACpD,CAAC,eAAe;AAAA,EAClB;AAEA,QAAM,CAAC,SAAS,UAAU,IAAU,gBAAuB,CAAC,CAAC;AAC7D,QAAM,CAAC,gBAAgB,iBAAiB,IAAU;AAAA,IAChD;AAAA,EACF;AACA,QAAM,CAAC,WAAW,YAAY,IAAU,gBAAS,IAAI;AAErD,QAAM,eAAe,iBAAiB;AACtC,QAAM,iBAAiB,eAAe,eAAe;AAErD,QAAM,oBAA0B;AAAA,IAC9B,CAAC,OAA2B;AAC1B,UAAI,CAAC,aAAc,mBAAkB,EAAE;AACvC,6BAAuB,EAAE;AAAA,IAC3B;AAAA,IACA,CAAC,cAAc,oBAAoB;AAAA,EACrC;AAEA,EAAM,iBAAU,MAAM;AACpB,QAAI,YAAY;AAChB,KAAC,YAAY;AACX,mBAAa,IAAI;AACjB,YAAM,SAAS,MAAM,QAAQ,KAAK;AAClC,UAAI,UAAW;AACf,iBAAW,MAAM;AACjB,mBAAa,KAAK;AAAA,IACpB,GAAG;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,eAAqB;AAAA,IACzB,OAAO,YAAkC;AACvC,YAAM,SAAS,MAAM,QAAQ,OAAO,OAAO;AAC3C,iBAAW,CAAC,SAAS,CAAC,QAAQ,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE,CAAC,CAAC;AACxE,aAAO;AAAA,IACT;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,eAAqB;AAAA,IACzB,OAAO,IAAY,aAAqB;AACtC,YAAM,QAAQ,OAAO,IAAI,QAAQ;AACjC;AAAA,QAAW,CAAC,SACV,KAAK;AAAA,UAAI,CAAC,MACR,EAAE,OAAO,KAAK,EAAE,GAAG,GAAG,OAAO,UAAU,WAAW,KAAK,IAAI,EAAE,IAAI;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,eAAqB;AAAA,IACzB,OAAO,OAAe;AACpB,YAAM,QAAQ,OAAO,EAAE;AACvB,iBAAW,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AACpD,UAAI,mBAAmB,GAAI,mBAAkB,MAAS;AAAA,IACxD;AAAA,IACA,CAAC,SAAS,gBAAgB,iBAAiB;AAAA,EAC7C;AAEA,QAAM,aAAmB,cAAO,OAAO;AACvC,aAAW,UAAU;AAErB,QAAM,uBAA6B;AAAA,IACjC,CAAC,IAAY,aAA4B;AACvC,YAAM,WAAW,WAAW,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE;AAC3D,UAAI,CAAC,SAAU;AACf,YAAM,OAAmB;AAAA,QACvB,GAAG;AAAA,QACH;AAAA,QACA,WAAW,KAAK,IAAI;AAAA,MACtB;AACA,iBAAW,CAAC,SAAS,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,OAAO,CAAE,CAAC;AAC9D,WAAK,QAAQ,KAAK,IAAI;AAAA,IACxB;AAAA,IACA,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,eAAqB;AAAA,IACzB,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,cAAc;AAAA,IACjD,CAAC,SAAS,cAAc;AAAA,EAC1B;AAEA,QAAM,QAAc;AAAA,IAClB,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAA,MAAC,mBAAmB,UAAnB,EAA4B,OAC1B,UACH;AAEJ;;;AC1NO,IAAMC,QAUT,OAAO,OAAO,cAAW;AAAA,EAC3B,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAAA,EACd,mBAAmB;AACrB,CAAC;AAEM,IAAMC,sBAAqB;AAC3B,IAAMC,iBAAgB;","names":["useLayoutEffect","useRef","useState","Caption1","makeStyles","Button","makeStyles","tokens","jsx","jsxs","useStyles","makeStyles","tokens","input","attachments","Button","React","useEffect","useLayoutEffect","useRef","useState","Body1","Button","Caption1","makeStyles","tokens","useState","useEffect","useRef","makeStyles","tokens","jsx","jsxs","useStyles","Body1","Button","makeStyles","tokens","jsx","jsxs","useStyles","useState","useEffect","useRef","Body1","makeStyles","tokens","jsx","jsxs","useStyles","useState","Body1","makeStyles","tokens","jsx","jsxs","useStyles","jsx","jsxs","useStyles","makeStyles","tokens","useRef","useState","useLayoutEffect","useEffect","Caption1","Button","Body1","React","useRef","useState","useEffect","Body1","Button","makeStyles","tokens","useRef","Button","Fragment","jsx","jsxs","useRef","Button","jsx","jsxs","useStyles","makeStyles","tokens","useState","useRef","useEffect","Button","Body1","Body1","Button","Caption1","makeStyles","tokens","jsx","jsxs","useStyles","makeStyles","tokens","Body1","Button","Caption1","Fragment","jsx","jsxs","useStyles","makeStyles","useRef","useState","useLayoutEffect","Caption1","React","jsx","Chat","normalizeChatError","createHandler"]}
|