vanilla-agent 1.9.0 → 1.10.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/README.md +246 -0
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +277 -1
- package/dist/index.d.ts +277 -1
- package/dist/index.global.js +26 -26
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +141 -12
- package/src/components/forms.ts +1 -0
- package/src/components/registry.ts +87 -0
- package/src/index.ts +22 -2
- package/src/plugins/registry.ts +1 -0
- package/src/plugins/types.ts +1 -0
- package/src/types.ts +150 -0
- package/src/ui.ts +69 -6
- package/src/utils/component-middleware.ts +137 -0
- package/src/utils/component-parser.ts +119 -0
- package/src/utils/constants.ts +1 -0
- package/src/utils/dom.ts +1 -0
- package/src/utils/formatting.ts +33 -8
- package/src/utils/positioning.ts +1 -0
- package/src/utils/theme.ts +1 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/postprocessors.ts","../src/utils/formatting.ts","../src/client.ts","../src/session.ts","../src/utils/theme.ts","../src/utils/icons.ts","../src/utils/dom.ts","../src/utils/constants.ts","../src/utils/positioning.ts","../src/components/launcher.ts","../src/components/panel.ts","../src/components/message-bubble.ts","../src/components/reasoning-bubble.ts","../src/components/tool-bubble.ts","../src/components/suggestions.ts","../src/components/forms.ts","../src/plugins/registry.ts","../src/defaults.ts","../src/utils/events.ts","../src/utils/actions.ts","../src/ui.ts","../src/runtime/init.ts","../src/utils/storage.ts","../src/index.ts"],"sourcesContent":["import { marked } from \"marked\";\n\nmarked.setOptions({ breaks: true });\n\n/**\n * Basic markdown renderer. Remember to sanitize the returned HTML if you render\n * untrusted content in your host page.\n */\nexport const markdownPostprocessor = (text: string): string => {\n return marked.parse(text) as string;\n};\n\n/**\n * Escapes HTML entities. Used as the default safe renderer.\n */\nexport const escapeHtml = (text: string): string =>\n text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n\nconst escapeAttribute = (value: string) =>\n value.replace(/\"/g, \""\").replace(/</g, \"<\").replace(/>/g, \">\");\n\nconst makeToken = (idx: number) => `%%FORM_PLACEHOLDER_${idx}%%`;\n\nconst directiveReplacer = (source: string, placeholders: Array<{ token: string; type: string }>) => {\n let working = source;\n\n // JSON directive pattern e.g. <Directive>{\"component\":\"form\",\"type\":\"init\"}</Directive>\n working = working.replace(/<Directive>([\\s\\S]*?)<\\/Directive>/gi, (match, jsonText) => {\n try {\n const parsed = JSON.parse(jsonText.trim());\n if (parsed && typeof parsed === \"object\" && parsed.component === \"form\" && parsed.type) {\n const token = makeToken(placeholders.length);\n placeholders.push({ token, type: String(parsed.type) });\n return token;\n }\n } catch (error) {\n return match;\n }\n return match;\n });\n\n // XML-style directive e.g. <Form type=\"init\" />\n working = working.replace(/<Form\\s+type=\"([^\"]+)\"\\s*\\/>/gi, (_, type) => {\n const token = makeToken(placeholders.length);\n placeholders.push({ token, type });\n return token;\n });\n\n return working;\n};\n\n/**\n * Converts special directives (either `<Form type=\"init\" />` or\n * `<Directive>{\"component\":\"form\",\"type\":\"init\"}</Directive>`) into placeholder\n * elements that the widget upgrades after render. Remaining text is rendered as\n * Markdown.\n */\nexport const directivePostprocessor = (text: string): string => {\n const placeholders: Array<{ token: string; type: string }> = [];\n const withTokens = directiveReplacer(text, placeholders);\n let html = markdownPostprocessor(withTokens);\n\n placeholders.forEach(({ token, type }) => {\n const tokenRegex = new RegExp(token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"g\");\n const safeType = escapeAttribute(type);\n const replacement = `<div class=\"tvw-form-directive\" data-tv-form=\"${safeType}\"></div>`;\n html = html.replace(tokenRegex, replacement);\n });\n\n return html;\n};\n","import { AgentWidgetReasoning, AgentWidgetToolCall, AgentWidgetStreamParser, AgentWidgetStreamParserResult } from \"../types\";\nimport { parse as parsePartialJson, STR, OBJ } from \"partial-json\";\n\nexport const formatUnknownValue = (value: unknown): string => {\n if (value === null) return \"null\";\n if (value === undefined) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n try {\n return JSON.stringify(value, null, 2);\n } catch (error) {\n return String(value);\n }\n};\n\nexport const formatReasoningDuration = (reasoning: AgentWidgetReasoning) => {\n const end = reasoning.completedAt ?? Date.now();\n const start = reasoning.startedAt ?? end;\n const durationMs =\n reasoning.durationMs !== undefined\n ? reasoning.durationMs\n : Math.max(0, end - start);\n const seconds = durationMs / 1000;\n if (seconds < 0.1) {\n return \"Thought for <0.1 seconds\";\n }\n const formatted =\n seconds >= 10\n ? Math.round(seconds).toString()\n : seconds.toFixed(1).replace(/\\.0$/, \"\");\n return `Thought for ${formatted} seconds`;\n};\n\nexport const describeReasonStatus = (reasoning: AgentWidgetReasoning) => {\n if (reasoning.status === \"complete\") return formatReasoningDuration(reasoning);\n if (reasoning.status === \"pending\") return \"Waiting\";\n return \"\";\n};\n\nexport const formatToolDuration = (tool: AgentWidgetToolCall) => {\n const durationMs =\n typeof tool.duration === \"number\"\n ? tool.duration\n : typeof tool.durationMs === \"number\"\n ? tool.durationMs\n : Math.max(\n 0,\n (tool.completedAt ?? Date.now()) -\n (tool.startedAt ?? tool.completedAt ?? Date.now())\n );\n const seconds = durationMs / 1000;\n if (seconds < 0.1) {\n return \"Used tool for <0.1 seconds\";\n }\n const formatted =\n seconds >= 10\n ? Math.round(seconds).toString()\n : seconds.toFixed(1).replace(/\\.0$/, \"\");\n return `Used tool for ${formatted} seconds`;\n};\n\nexport const describeToolStatus = (status: AgentWidgetToolCall[\"status\"]) => {\n if (status === \"complete\") return \"\";\n if (status === \"pending\") return \"Starting\";\n return \"Running\";\n};\n\nexport const describeToolTitle = (tool: AgentWidgetToolCall) => {\n if (tool.status === \"complete\") {\n return formatToolDuration(tool);\n }\n return \"Using tool...\";\n};\n\n/**\n * Creates a regex-based parser for extracting text from JSON streams.\n * This is a simpler alternative to schema-stream that uses regex to extract\n * the 'text' field incrementally as JSON streams in.\n * \n * This can be used as an alternative parser option.\n */\nconst createRegexJsonParserInternal = (): {\n processChunk(accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null>;\n getExtractedText(): string | null;\n close?(): Promise<void>;\n} => {\n let extractedText: string | null = null;\n let processedLength = 0;\n \n // Regex-based extraction for incremental JSON parsing\n const extractTextFromIncompleteJson = (jsonString: string): string | null => {\n // Look for \"text\": \"value\" pattern, handling incomplete strings\n // Match: \"text\": \" followed by any characters (including incomplete)\n const textFieldRegex = /\"text\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.|\")*?)\"/;\n const match = jsonString.match(textFieldRegex);\n \n if (match && match[1]) {\n // Unescape the string value\n try {\n // Replace escaped characters\n let unescaped = match[1]\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n return unescaped;\n } catch {\n return match[1];\n }\n }\n \n // Also try to match incomplete text field (text field that hasn't closed yet)\n // Look for \"text\": \" followed by content that may not be closed\n const incompleteTextFieldRegex = /\"text\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)/;\n const incompleteMatch = jsonString.match(incompleteTextFieldRegex);\n \n if (incompleteMatch && incompleteMatch[1]) {\n // Unescape the partial string value\n try {\n let unescaped = incompleteMatch[1]\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n return unescaped;\n } catch {\n return incompleteMatch[1];\n }\n }\n \n return null;\n };\n \n return {\n getExtractedText: () => extractedText,\n processChunk: async (accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null> => {\n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedText !== null\n ? { text: extractedText, raw: accumulatedContent }\n : null;\n }\n \n // Validate that the accumulated content looks like valid JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n \n // Try to extract text field using regex\n const extracted = extractTextFromIncompleteJson(accumulatedContent);\n if (extracted !== null) {\n extractedText = extracted;\n }\n \n // Update processed length\n processedLength = accumulatedContent.length;\n \n // Return both the extracted text and raw JSON\n if (extractedText !== null) {\n return {\n text: extractedText,\n raw: accumulatedContent\n };\n }\n\n return null;\n },\n close: async () => {\n // No cleanup needed for regex-based parser\n }\n };\n};\n\n/**\n * Extracts the text field from JSON (works with partial JSON during streaming).\n * For complete JSON, uses fast path. For incomplete JSON, returns null (use stateful parser in client.ts).\n * \n * @param jsonString - The JSON string (can be partial/incomplete during streaming)\n * @returns The extracted text value, or null if not found or invalid\n */\nexport const extractTextFromJson = (jsonString: string): string | null => {\n try {\n // Try to parse complete JSON first (fast path)\n const parsed = JSON.parse(jsonString);\n if (parsed && typeof parsed === \"object\" && typeof parsed.text === \"string\") {\n return parsed.text;\n }\n } catch {\n // For incomplete JSON, return null - use stateful parser in client.ts\n return null;\n }\n return null;\n};\n\n/**\n * Plain text parser - passes through text as-is without any parsing.\n * This is the default parser.\n */\nexport const createPlainTextParser = (): AgentWidgetStreamParser => {\n const parser: AgentWidgetStreamParser = {\n processChunk: (accumulatedContent: string): string | null => {\n // Always return null to indicate this isn't a structured format\n // Content will be displayed as plain text\n return null;\n },\n getExtractedText: (): string | null => {\n return null;\n }\n };\n // Mark this as a plain text parser\n (parser as any).__isPlainTextParser = true;\n return parser;\n};\n\n/**\n * JSON parser using regex-based extraction.\n * Extracts the 'text' field from JSON responses using regex patterns.\n * This is a simpler regex-based alternative to createJsonStreamParser.\n * Less robust for complex/malformed JSON but has no external dependencies.\n */\nexport const createRegexJsonParser = (): AgentWidgetStreamParser => {\n const regexParser = createRegexJsonParserInternal();\n \n return {\n processChunk: async (accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null> => {\n // Only process if it looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n return regexParser.processChunk(accumulatedContent);\n },\n getExtractedText: regexParser.getExtractedText.bind(regexParser),\n close: regexParser.close?.bind(regexParser)\n };\n};\n\n/**\n * JSON stream parser using partial-json library.\n * Extracts the 'text' field from JSON responses using the partial-json library,\n * which is specifically designed for parsing incomplete JSON from LLMs.\n * This is the recommended parser as it's more robust than regex.\n * \n * Library: https://github.com/promplate/partial-json-parser-js\n */\nexport const createJsonStreamParser = (): AgentWidgetStreamParser => {\n let extractedText: string | null = null;\n let processedLength = 0;\n \n return {\n getExtractedText: () => extractedText,\n processChunk: (accumulatedContent: string): AgentWidgetStreamParserResult | string | null => {\n // Validate that the accumulated content looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n \n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedText !== null\n ? { text: extractedText, raw: accumulatedContent }\n : null;\n }\n \n try {\n // Parse partial JSON - allow partial strings and objects\n // STR | OBJ allows incomplete strings and objects during streaming\n const parsed = parsePartialJson(accumulatedContent, STR | OBJ);\n \n // Extract text field if available\n if (parsed && typeof parsed === \"object\" && typeof parsed.text === \"string\") {\n extractedText = parsed.text;\n }\n } catch (error) {\n // If parsing fails completely, keep the last extracted text\n // This can happen with very malformed JSON\n }\n \n // Update processed length\n processedLength = accumulatedContent.length;\n \n // Return both the extracted text and raw JSON\n if (extractedText !== null) {\n return {\n text: extractedText,\n raw: accumulatedContent\n };\n }\n\n return null;\n },\n close: () => {\n // No cleanup needed\n }\n };\n};\n\n/**\n * Flexible JSON stream parser that can extract text from various field names.\n * This parser looks for display text in multiple possible fields, making it\n * compatible with different JSON response formats.\n * \n * @param textExtractor Optional function to extract display text from parsed JSON.\n * If not provided, looks for common text fields.\n */\nexport const createFlexibleJsonStreamParser = (\n textExtractor?: (parsed: any) => string | null\n): AgentWidgetStreamParser => {\n let extractedText: string | null = null;\n let processedLength = 0;\n \n // Default text extractor that handles common patterns\n const defaultExtractor = (parsed: any): string | null => {\n if (!parsed || typeof parsed !== \"object\") return null;\n \n // Check for action-based text fields\n if (parsed.action) {\n switch (parsed.action) {\n case 'nav_then_click':\n return parsed.on_load_text || parsed.text || null;\n case 'message':\n case 'message_and_click':\n case 'checkout':\n return parsed.text || null;\n default:\n return parsed.text || parsed.display_text || parsed.message || null;\n }\n }\n \n // Fallback to common text field names\n return parsed.text || parsed.display_text || parsed.message || parsed.content || null;\n };\n \n const extractText = textExtractor || defaultExtractor;\n \n return {\n getExtractedText: () => extractedText,\n processChunk: (accumulatedContent: string): AgentWidgetStreamParserResult | string | null => {\n // Validate that the accumulated content looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n \n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedText !== null\n ? { text: extractedText, raw: accumulatedContent }\n : null;\n }\n \n try {\n // Parse partial JSON - allow partial strings and objects\n // STR | OBJ allows incomplete strings and objects during streaming\n const parsed = parsePartialJson(accumulatedContent, STR | OBJ);\n \n // Extract text using the provided or default extractor\n const newText = extractText(parsed);\n if (newText !== null) {\n extractedText = newText;\n }\n } catch (error) {\n // If parsing fails completely, keep the last extracted text\n // This can happen with very malformed JSON\n }\n \n // Update processed length\n processedLength = accumulatedContent.length;\n \n // Always return the raw JSON for action parsing\n // Text may be null during early streaming, that's ok\n return {\n text: extractedText || \"\",\n raw: accumulatedContent\n };\n },\n close: () => {\n // No cleanup needed\n }\n };\n};\n\n/**\n * XML stream parser.\n * Extracts text from <text>...</text> tags in XML responses.\n */\nexport const createXmlParser = (): AgentWidgetStreamParser => {\n let extractedText: string | null = null;\n \n return {\n processChunk: (accumulatedContent: string): AgentWidgetStreamParserResult | string | null => {\n // Return null if not XML format\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('<')) {\n return null;\n }\n \n // Extract text from <text>...</text> tags\n // Handle both <text>content</text> and <text attr=\"value\">content</text>\n const match = accumulatedContent.match(/<text[^>]*>([\\s\\S]*?)<\\/text>/);\n if (match && match[1]) {\n extractedText = match[1];\n // For XML, we typically don't need the raw content for middleware\n // but we can include it for consistency\n return { text: extractedText, raw: accumulatedContent };\n }\n \n return null;\n },\n getExtractedText: (): string | null => {\n return extractedText;\n }\n };\n};\n\n\n\n\n\n\n\n","import {\n AgentWidgetConfig,\n AgentWidgetMessage,\n AgentWidgetEvent,\n AgentWidgetStreamParser,\n AgentWidgetContextProvider,\n AgentWidgetRequestMiddleware,\n AgentWidgetRequestPayload\n} from \"./types\";\nimport { \n extractTextFromJson, \n createPlainTextParser,\n createJsonStreamParser,\n createRegexJsonParser,\n createXmlParser\n} from \"./utils/formatting\";\n\ntype DispatchOptions = {\n messages: AgentWidgetMessage[];\n signal?: AbortSignal;\n};\n\ntype SSEHandler = (event: AgentWidgetEvent) => void;\n\nconst DEFAULT_ENDPOINT = \"https://api.travrse.ai/v1/dispatch\";\n\n/**\n * Maps parserType string to the corresponding parser factory function\n */\nfunction getParserFromType(parserType?: \"plain\" | \"json\" | \"regex-json\" | \"xml\"): () => AgentWidgetStreamParser {\n switch (parserType) {\n case \"json\":\n return createJsonStreamParser;\n case \"regex-json\":\n return createRegexJsonParser;\n case \"xml\":\n return createXmlParser;\n case \"plain\":\n default:\n return createPlainTextParser;\n }\n}\n\nexport class AgentWidgetClient {\n private readonly apiUrl: string;\n private readonly headers: Record<string, string>;\n private readonly debug: boolean;\n private readonly createStreamParser: () => AgentWidgetStreamParser;\n private readonly contextProviders: AgentWidgetContextProvider[];\n private readonly requestMiddleware?: AgentWidgetRequestMiddleware;\n\n constructor(private config: AgentWidgetConfig = {}) {\n this.apiUrl = config.apiUrl ?? DEFAULT_ENDPOINT;\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...config.headers\n };\n this.debug = Boolean(config.debug);\n // Use custom stream parser if provided, otherwise use parserType, or fall back to plain text parser\n this.createStreamParser = config.streamParser ?? getParserFromType(config.parserType);\n this.contextProviders = config.contextProviders ?? [];\n this.requestMiddleware = config.requestMiddleware;\n }\n\n public async dispatch(options: DispatchOptions, onEvent: SSEHandler) {\n const controller = new AbortController();\n if (options.signal) {\n options.signal.addEventListener(\"abort\", () => controller.abort());\n }\n\n onEvent({ type: \"status\", status: \"connecting\" });\n\n const body = await this.buildPayload(options.messages);\n\n if (this.debug) {\n // eslint-disable-next-line no-console\n console.debug(\"[AgentWidgetClient] dispatch body\", body);\n }\n\n const response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n body: JSON.stringify(body),\n signal: controller.signal\n });\n\n if (!response.ok || !response.body) {\n const error = new Error(\n `Chat backend request failed: ${response.status} ${response.statusText}`\n );\n onEvent({ type: \"error\", error });\n throw error;\n }\n\n onEvent({ type: \"status\", status: \"connected\" });\n try {\n await this.streamResponse(response.body, onEvent);\n } finally {\n onEvent({ type: \"status\", status: \"idle\" });\n }\n }\n\n private async buildPayload(\n messages: AgentWidgetMessage[]\n ): Promise<AgentWidgetRequestPayload> {\n const normalizedMessages = messages\n .slice()\n .sort((a, b) => {\n const timeA = new Date(a.createdAt).getTime();\n const timeB = new Date(b.createdAt).getTime();\n return timeA - timeB;\n })\n .map((message) => ({\n role: message.role,\n content: message.content,\n createdAt: message.createdAt\n }));\n\n const payload: AgentWidgetRequestPayload = {\n messages: normalizedMessages,\n ...(this.config.flowId && { flowId: this.config.flowId })\n };\n\n if (this.contextProviders.length) {\n const contextAggregate: Record<string, unknown> = {};\n await Promise.all(\n this.contextProviders.map(async (provider) => {\n try {\n const result = await provider({\n messages,\n config: this.config\n });\n if (result && typeof result === \"object\") {\n Object.assign(contextAggregate, result);\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.warn(\"[AgentWidget] Context provider failed:\", error);\n }\n }\n })\n );\n\n if (Object.keys(contextAggregate).length) {\n payload.context = contextAggregate;\n }\n }\n\n if (this.requestMiddleware) {\n try {\n const result = await this.requestMiddleware({\n payload: { ...payload },\n config: this.config\n });\n if (result && typeof result === \"object\") {\n return result as AgentWidgetRequestPayload;\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Request middleware error:\", error);\n }\n }\n }\n\n return payload;\n }\n\n private async streamResponse(\n body: ReadableStream<Uint8Array>,\n onEvent: SSEHandler\n ) {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n const baseSequence = Date.now();\n let sequenceCounter = 0;\n const nextSequence = () => baseSequence + sequenceCounter++;\n\n const cloneMessage = (msg: AgentWidgetMessage): AgentWidgetMessage => {\n const reasoning = msg.reasoning\n ? {\n ...msg.reasoning,\n chunks: [...msg.reasoning.chunks]\n }\n : undefined;\n const toolCall = msg.toolCall\n ? {\n ...msg.toolCall,\n chunks: msg.toolCall.chunks ? [...msg.toolCall.chunks] : undefined\n }\n : undefined;\n const tools = msg.tools\n ? msg.tools.map((tool) => ({\n ...tool,\n chunks: tool.chunks ? [...tool.chunks] : undefined\n }))\n : undefined;\n\n return {\n ...msg,\n reasoning,\n toolCall,\n tools\n };\n };\n\n const emitMessage = (msg: AgentWidgetMessage) => {\n onEvent({\n type: \"message\",\n message: cloneMessage(msg)\n });\n };\n\n let assistantMessage: AgentWidgetMessage | null = null;\n const reasoningMessages = new Map<string, AgentWidgetMessage>();\n const toolMessages = new Map<string, AgentWidgetMessage>();\n const reasoningContext = {\n lastId: null as string | null,\n byStep: new Map<string, string>()\n };\n const toolContext = {\n lastId: null as string | null,\n byCall: new Map<string, string>()\n };\n\n const normalizeKey = (value: unknown): string | null => {\n if (value === null || value === undefined) return null;\n try {\n return String(value);\n } catch (error) {\n return null;\n }\n };\n\n const getStepKey = (payload: Record<string, any>) =>\n normalizeKey(\n payload.stepId ??\n payload.step_id ??\n payload.step ??\n payload.parentId ??\n payload.flowStepId ??\n payload.flow_step_id\n );\n\n const getToolCallKey = (payload: Record<string, any>) =>\n normalizeKey(\n payload.callId ??\n payload.call_id ??\n payload.requestId ??\n payload.request_id ??\n payload.toolCallId ??\n payload.tool_call_id ??\n payload.stepId ??\n payload.step_id\n );\n\n const ensureAssistantMessage = () => {\n if (assistantMessage) return assistantMessage;\n assistantMessage = {\n id: `assistant-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n variant: \"assistant\",\n sequence: nextSequence()\n };\n emitMessage(assistantMessage);\n return assistantMessage;\n };\n\n const trackReasoningId = (stepKey: string | null, id: string) => {\n reasoningContext.lastId = id;\n if (stepKey) {\n reasoningContext.byStep.set(stepKey, id);\n }\n };\n\n const resolveReasoningId = (\n payload: Record<string, any>,\n allowCreate: boolean\n ): string | null => {\n const rawId = payload.reasoningId ?? payload.id;\n const stepKey = getStepKey(payload);\n if (rawId) {\n const resolved = String(rawId);\n trackReasoningId(stepKey, resolved);\n return resolved;\n }\n if (stepKey) {\n const existing = reasoningContext.byStep.get(stepKey);\n if (existing) {\n reasoningContext.lastId = existing;\n return existing;\n }\n }\n if (reasoningContext.lastId && !allowCreate) {\n return reasoningContext.lastId;\n }\n if (!allowCreate) {\n return null;\n }\n const generated = `reason-${nextSequence()}`;\n trackReasoningId(stepKey, generated);\n return generated;\n };\n\n const ensureReasoningMessage = (reasoningId: string) => {\n const existing = reasoningMessages.get(reasoningId);\n if (existing) {\n return existing;\n }\n\n const message: AgentWidgetMessage = {\n id: `reason-${reasoningId}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n variant: \"reasoning\",\n sequence: nextSequence(),\n reasoning: {\n id: reasoningId,\n status: \"streaming\",\n chunks: []\n }\n };\n\n reasoningMessages.set(reasoningId, message);\n emitMessage(message);\n return message;\n };\n\n const trackToolId = (callKey: string | null, id: string) => {\n toolContext.lastId = id;\n if (callKey) {\n toolContext.byCall.set(callKey, id);\n }\n };\n\n const resolveToolId = (\n payload: Record<string, any>,\n allowCreate: boolean\n ): string | null => {\n const rawId = payload.toolId ?? payload.id;\n const callKey = getToolCallKey(payload);\n if (rawId) {\n const resolved = String(rawId);\n trackToolId(callKey, resolved);\n return resolved;\n }\n if (callKey) {\n const existing = toolContext.byCall.get(callKey);\n if (existing) {\n toolContext.lastId = existing;\n return existing;\n }\n }\n if (toolContext.lastId && !allowCreate) {\n return toolContext.lastId;\n }\n if (!allowCreate) {\n return null;\n }\n const generated = `tool-${nextSequence()}`;\n trackToolId(callKey, generated);\n return generated;\n };\n\n const ensureToolMessage = (toolId: string) => {\n const existing = toolMessages.get(toolId);\n if (existing) {\n return existing;\n }\n\n const message: AgentWidgetMessage = {\n id: `tool-${toolId}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n variant: \"tool\",\n sequence: nextSequence(),\n toolCall: {\n id: toolId,\n status: \"pending\"\n }\n };\n\n toolMessages.set(toolId, message);\n emitMessage(message);\n return message;\n };\n\n const resolveTimestamp = (value: unknown) => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === \"string\") {\n const parsed = Number(value);\n if (!Number.isNaN(parsed) && Number.isFinite(parsed)) {\n return parsed;\n }\n const dateParsed = Date.parse(value);\n if (!Number.isNaN(dateParsed)) {\n return dateParsed;\n }\n }\n return Date.now();\n };\n\n const ensureStringContent = (value: unknown): string => {\n if (typeof value === \"string\") {\n return value;\n }\n if (value === null || value === undefined) {\n return \"\";\n }\n // Convert objects/arrays to JSON string\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n };\n\n // Maintain stateful stream parsers per message for incremental parsing\n const streamParsers = new Map<string, AgentWidgetStreamParser>();\n // Track accumulated raw content for structured formats (JSON, XML, etc.)\n const rawContentBuffers = new Map<string, string>();\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 events = buffer.split(\"\\n\\n\");\n buffer = events.pop() ?? \"\";\n\n for (const event of events) {\n const lines = event.split(\"\\n\");\n let eventType = \"message\";\n let data = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"event:\")) {\n eventType = line.replace(\"event:\", \"\").trim();\n } else if (line.startsWith(\"data:\")) {\n data += line.replace(\"data:\", \"\").trim();\n }\n }\n\n if (!data) continue;\n let payload: any;\n try {\n payload = JSON.parse(data);\n } catch (error) {\n onEvent({\n type: \"error\",\n error:\n error instanceof Error\n ? error\n : new Error(\"Failed to parse chat stream payload\")\n });\n continue;\n }\n\n const payloadType =\n eventType !== \"message\" ? eventType : payload.type ?? \"message\";\n\n if (payloadType === \"reason_start\") {\n const reasoningId =\n resolveReasoningId(payload, true) ?? `reason-${nextSequence()}`;\n const reasoningMessage = ensureReasoningMessage(reasoningId);\n reasoningMessage.reasoning = reasoningMessage.reasoning ?? {\n id: reasoningId,\n status: \"streaming\",\n chunks: []\n };\n reasoningMessage.reasoning.startedAt =\n reasoningMessage.reasoning.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n reasoningMessage.reasoning.completedAt = undefined;\n reasoningMessage.reasoning.durationMs = undefined;\n reasoningMessage.streaming = true;\n reasoningMessage.reasoning.status = \"streaming\";\n emitMessage(reasoningMessage);\n } else if (payloadType === \"reason_chunk\") {\n const reasoningId =\n resolveReasoningId(payload, false) ??\n resolveReasoningId(payload, true) ??\n `reason-${nextSequence()}`;\n const reasoningMessage = ensureReasoningMessage(reasoningId);\n reasoningMessage.reasoning = reasoningMessage.reasoning ?? {\n id: reasoningId,\n status: \"streaming\",\n chunks: []\n };\n reasoningMessage.reasoning.startedAt =\n reasoningMessage.reasoning.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n const chunk =\n payload.reasoningText ??\n payload.text ??\n payload.delta ??\n \"\";\n if (chunk && payload.hidden !== true) {\n reasoningMessage.reasoning.chunks.push(String(chunk));\n }\n reasoningMessage.reasoning.status = payload.done ? \"complete\" : \"streaming\";\n if (payload.done) {\n reasoningMessage.reasoning.completedAt = resolveTimestamp(\n payload.completedAt ?? payload.timestamp\n );\n const start = reasoningMessage.reasoning.startedAt ?? Date.now();\n reasoningMessage.reasoning.durationMs = Math.max(\n 0,\n (reasoningMessage.reasoning.completedAt ?? Date.now()) - start\n );\n }\n reasoningMessage.streaming = reasoningMessage.reasoning.status !== \"complete\";\n emitMessage(reasoningMessage);\n } else if (payloadType === \"reason_complete\") {\n const reasoningId =\n resolveReasoningId(payload, false) ??\n resolveReasoningId(payload, true) ??\n `reason-${nextSequence()}`;\n const reasoningMessage = reasoningMessages.get(reasoningId);\n if (reasoningMessage?.reasoning) {\n reasoningMessage.reasoning.status = \"complete\";\n reasoningMessage.reasoning.completedAt = resolveTimestamp(\n payload.completedAt ?? payload.timestamp\n );\n const start = reasoningMessage.reasoning.startedAt ?? Date.now();\n reasoningMessage.reasoning.durationMs = Math.max(\n 0,\n (reasoningMessage.reasoning.completedAt ?? Date.now()) - start\n );\n reasoningMessage.streaming = false;\n emitMessage(reasoningMessage);\n }\n const stepKey = getStepKey(payload);\n if (stepKey) {\n reasoningContext.byStep.delete(stepKey);\n }\n } else if (payloadType === \"tool_start\") {\n const toolId =\n resolveToolId(payload, true) ?? `tool-${nextSequence()}`;\n const toolMessage = ensureToolMessage(toolId);\n const tool = toolMessage.toolCall ?? {\n id: toolId,\n status: \"pending\"\n };\n tool.name = payload.toolName ?? tool.name;\n tool.status = \"running\";\n if (payload.args !== undefined) {\n tool.args = payload.args;\n }\n tool.startedAt =\n tool.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n tool.completedAt = undefined;\n tool.durationMs = undefined;\n toolMessage.toolCall = tool;\n toolMessage.streaming = true;\n emitMessage(toolMessage);\n } else if (payloadType === \"tool_chunk\") {\n const toolId =\n resolveToolId(payload, false) ??\n resolveToolId(payload, true) ??\n `tool-${nextSequence()}`;\n const toolMessage = ensureToolMessage(toolId);\n const tool = toolMessage.toolCall ?? {\n id: toolId,\n status: \"running\"\n };\n tool.startedAt =\n tool.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n const chunkText =\n payload.text ?? payload.delta ?? payload.message ?? \"\";\n if (chunkText) {\n tool.chunks = tool.chunks ?? [];\n tool.chunks.push(String(chunkText));\n }\n tool.status = \"running\";\n toolMessage.toolCall = tool;\n toolMessage.streaming = true;\n emitMessage(toolMessage);\n } else if (payloadType === \"tool_complete\") {\n const toolId =\n resolveToolId(payload, false) ??\n resolveToolId(payload, true) ??\n `tool-${nextSequence()}`;\n const toolMessage = ensureToolMessage(toolId);\n const tool = toolMessage.toolCall ?? {\n id: toolId,\n status: \"running\"\n };\n tool.status = \"complete\";\n if (payload.result !== undefined) {\n tool.result = payload.result;\n }\n if (typeof payload.duration === \"number\") {\n tool.duration = payload.duration;\n }\n tool.completedAt = resolveTimestamp(\n payload.completedAt ?? payload.timestamp\n );\n if (typeof payload.duration === \"number\") {\n tool.durationMs = payload.duration;\n } else {\n const start = tool.startedAt ?? Date.now();\n tool.durationMs = Math.max(\n 0,\n (tool.completedAt ?? Date.now()) - start\n );\n }\n toolMessage.toolCall = tool;\n toolMessage.streaming = false;\n emitMessage(toolMessage);\n const callKey = getToolCallKey(payload);\n if (callKey) {\n toolContext.byCall.delete(callKey);\n }\n } else if (payloadType === \"step_chunk\") {\n // Only process chunks for prompt steps, not tool/context steps\n const stepType = (payload as any).stepType;\n const executionType = (payload as any).executionType;\n if (stepType === \"tool\" || executionType === \"context\") {\n // Skip tool-related chunks - they're handled by tool_start/tool_complete\n continue;\n }\n const assistant = ensureAssistantMessage();\n const chunk = payload.text ?? payload.delta ?? payload.content ?? \"\";\n if (chunk) {\n // Accumulate raw content for structured format parsing\n const rawBuffer = rawContentBuffers.get(assistant.id) ?? \"\";\n const accumulatedRaw = rawBuffer + chunk;\n // Store raw content for action parsing, but NEVER set assistant.content to raw JSON\n assistant.rawContent = accumulatedRaw;\n \n // Use stream parser to parse\n if (!streamParsers.has(assistant.id)) {\n streamParsers.set(assistant.id, this.createStreamParser());\n }\n const parser = streamParsers.get(assistant.id)!;\n \n // Check if content looks like JSON\n const looksLikeJson = accumulatedRaw.trim().startsWith('{') || accumulatedRaw.trim().startsWith('[');\n \n // Store raw buffer before processing (needed for step_complete handler)\n if (looksLikeJson) {\n rawContentBuffers.set(assistant.id, accumulatedRaw);\n }\n \n // Check if this is a plain text parser (marked with __isPlainTextParser)\n const isPlainTextParser = (parser as any).__isPlainTextParser === true;\n \n // If plain text parser, just append the chunk directly\n if (isPlainTextParser) {\n assistant.content += chunk;\n // Clear any raw buffer/parser since we're in plain text mode\n rawContentBuffers.delete(assistant.id);\n streamParsers.delete(assistant.id);\n assistant.rawContent = undefined;\n emitMessage(assistant);\n continue;\n }\n \n // Try to parse with the parser (for structured parsers)\n const parsedResult = parser.processChunk(accumulatedRaw);\n \n // Handle async parser result\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n // Parser successfully extracted text\n // Update the message content with extracted text\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n emitMessage(currentAssistant);\n }\n } else if (!looksLikeJson && !accumulatedRaw.trim().startsWith('<')) {\n // Not a structured format - show as plain text\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content += chunk;\n rawContentBuffers.delete(currentAssistant.id);\n streamParsers.delete(currentAssistant.id);\n currentAssistant.rawContent = undefined;\n emitMessage(currentAssistant);\n }\n }\n // Otherwise wait for more chunks (incomplete structured format)\n // Don't emit message if parser hasn't extracted text yet\n }).catch(() => {\n // On error, treat as plain text\n assistant.content += chunk;\n rawContentBuffers.delete(assistant.id);\n streamParsers.delete(assistant.id);\n assistant.rawContent = undefined;\n emitMessage(assistant);\n });\n } else {\n // Synchronous parser result\n // Extract text from result (could be string, null, or object)\n const text = typeof parsedResult === 'string' ? parsedResult : parsedResult?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n // Parser successfully extracted text\n // Buffer is already set above\n assistant.content = text;\n emitMessage(assistant);\n } else if (!looksLikeJson && !accumulatedRaw.trim().startsWith('<')) {\n // Not a structured format - show as plain text\n assistant.content += chunk;\n // Clear any raw buffer/parser if we were in structured format mode\n rawContentBuffers.delete(assistant.id);\n streamParsers.delete(assistant.id);\n assistant.rawContent = undefined;\n emitMessage(assistant);\n }\n // Otherwise wait for more chunks (incomplete structured format)\n // Don't emit message if parser hasn't extracted text yet\n }\n \n // IMPORTANT: Don't call getExtractedText() and emit messages here\n // This was causing raw JSON to be displayed because getExtractedText() \n // wasn't extracting the \"text\" field correctly during streaming\n }\n if (payload.isComplete) {\n const finalContent = payload.result?.response ?? assistant.content;\n if (finalContent) {\n // Check if we have raw content buffer that needs final processing\n const rawBuffer = rawContentBuffers.get(assistant.id);\n const contentToProcess = rawBuffer ?? ensureStringContent(finalContent);\n assistant.rawContent = contentToProcess;\n \n // Try to extract text from final structured content\n const parser = streamParsers.get(assistant.id);\n let extractedText: string | null = null;\n \n if (parser) {\n // First check if parser already has extracted text\n extractedText = parser.getExtractedText();\n \n if (extractedText === null) {\n // Try extracting with regex\n extractedText = extractTextFromJson(contentToProcess);\n }\n \n if (extractedText === null) {\n // Try parser.processChunk as last resort\n const parsedResult = parser.processChunk(contentToProcess);\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n if (text !== null) {\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n }\n });\n } else {\n // Extract text from synchronous result\n extractedText = typeof parsedResult === 'string' ? parsedResult : parsedResult?.text ?? null;\n }\n }\n }\n \n // Set content: use extracted text if available, otherwise use raw content\n if (extractedText !== null && extractedText.trim() !== \"\") {\n assistant.content = extractedText;\n } else if (!rawContentBuffers.has(assistant.id)) {\n // Only use raw final content if we didn't accumulate chunks\n assistant.content = ensureStringContent(finalContent);\n }\n \n // Clean up parser and buffer\n const parserToClose = streamParsers.get(assistant.id);\n if (parserToClose) {\n const closeResult = parserToClose.close?.();\n if (closeResult instanceof Promise) {\n closeResult.catch(() => {});\n }\n streamParsers.delete(assistant.id);\n }\n rawContentBuffers.delete(assistant.id);\n assistant.streaming = false;\n emitMessage(assistant);\n }\n }\n } else if (payloadType === \"step_complete\") {\n // Only process completions for prompt steps, not tool/context steps\n const stepType = (payload as any).stepType;\n const executionType = (payload as any).executionType;\n if (stepType === \"tool\" || executionType === \"context\") {\n // Skip tool-related completions - they're handled by tool_complete\n continue;\n }\n const finalContent = payload.result?.response;\n const assistant = ensureAssistantMessage();\n if (finalContent !== undefined && finalContent !== null) {\n // Check if we already have extracted text from streaming\n const parser = streamParsers.get(assistant.id);\n let hasExtractedText = false;\n \n if (parser) {\n // First check if parser already extracted text during streaming\n const currentExtractedText = parser.getExtractedText();\n const rawBuffer = rawContentBuffers.get(assistant.id);\n const contentToProcess = rawBuffer ?? ensureStringContent(finalContent);\n \n // Always set rawContent so action parsers can access the raw JSON\n assistant.rawContent = contentToProcess;\n \n if (currentExtractedText !== null && currentExtractedText.trim() !== \"\") {\n // We already have extracted text from streaming - use it\n assistant.content = currentExtractedText;\n hasExtractedText = true;\n } else {\n // No extracted text yet - try to extract from final content\n \n // Try fast path first\n const extractedText = extractTextFromJson(contentToProcess);\n if (extractedText !== null) {\n assistant.content = extractedText;\n hasExtractedText = true;\n } else {\n // Try parser\n const parsedResult = parser.processChunk(contentToProcess);\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n } else {\n // No extracted text - check if we should show raw content\n const finalExtractedText = parser.getExtractedText();\n if (finalExtractedText === null || finalExtractedText.trim() === \"\") {\n // No extracted text available - show raw content only if no streaming happened\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n // Only show raw content if we never had any extracted text\n if (!rawContentBuffers.has(assistant.id)) {\n currentAssistant.content = ensureStringContent(finalContent);\n }\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n }\n }\n });\n } else {\n // Extract text from synchronous result\n const text = typeof parsedResult === 'string' ? parsedResult : parsedResult?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n assistant.content = text;\n hasExtractedText = true;\n } else {\n // Check stub one more time\n const finalExtractedText = parser.getExtractedText();\n if (finalExtractedText !== null && finalExtractedText.trim() !== \"\") {\n assistant.content = finalExtractedText;\n hasExtractedText = true;\n }\n }\n }\n }\n }\n }\n \n // Ensure rawContent is set even if there's no parser (for action parsing)\n if (!assistant.rawContent) {\n const rawBuffer = rawContentBuffers.get(assistant.id);\n assistant.rawContent = rawBuffer ?? ensureStringContent(finalContent);\n }\n \n // Only show raw content if we never extracted any text and no buffer was used\n if (!hasExtractedText && !rawContentBuffers.has(assistant.id)) {\n // No extracted text and no streaming happened - show raw content\n assistant.content = ensureStringContent(finalContent);\n }\n \n // Clean up parser and buffer\n if (parser) {\n const closeResult = parser.close?.();\n if (closeResult instanceof Promise) {\n closeResult.catch(() => {});\n }\n }\n streamParsers.delete(assistant.id);\n rawContentBuffers.delete(assistant.id);\n assistant.streaming = false;\n emitMessage(assistant);\n } else {\n // No final content, just mark as complete and clean up\n streamParsers.delete(assistant.id);\n rawContentBuffers.delete(assistant.id);\n assistant.streaming = false;\n emitMessage(assistant);\n }\n } else if (payloadType === \"flow_complete\") {\n const finalContent = payload.result?.response;\n if (finalContent !== undefined && finalContent !== null) {\n const assistant = ensureAssistantMessage();\n // Check if we have raw content buffer that needs final processing\n const rawBuffer = rawContentBuffers.get(assistant.id);\n const stringContent = rawBuffer ?? ensureStringContent(finalContent);\n assistant.rawContent = stringContent;\n // Try to extract text from structured content\n let displayContent = ensureStringContent(finalContent);\n const parser = streamParsers.get(assistant.id);\n if (parser) {\n const extractedText = extractTextFromJson(stringContent);\n if (extractedText !== null) {\n displayContent = extractedText;\n } else {\n // Try parser if it exists\n const parsedResult = parser.processChunk(stringContent);\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n if (text !== null) {\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n }\n });\n }\n const currentText = parser.getExtractedText();\n if (currentText !== null) {\n displayContent = currentText;\n }\n }\n }\n // Clean up parser and buffer\n streamParsers.delete(assistant.id);\n rawContentBuffers.delete(assistant.id);\n if (displayContent !== assistant.content) {\n assistant.content = displayContent;\n emitMessage(assistant);\n }\n assistant.streaming = false;\n emitMessage(assistant);\n } else {\n // No final content, just mark as complete and clean up\n if (assistantMessage !== null) {\n // Clean up any remaining parsers/buffers\n // TypeScript narrowing issue - assistantMessage is checked for null above\n const msg: AgentWidgetMessage = assistantMessage;\n streamParsers.delete(msg.id);\n rawContentBuffers.delete(msg.id);\n msg.streaming = false;\n emitMessage(msg);\n }\n }\n onEvent({ type: \"status\", status: \"idle\" });\n } else if (payloadType === \"error\" && payload.error) {\n onEvent({\n type: \"error\",\n error:\n payload.error instanceof Error\n ? payload.error\n : new Error(String(payload.error))\n });\n }\n }\n }\n }\n}\n","import { AgentWidgetClient } from \"./client\";\nimport {\n AgentWidgetConfig,\n AgentWidgetEvent,\n AgentWidgetMessage\n} from \"./types\";\n\nexport type AgentWidgetSessionStatus =\n | \"idle\"\n | \"connecting\"\n | \"connected\"\n | \"error\";\n\ntype SessionCallbacks = {\n onMessagesChanged: (messages: AgentWidgetMessage[]) => void;\n onStatusChanged: (status: AgentWidgetSessionStatus) => void;\n onStreamingChanged: (streaming: boolean) => void;\n onError?: (error: Error) => void;\n};\n\nexport class AgentWidgetSession {\n private client: AgentWidgetClient;\n private messages: AgentWidgetMessage[];\n private status: AgentWidgetSessionStatus = \"idle\";\n private streaming = false;\n private abortController: AbortController | null = null;\n private sequenceCounter = Date.now();\n\n constructor(\n private config: AgentWidgetConfig = {},\n private callbacks: SessionCallbacks\n ) {\n this.messages = [...(config.initialMessages ?? [])].map((message) => ({\n ...message,\n sequence: message.sequence ?? this.nextSequence()\n }));\n this.messages = this.sortMessages(this.messages);\n this.client = new AgentWidgetClient(config);\n\n if (this.messages.length) {\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n this.callbacks.onStatusChanged(this.status);\n }\n\n public updateConfig(next: AgentWidgetConfig) {\n this.config = { ...this.config, ...next };\n this.client = new AgentWidgetClient(this.config);\n }\n\n public getMessages() {\n return [...this.messages];\n }\n\n public getStatus() {\n return this.status;\n }\n\n public isStreaming() {\n return this.streaming;\n }\n\n public injectTestEvent(event: AgentWidgetEvent) {\n this.handleEvent(event);\n }\n\n public async sendMessage(rawInput: string, options?: { viaVoice?: boolean }) {\n const input = rawInput.trim();\n if (!input) return;\n\n this.abortController?.abort();\n\n const userMessage: AgentWidgetMessage = {\n id: `user-${Date.now()}`,\n role: \"user\",\n content: input,\n createdAt: new Date().toISOString(),\n sequence: this.nextSequence(),\n viaVoice: options?.viaVoice || false\n };\n\n this.appendMessage(userMessage);\n this.setStreaming(true);\n\n const controller = new AbortController();\n this.abortController = controller;\n\n const snapshot = [...this.messages];\n\n try {\n await this.client.dispatch(\n {\n messages: snapshot,\n signal: controller.signal\n },\n this.handleEvent\n );\n } catch (error) {\n const fallback: AgentWidgetMessage = {\n id: `assistant-${Date.now()}`,\n role: \"assistant\",\n createdAt: new Date().toISOString(),\n content:\n \"It looks like the proxy isn't returning a real response yet. Here's a sample message so you can continue testing locally.\",\n sequence: this.nextSequence()\n };\n\n this.appendMessage(fallback);\n this.setStatus(\"idle\");\n this.setStreaming(false);\n this.abortController = null;\n if (error instanceof Error) {\n this.callbacks.onError?.(error);\n } else {\n this.callbacks.onError?.(new Error(String(error)));\n }\n }\n }\n\n public cancel() {\n this.abortController?.abort();\n this.abortController = null;\n this.setStreaming(false);\n this.setStatus(\"idle\");\n }\n\n public clearMessages() {\n this.abortController?.abort();\n this.abortController = null;\n this.messages = [];\n this.setStreaming(false);\n this.setStatus(\"idle\");\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n public hydrateMessages(messages: AgentWidgetMessage[]) {\n this.abortController?.abort();\n this.abortController = null;\n this.messages = this.sortMessages(\n messages.map((message) => ({\n ...message,\n streaming: false,\n sequence: message.sequence ?? this.nextSequence()\n }))\n );\n this.setStreaming(false);\n this.setStatus(\"idle\");\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n private handleEvent = (event: AgentWidgetEvent) => {\n if (event.type === \"message\") {\n this.upsertMessage(event.message);\n } else if (event.type === \"status\") {\n this.setStatus(event.status);\n if (event.status === \"connecting\") {\n this.setStreaming(true);\n } else if (event.status === \"idle\" || event.status === \"error\") {\n this.setStreaming(false);\n this.abortController = null;\n }\n } else if (event.type === \"error\") {\n this.setStatus(\"error\");\n this.setStreaming(false);\n this.abortController = null;\n this.callbacks.onError?.(event.error);\n }\n };\n\n private setStatus(status: AgentWidgetSessionStatus) {\n if (this.status === status) return;\n this.status = status;\n this.callbacks.onStatusChanged(status);\n }\n\n private setStreaming(streaming: boolean) {\n if (this.streaming === streaming) return;\n this.streaming = streaming;\n this.callbacks.onStreamingChanged(streaming);\n }\n\n private appendMessage(message: AgentWidgetMessage) {\n const withSequence = this.ensureSequence(message);\n this.messages = this.sortMessages([...this.messages, withSequence]);\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n private upsertMessage(message: AgentWidgetMessage) {\n const withSequence = this.ensureSequence(message);\n const index = this.messages.findIndex((m) => m.id === withSequence.id);\n if (index === -1) {\n this.appendMessage(withSequence);\n return;\n }\n\n this.messages = this.messages.map((existing, idx) =>\n idx === index ? { ...existing, ...withSequence } : existing\n );\n this.messages = this.sortMessages(this.messages);\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n private ensureSequence(message: AgentWidgetMessage): AgentWidgetMessage {\n if (message.sequence !== undefined) {\n return { ...message };\n }\n return {\n ...message,\n sequence: this.nextSequence()\n };\n }\n\n private nextSequence() {\n return this.sequenceCounter++;\n }\n\n private sortMessages(messages: AgentWidgetMessage[]) {\n return [...messages].sort((a, b) => {\n // Sort by createdAt timestamp first (chronological order)\n const timeA = new Date(a.createdAt).getTime();\n const timeB = new Date(b.createdAt).getTime();\n if (!Number.isNaN(timeA) && !Number.isNaN(timeB) && timeA !== timeB) {\n return timeA - timeB;\n }\n\n // Fall back to sequence if timestamps are equal or invalid\n const seqA = a.sequence ?? 0;\n const seqB = b.sequence ?? 0;\n if (seqA !== seqB) return seqA - seqB;\n\n // Final fallback to ID\n return a.id.localeCompare(b.id);\n });\n }\n}\n","import { AgentWidgetConfig } from \"../types\";\n\nexport const applyThemeVariables = (\n element: HTMLElement,\n config?: AgentWidgetConfig\n) => {\n const theme = config?.theme ?? {};\n Object.entries(theme).forEach(([key, value]) => {\n // Skip undefined or empty values\n if (value === undefined || value === null || value === \"\") {\n return;\n }\n // Convert camelCase to kebab-case (e.g., radiusSm → radius-sm)\n const kebabKey = key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);\n element.style.setProperty(`--cw-${kebabKey}`, String(value));\n });\n};\n\n\n\n\n\n\n\n","import * as icons from \"lucide\";\nimport type { IconNode } from \"lucide\";\n\n/**\n * Renders a Lucide icon as an inline SVG element\n * This approach requires no CSS and works on any page\n * \n * @param iconName - The Lucide icon name in kebab-case (e.g., \"arrow-up\")\n * @param size - The size of the icon (default: 24)\n * @param color - The stroke color (default: \"currentColor\")\n * @param strokeWidth - The stroke width (default: 2)\n * @returns SVGElement or null if icon not found\n */\nexport const renderLucideIcon = (\n iconName: string,\n size: number | string = 24,\n color: string = \"currentColor\",\n strokeWidth: number = 2\n): SVGElement | null => {\n try {\n // Convert kebab-case to PascalCase (e.g., \"arrow-up\" -> \"ArrowUp\")\n const pascalName = iconName\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\"\");\n \n // Lucide's icons object contains IconNode data directly, not functions\n const iconData = (icons as Record<string, IconNode>)[pascalName] as IconNode;\n \n if (!iconData) {\n console.warn(`Lucide icon \"${iconName}\" not found (tried \"${pascalName}\"). Available icons: https://lucide.dev/icons`);\n return null;\n }\n\n return createSvgFromIconData(iconData, size, color, strokeWidth);\n } catch (error) {\n console.warn(`Failed to render Lucide icon \"${iconName}\":`, error);\n return null;\n }\n};\n\n/**\n * Helper function to create SVG from IconNode data\n */\nfunction createSvgFromIconData(\n iconData: IconNode,\n size: number | string,\n color: string,\n strokeWidth: number\n): SVGElement | null {\n if (!iconData || !Array.isArray(iconData)) {\n return null;\n }\n\n // Create SVG element\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"width\", String(size));\n svg.setAttribute(\"height\", String(size));\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", color);\n svg.setAttribute(\"stroke-width\", String(strokeWidth));\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n \n // Render elements from icon data\n // IconNode format: [[\"path\", {\"d\": \"...\"}], [\"rect\", {\"x\": \"...\", \"y\": \"...\"}], ...]\n iconData.forEach((elementData) => {\n if (Array.isArray(elementData) && elementData.length >= 2) {\n const tagName = elementData[0] as string;\n const attrs = elementData[1] as Record<string, string>;\n \n if (attrs) {\n // Create the appropriate SVG element (path, rect, circle, ellipse, line, etc.)\n const element = document.createElementNS(\"http://www.w3.org/2000/svg\", tagName);\n \n // Apply all attributes, but skip 'stroke' (we want to use the parent SVG's stroke for consistent coloring)\n Object.entries(attrs).forEach(([key, value]) => {\n if (key !== \"stroke\") {\n element.setAttribute(key, String(value));\n }\n });\n \n svg.appendChild(element);\n }\n }\n });\n \n return svg;\n}\n\n","/**\n * DOM utility functions\n */\nexport const createElement = <K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string\n): HTMLElementTagNameMap[K] => {\n const element = document.createElement(tag);\n if (className) {\n element.className = className;\n }\n return element;\n};\n\nexport const createFragment = (): DocumentFragment => {\n return document.createDocumentFragment();\n};\n\n\n\n\n\n\n\n","import { AgentWidgetSessionStatus } from \"../session\";\n\nexport const statusCopy: Record<AgentWidgetSessionStatus, string> = {\n idle: \"Online\",\n connecting: \"Connecting…\",\n connected: \"Streaming…\",\n error: \"Offline\"\n};\n\n\n\n\n\n\n\n","export const positionMap: Record<\n \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\",\n string\n> = {\n \"bottom-right\": \"tvw-bottom-6 tvw-right-6\",\n \"bottom-left\": \"tvw-bottom-6 tvw-left-6\",\n \"top-right\": \"tvw-top-6 tvw-right-6\",\n \"top-left\": \"tvw-top-6 tvw-left-6\"\n};\n\n\n\n\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetConfig } from \"../types\";\nimport { positionMap } from \"../utils/positioning\";\nimport { renderLucideIcon } from \"../utils/icons\";\n\nexport interface LauncherButton {\n element: HTMLButtonElement;\n update: (config: AgentWidgetConfig) => void;\n destroy: () => void;\n}\n\nexport const createLauncherButton = (\n config: AgentWidgetConfig | undefined,\n onToggle: () => void\n): LauncherButton => {\n const button = createElement(\"button\") as HTMLButtonElement;\n button.type = \"button\";\n button.innerHTML = `\n <span class=\"tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-bg-cw-primary tvw-text-white\" data-role=\"launcher-icon\">💬</span>\n <img data-role=\"launcher-image\" class=\"tvw-rounded-full tvw-object-cover\" alt=\"\" style=\"display:none\" />\n <span class=\"tvw-flex tvw-flex-col tvw-items-start tvw-text-left\">\n <span class=\"tvw-text-sm tvw-font-semibold tvw-text-cw-primary\" data-role=\"launcher-title\"></span>\n <span class=\"tvw-text-xs tvw-text-cw-muted\" data-role=\"launcher-subtitle\"></span>\n </span>\n <span class=\"tvw-ml-2 tvw-grid tvw-place-items-center tvw-rounded-full tvw-bg-cw-primary tvw-text-cw-call-to-action\" data-role=\"launcher-call-to-action-icon\">↗</span>\n `;\n button.addEventListener(\"click\", onToggle);\n\n const update = (newConfig: AgentWidgetConfig) => {\n const launcher = newConfig.launcher ?? {};\n\n const titleEl = button.querySelector(\"[data-role='launcher-title']\");\n if (titleEl) {\n titleEl.textContent = launcher.title ?? \"Chat Assistant\";\n }\n\n const subtitleEl = button.querySelector(\"[data-role='launcher-subtitle']\");\n if (subtitleEl) {\n subtitleEl.textContent = launcher.subtitle ?? \"Get answers fast\";\n }\n\n // Hide/show text container\n const textContainer = button.querySelector(\".tvw-flex-col\");\n if (textContainer) {\n if (launcher.textHidden) {\n (textContainer as HTMLElement).style.display = \"none\";\n } else {\n (textContainer as HTMLElement).style.display = \"\";\n }\n }\n\n const icon = button.querySelector<HTMLSpanElement>(\"[data-role='launcher-icon']\");\n if (icon) {\n if (launcher.agentIconHidden) {\n icon.style.display = \"none\";\n } else {\n const iconSize = launcher.agentIconSize ?? \"40px\";\n icon.style.height = iconSize;\n icon.style.width = iconSize;\n \n // Clear existing content\n icon.innerHTML = \"\";\n \n // Render icon based on priority: Lucide icon > iconUrl > agentIconText\n if (launcher.agentIconName) {\n // Use Lucide icon\n const iconSizeNum = parseFloat(iconSize) || 24;\n const iconSvg = renderLucideIcon(launcher.agentIconName, iconSizeNum * 0.6, \"#ffffff\", 2);\n if (iconSvg) {\n icon.appendChild(iconSvg);\n icon.style.display = \"\";\n } else {\n // Fallback to agentIconText if Lucide icon fails\n icon.textContent = launcher.agentIconText ?? \"💬\";\n icon.style.display = \"\";\n }\n } else if (launcher.iconUrl) {\n // Use image URL - hide icon span and show img\n icon.style.display = \"none\";\n } else {\n // Use text/emoji\n icon.textContent = launcher.agentIconText ?? \"💬\";\n icon.style.display = \"\";\n }\n }\n }\n\n const img = button.querySelector<HTMLImageElement>(\"[data-role='launcher-image']\");\n if (img) {\n const iconSize = launcher.agentIconSize ?? \"40px\";\n img.style.height = iconSize;\n img.style.width = iconSize;\n if (launcher.iconUrl && !launcher.agentIconName && !launcher.agentIconHidden) {\n // Only show image if not using Lucide icon and not hidden\n img.src = launcher.iconUrl;\n img.style.display = \"block\";\n } else {\n img.style.display = \"none\";\n }\n }\n\n const callToActionIconEl = button.querySelector<HTMLSpanElement>(\"[data-role='launcher-call-to-action-icon']\");\n if (callToActionIconEl) {\n const callToActionIconSize = launcher.callToActionIconSize ?? \"32px\";\n callToActionIconEl.style.height = callToActionIconSize;\n callToActionIconEl.style.width = callToActionIconSize;\n \n // Apply background color if configured\n if (launcher.callToActionIconBackgroundColor) {\n callToActionIconEl.style.backgroundColor = launcher.callToActionIconBackgroundColor;\n callToActionIconEl.classList.remove(\"tvw-bg-cw-primary\");\n } else {\n callToActionIconEl.style.backgroundColor = \"\";\n callToActionIconEl.classList.add(\"tvw-bg-cw-primary\");\n }\n \n // Calculate padding to adjust icon size\n let paddingTotal = 0;\n if (launcher.callToActionIconPadding) {\n callToActionIconEl.style.boxSizing = \"border-box\";\n callToActionIconEl.style.padding = launcher.callToActionIconPadding;\n // Parse padding value to calculate total padding (padding applies to both sides)\n const paddingValue = parseFloat(launcher.callToActionIconPadding) || 0;\n paddingTotal = paddingValue * 2; // padding on both sides\n } else {\n callToActionIconEl.style.boxSizing = \"\";\n callToActionIconEl.style.padding = \"\";\n }\n \n if (launcher.callToActionIconHidden) {\n callToActionIconEl.style.display = \"none\";\n } else {\n callToActionIconEl.style.display = \"\";\n \n // Clear existing content\n callToActionIconEl.innerHTML = \"\";\n \n // Use Lucide icon if provided, otherwise fall back to text\n if (launcher.callToActionIconName) {\n // Calculate actual icon size by subtracting padding\n const containerSize = parseFloat(callToActionIconSize) || 24;\n const iconSize = Math.max(containerSize - paddingTotal, 8); // Ensure minimum size of 8px\n const iconSvg = renderLucideIcon(launcher.callToActionIconName, iconSize, \"currentColor\", 2);\n if (iconSvg) {\n callToActionIconEl.appendChild(iconSvg);\n } else {\n // Fallback to text if icon fails to render\n callToActionIconEl.textContent = launcher.callToActionIconText ?? \"↗\";\n }\n } else {\n callToActionIconEl.textContent = launcher.callToActionIconText ?? \"↗\";\n }\n }\n }\n\n const positionClass =\n launcher.position && positionMap[launcher.position]\n ? positionMap[launcher.position]\n : positionMap[\"bottom-right\"];\n\n const base =\n \"tvw-fixed tvw-flex tvw-items-center tvw-gap-3 tvw-rounded-launcher tvw-bg-cw-surface tvw-py-2.5 tvw-pl-3 tvw-pr-3 tvw-shadow-lg tvw-border tvw-border-gray-200 tvw-transition hover:tvw-translate-y-[-2px] tvw-cursor-pointer tvw-z-50\";\n\n button.className = `${base} ${positionClass}`;\n };\n\n const destroy = () => {\n button.removeEventListener(\"click\", onToggle);\n button.remove();\n };\n\n // Initial update\n if (config) {\n update(config);\n }\n\n return {\n element: button,\n update,\n destroy\n };\n};\n\n\n","import { createElement } from \"../utils/dom\";\nimport { renderLucideIcon } from \"../utils/icons\";\nimport { AgentWidgetConfig } from \"../types\";\nimport { positionMap } from \"../utils/positioning\";\n\nexport interface PanelWrapper {\n wrapper: HTMLElement;\n panel: HTMLElement;\n}\n\nexport const createWrapper = (config?: AgentWidgetConfig): PanelWrapper => {\n const launcherEnabled = config?.launcher?.enabled ?? true;\n\n if (!launcherEnabled) {\n const wrapper = createElement(\n \"div\",\n \"tvw-relative tvw-w-full tvw-h-full\"\n );\n const panel = createElement(\n \"div\",\n \"tvw-relative tvw-w-full tvw-h-full tvw-min-h-[360px]\"\n );\n wrapper.appendChild(panel);\n return { wrapper, panel };\n }\n\n const launcher = config?.launcher ?? {};\n const position =\n launcher.position && positionMap[launcher.position]\n ? positionMap[launcher.position]\n : positionMap[\"bottom-right\"];\n\n const wrapper = createElement(\n \"div\",\n `tvw-fixed ${position} tvw-z-50 tvw-transition`\n );\n\n const panel = createElement(\n \"div\",\n \"tvw-relative tvw-min-h-[320px]\"\n );\n const launcherWidth = config?.launcher?.width ?? config?.launcherWidth;\n const width = launcherWidth ?? \"min(400px, calc(100vw - 24px))\";\n panel.style.width = width;\n panel.style.maxWidth = width;\n\n wrapper.appendChild(panel);\n return { wrapper, panel };\n};\n\nexport interface PanelElements {\n container: HTMLElement;\n body: HTMLElement;\n messagesWrapper: HTMLElement;\n suggestions: HTMLElement;\n textarea: HTMLTextAreaElement;\n sendButton: HTMLButtonElement;\n sendButtonWrapper: HTMLElement;\n micButton: HTMLButtonElement | null;\n micButtonWrapper: HTMLElement | null;\n composerForm: HTMLFormElement;\n statusText: HTMLElement;\n introTitle: HTMLElement;\n introSubtitle: HTMLElement;\n closeButton: HTMLButtonElement;\n closeButtonWrapper: HTMLElement;\n clearChatButton: HTMLButtonElement | null;\n clearChatButtonWrapper: HTMLElement | null;\n iconHolder: HTMLElement;\n headerTitle: HTMLElement;\n headerSubtitle: HTMLElement;\n}\n\nexport const buildPanel = (config?: AgentWidgetConfig, showClose = true): PanelElements => {\n const container = createElement(\n \"div\",\n \"tvw-flex tvw-h-full tvw-w-full tvw-flex-col tvw-bg-cw-surface tvw-text-cw-primary tvw-rounded-2xl tvw-overflow-hidden tvw-shadow-2xl tvw-border tvw-border-cw-border\"\n );\n\n const header = createElement(\n \"div\",\n \"tvw-flex tvw-items-center tvw-gap-3 tvw-bg-cw-surface tvw-px-6 tvw-py-5 tvw-border-b-cw-divider\"\n );\n\n const launcher = config?.launcher ?? {};\n const headerIconSize = launcher.headerIconSize ?? \"48px\";\n const closeButtonSize = launcher.closeButtonSize ?? \"32px\";\n const closeButtonPlacement = launcher.closeButtonPlacement ?? \"inline\";\n const headerIconHidden = launcher.headerIconHidden ?? false;\n const headerIconName = launcher.headerIconName;\n\n const iconHolder = createElement(\n \"div\",\n \"tvw-flex tvw-items-center tvw-justify-center tvw-rounded-xl tvw-bg-cw-primary tvw-text-white tvw-text-xl\"\n );\n iconHolder.style.height = headerIconSize;\n iconHolder.style.width = headerIconSize;\n \n // Render icon based on priority: Lucide icon > iconUrl > agentIconText\n if (!headerIconHidden) {\n if (headerIconName) {\n // Use Lucide icon\n const iconSize = parseFloat(headerIconSize) || 24;\n const iconSvg = renderLucideIcon(headerIconName, iconSize * 0.6, \"#ffffff\", 2);\n if (iconSvg) {\n iconHolder.replaceChildren(iconSvg);\n } else {\n // Fallback to agentIconText if Lucide icon fails\n iconHolder.textContent = config?.launcher?.agentIconText ?? \"💬\";\n }\n } else if (config?.launcher?.iconUrl) {\n // Use image URL\n const img = createElement(\"img\") as HTMLImageElement;\n img.src = config.launcher.iconUrl;\n img.alt = \"\";\n img.className = \"tvw-rounded-xl tvw-object-cover\";\n img.style.height = headerIconSize;\n img.style.width = headerIconSize;\n iconHolder.replaceChildren(img);\n } else {\n // Use text/emoji\n iconHolder.textContent = config?.launcher?.agentIconText ?? \"💬\";\n }\n }\n\n const headerCopy = createElement(\"div\", \"tvw-flex tvw-flex-col\");\n const title = createElement(\n \"span\",\n \"tvw-text-base tvw-font-semibold\"\n );\n title.textContent =\n config?.launcher?.title ?? \"Chat Assistant\";\n const subtitle = createElement(\n \"span\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n subtitle.textContent =\n config?.launcher?.subtitle ?? \"Here to help you get answers fast\";\n\n headerCopy.append(title, subtitle);\n \n // Only append iconHolder if not hidden\n if (!headerIconHidden) {\n header.append(iconHolder, headerCopy);\n } else {\n header.append(headerCopy);\n }\n\n // Create clear chat button if enabled\n const clearChatConfig = launcher.clearChat ?? {};\n const clearChatEnabled = clearChatConfig.enabled ?? true;\n let clearChatButton: HTMLButtonElement | null = null;\n let clearChatButtonWrapper: HTMLElement | null = null;\n\n if (clearChatEnabled) {\n const clearChatSize = clearChatConfig.size ?? \"32px\";\n const clearChatIconName = clearChatConfig.iconName ?? \"refresh-cw\";\n const clearChatIconColor = clearChatConfig.iconColor ?? \"\";\n const clearChatBgColor = clearChatConfig.backgroundColor ?? \"\";\n const clearChatBorderWidth = clearChatConfig.borderWidth ?? \"\";\n const clearChatBorderColor = clearChatConfig.borderColor ?? \"\";\n const clearChatBorderRadius = clearChatConfig.borderRadius ?? \"\";\n const clearChatPaddingX = clearChatConfig.paddingX ?? \"\";\n const clearChatPaddingY = clearChatConfig.paddingY ?? \"\";\n const clearChatTooltipText = clearChatConfig.tooltipText ?? \"Clear chat\";\n const clearChatShowTooltip = clearChatConfig.showTooltip ?? true;\n\n // Create button wrapper for tooltip\n clearChatButtonWrapper = createElement(\n \"div\",\n \"tvw-relative tvw-ml-auto tvw-clear-chat-button-wrapper\"\n );\n\n clearChatButton = createElement(\n \"button\",\n \"tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n\n clearChatButton.style.height = clearChatSize;\n clearChatButton.style.width = clearChatSize;\n clearChatButton.type = \"button\";\n clearChatButton.setAttribute(\"aria-label\", clearChatTooltipText);\n\n // Add icon\n const iconSvg = renderLucideIcon(clearChatIconName, \"20px\", clearChatIconColor || \"\", 2);\n if (iconSvg) {\n clearChatButton.appendChild(iconSvg);\n }\n\n // Apply styling from config\n if (clearChatIconColor) {\n clearChatButton.style.color = clearChatIconColor;\n clearChatButton.classList.remove(\"tvw-text-cw-muted\");\n }\n\n if (clearChatBgColor) {\n clearChatButton.style.backgroundColor = clearChatBgColor;\n clearChatButton.classList.remove(\"hover:tvw-bg-gray-100\");\n }\n\n if (clearChatBorderWidth || clearChatBorderColor) {\n const borderWidth = clearChatBorderWidth || \"0px\";\n const borderColor = clearChatBorderColor || \"transparent\";\n clearChatButton.style.border = `${borderWidth} solid ${borderColor}`;\n clearChatButton.classList.remove(\"tvw-border-none\");\n }\n\n if (clearChatBorderRadius) {\n clearChatButton.style.borderRadius = clearChatBorderRadius;\n clearChatButton.classList.remove(\"tvw-rounded-full\");\n }\n\n // Apply padding styling\n if (clearChatPaddingX) {\n clearChatButton.style.paddingLeft = clearChatPaddingX;\n clearChatButton.style.paddingRight = clearChatPaddingX;\n } else {\n clearChatButton.style.paddingLeft = \"\";\n clearChatButton.style.paddingRight = \"\";\n }\n if (clearChatPaddingY) {\n clearChatButton.style.paddingTop = clearChatPaddingY;\n clearChatButton.style.paddingBottom = clearChatPaddingY;\n } else {\n clearChatButton.style.paddingTop = \"\";\n clearChatButton.style.paddingBottom = \"\";\n }\n\n clearChatButtonWrapper.appendChild(clearChatButton);\n\n // Add tooltip with portaling to document.body to escape overflow clipping\n if (clearChatShowTooltip && clearChatTooltipText && clearChatButton && clearChatButtonWrapper) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip || !clearChatButton) return; // Already showing or button doesn't exist\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = clearChatTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = clearChatButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n clearChatButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n clearChatButton.addEventListener(\"focus\", showTooltip);\n clearChatButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the button for later use\n (clearChatButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n if (clearChatButtonWrapper) {\n clearChatButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n }\n if (clearChatButton) {\n clearChatButton.removeEventListener(\"focus\", showTooltip);\n clearChatButton.removeEventListener(\"blur\", hideTooltip);\n }\n };\n }\n\n header.appendChild(clearChatButtonWrapper);\n }\n\n // Create close button wrapper for tooltip positioning\n const closeButtonWrapper = createElement(\n \"div\",\n closeButtonPlacement === \"top-right\"\n ? \"tvw-absolute tvw-top-4 tvw-right-4 tvw-z-50\"\n : (clearChatEnabled\n ? \"\"\n : \"tvw-ml-auto\")\n );\n\n // Create close button with base classes\n const closeButton = createElement(\n \"button\",\n \"tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n closeButton.style.height = closeButtonSize;\n closeButton.style.width = closeButtonSize;\n closeButton.type = \"button\";\n\n // Get tooltip config\n const closeButtonTooltipText = launcher.closeButtonTooltipText ?? \"Close chat\";\n const closeButtonShowTooltip = launcher.closeButtonShowTooltip ?? true;\n\n closeButton.setAttribute(\"aria-label\", closeButtonTooltipText);\n closeButton.style.display = showClose ? \"\" : \"none\";\n\n // Add icon or fallback text\n const closeButtonIconName = launcher.closeButtonIconName ?? \"x\";\n const closeButtonIconText = launcher.closeButtonIconText ?? \"×\";\n\n // Try to render Lucide icon, fallback to text if not provided or fails\n const iconSvg = renderLucideIcon(closeButtonIconName, \"20px\", launcher.closeButtonColor || \"\", 2);\n if (iconSvg) {\n closeButton.appendChild(iconSvg);\n } else {\n closeButton.textContent = closeButtonIconText;\n }\n \n // Apply close button styling from config\n if (launcher.closeButtonColor) {\n closeButton.style.color = launcher.closeButtonColor;\n closeButton.classList.remove(\"tvw-text-cw-muted\");\n } else {\n closeButton.style.color = \"\";\n closeButton.classList.add(\"tvw-text-cw-muted\");\n }\n \n if (launcher.closeButtonBackgroundColor) {\n closeButton.style.backgroundColor = launcher.closeButtonBackgroundColor;\n closeButton.classList.remove(\"hover:tvw-bg-gray-100\");\n } else {\n closeButton.style.backgroundColor = \"\";\n closeButton.classList.add(\"hover:tvw-bg-gray-100\");\n }\n \n // Apply border if width and/or color are provided\n if (launcher.closeButtonBorderWidth || launcher.closeButtonBorderColor) {\n const borderWidth = launcher.closeButtonBorderWidth || \"0px\";\n const borderColor = launcher.closeButtonBorderColor || \"transparent\";\n closeButton.style.border = `${borderWidth} solid ${borderColor}`;\n closeButton.classList.remove(\"tvw-border-none\");\n } else {\n closeButton.style.border = \"\";\n closeButton.classList.add(\"tvw-border-none\");\n }\n \n if (launcher.closeButtonBorderRadius) {\n closeButton.style.borderRadius = launcher.closeButtonBorderRadius;\n closeButton.classList.remove(\"tvw-rounded-full\");\n } else {\n closeButton.style.borderRadius = \"\";\n closeButton.classList.add(\"tvw-rounded-full\");\n }\n\n // Apply padding styling\n if (launcher.closeButtonPaddingX) {\n closeButton.style.paddingLeft = launcher.closeButtonPaddingX;\n closeButton.style.paddingRight = launcher.closeButtonPaddingX;\n } else {\n closeButton.style.paddingLeft = \"\";\n closeButton.style.paddingRight = \"\";\n }\n if (launcher.closeButtonPaddingY) {\n closeButton.style.paddingTop = launcher.closeButtonPaddingY;\n closeButton.style.paddingBottom = launcher.closeButtonPaddingY;\n } else {\n closeButton.style.paddingTop = \"\";\n closeButton.style.paddingBottom = \"\";\n }\n\n closeButtonWrapper.appendChild(closeButton);\n\n // Add tooltip with portaling to document.body to escape overflow clipping\n if (closeButtonShowTooltip && closeButtonTooltipText) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip) return; // Already showing\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = closeButtonTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = closeButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n closeButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n closeButton.addEventListener(\"focus\", showTooltip);\n closeButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the wrapper for later use\n (closeButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n closeButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n closeButton.removeEventListener(\"focus\", showTooltip);\n closeButton.removeEventListener(\"blur\", hideTooltip);\n };\n }\n\n // Position close button wrapper based on placement\n if (closeButtonPlacement === \"top-right\") {\n // Make container position relative for absolute positioning\n container.style.position = \"relative\";\n container.appendChild(closeButtonWrapper);\n } else {\n // Inline placement: append to header\n header.appendChild(closeButtonWrapper);\n }\n\n const body = createElement(\n \"div\",\n \"tvw-flex tvw-flex-1 tvw-min-h-0 tvw-flex-col tvw-gap-6 tvw-overflow-y-auto tvw-bg-cw-container tvw-px-6 tvw-py-6\"\n );\n body.id = \"vanilla-agent-scroll-container\";\n const introCard = createElement(\n \"div\",\n \"tvw-rounded-2xl tvw-bg-cw-surface tvw-p-6 tvw-shadow-sm\"\n );\n const introTitle = createElement(\n \"h2\",\n \"tvw-text-lg tvw-font-semibold tvw-text-cw-primary\"\n );\n introTitle.textContent = config?.copy?.welcomeTitle ?? \"Hello 👋\";\n const introSubtitle = createElement(\n \"p\",\n \"tvw-mt-2 tvw-text-sm tvw-text-cw-muted\"\n );\n introSubtitle.textContent =\n config?.copy?.welcomeSubtitle ??\n \"Ask anything about your account or products.\";\n introCard.append(introTitle, introSubtitle);\n\n const messagesWrapper = createElement(\n \"div\",\n \"tvw-flex tvw-flex-col tvw-gap-3\"\n );\n\n body.append(introCard, messagesWrapper);\n\n const footer = createElement(\n \"div\",\n \"tvw-border-t-cw-divider tvw-bg-cw-surface tvw-px-6 tvw-py-4\"\n );\n const suggestions = createElement(\n \"div\",\n \"tvw-mb-3 tvw-flex tvw-flex-wrap tvw-gap-2\"\n );\n // Determine gap based on voice recognition\n const voiceRecognitionEnabledForGap = config?.voiceRecognition?.enabled === true;\n const hasSpeechRecognitionForGap = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n const shouldUseSmallGap = voiceRecognitionEnabledForGap && hasSpeechRecognitionForGap;\n const gapClass = shouldUseSmallGap ? \"tvw-gap-1\" : \"tvw-gap-3\";\n \n const composerForm = createElement(\n \"form\",\n `tvw-flex tvw-items-end ${gapClass} tvw-rounded-2xl tvw-border tvw-border-gray-200 tvw-bg-cw-input-background tvw-px-4 tvw-py-3`\n ) as HTMLFormElement;\n // Prevent form from getting focus styles\n composerForm.style.outline = \"none\";\n \n const textarea = createElement(\"textarea\") as HTMLTextAreaElement;\n textarea.placeholder = config?.copy?.inputPlaceholder ?? \"Type your message…\";\n textarea.className =\n \"tvw-min-h-[48px] tvw-flex-1 tvw-resize-none tvw-border-none tvw-bg-transparent tvw-text-sm tvw-text-cw-primary focus:tvw-outline-none focus:tvw-border-none\";\n textarea.rows = 1;\n \n // Apply font family and weight from config\n const fontFamily = config?.theme?.inputFontFamily ?? \"sans-serif\";\n const fontWeight = config?.theme?.inputFontWeight ?? \"400\";\n \n const getFontFamilyValue = (family: \"sans-serif\" | \"serif\" | \"mono\"): string => {\n switch (family) {\n case \"serif\":\n return 'Georgia, \"Times New Roman\", Times, serif';\n case \"mono\":\n return '\"Courier New\", Courier, \"Lucida Console\", Monaco, monospace';\n case \"sans-serif\":\n default:\n return '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif';\n }\n };\n \n textarea.style.fontFamily = getFontFamilyValue(fontFamily);\n textarea.style.fontWeight = fontWeight;\n \n // Explicitly remove border and outline on focus to prevent browser defaults\n textarea.style.border = \"none\";\n textarea.style.outline = \"none\";\n textarea.style.borderWidth = \"0\";\n textarea.style.borderStyle = \"none\";\n textarea.style.borderColor = \"transparent\";\n textarea.addEventListener(\"focus\", () => {\n textarea.style.border = \"none\";\n textarea.style.outline = \"none\";\n textarea.style.borderWidth = \"0\";\n textarea.style.borderStyle = \"none\";\n textarea.style.borderColor = \"transparent\";\n textarea.style.boxShadow = \"none\";\n });\n textarea.addEventListener(\"blur\", () => {\n textarea.style.border = \"none\";\n textarea.style.outline = \"none\";\n });\n // Send button configuration\n const sendButtonConfig = config?.sendButton ?? {};\n const useIcon = sendButtonConfig.useIcon ?? false;\n const iconText = sendButtonConfig.iconText ?? \"↑\";\n const iconName = sendButtonConfig.iconName;\n const tooltipText = sendButtonConfig.tooltipText ?? \"Send message\";\n const showTooltip = sendButtonConfig.showTooltip ?? false;\n const buttonSize = sendButtonConfig.size ?? \"40px\";\n const backgroundColor = sendButtonConfig.backgroundColor;\n const textColor = sendButtonConfig.textColor;\n\n // Create wrapper for tooltip positioning\n const sendButtonWrapper = createElement(\"div\", \"tvw-send-button-wrapper\");\n\n const sendButton = createElement(\n \"button\",\n useIcon \n ? \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\"\n : \"tvw-rounded-button tvw-bg-cw-accent tvw-px-4 tvw-py-2 tvw-text-sm tvw-font-semibold disabled:tvw-opacity-50 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n\n sendButton.type = \"submit\";\n\n if (useIcon) {\n // Icon mode: circular button\n sendButton.style.width = buttonSize;\n sendButton.style.height = buttonSize;\n sendButton.style.minWidth = buttonSize;\n sendButton.style.minHeight = buttonSize;\n sendButton.style.fontSize = \"18px\";\n sendButton.style.lineHeight = \"1\";\n \n // Clear any existing content\n sendButton.innerHTML = \"\";\n \n // Use Lucide icon if iconName is provided, otherwise fall back to iconText\n if (iconName) {\n const iconSize = parseFloat(buttonSize) || 24;\n const iconColor = textColor && typeof textColor === 'string' && textColor.trim() ? textColor.trim() : \"currentColor\";\n const iconSvg = renderLucideIcon(iconName, iconSize, iconColor, 2);\n if (iconSvg) {\n sendButton.appendChild(iconSvg);\n sendButton.style.color = iconColor;\n } else {\n // Fallback to text if icon fails to render\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n } else {\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n \n if (backgroundColor) {\n sendButton.style.backgroundColor = backgroundColor;\n } else {\n sendButton.classList.add(\"tvw-bg-cw-primary\");\n }\n } else {\n // Text mode: existing behavior\n sendButton.textContent = config?.copy?.sendButtonLabel ?? \"Send\";\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n \n // Apply existing styling from config\n if (sendButtonConfig.borderWidth) {\n sendButton.style.borderWidth = sendButtonConfig.borderWidth;\n sendButton.style.borderStyle = \"solid\";\n }\n if (sendButtonConfig.borderColor) {\n sendButton.style.borderColor = sendButtonConfig.borderColor;\n }\n \n // Apply padding styling (works in both icon and text mode)\n if (sendButtonConfig.paddingX) {\n sendButton.style.paddingLeft = sendButtonConfig.paddingX;\n sendButton.style.paddingRight = sendButtonConfig.paddingX;\n } else {\n sendButton.style.paddingLeft = \"\";\n sendButton.style.paddingRight = \"\";\n }\n if (sendButtonConfig.paddingY) {\n sendButton.style.paddingTop = sendButtonConfig.paddingY;\n sendButton.style.paddingBottom = sendButtonConfig.paddingY;\n } else {\n sendButton.style.paddingTop = \"\";\n sendButton.style.paddingBottom = \"\";\n }\n\n // Add tooltip if enabled\n if (showTooltip && tooltipText) {\n const tooltip = createElement(\"div\", \"tvw-send-button-tooltip\");\n tooltip.textContent = tooltipText;\n sendButtonWrapper.appendChild(tooltip);\n }\n\n sendButtonWrapper.appendChild(sendButton);\n \n // Voice recognition mic button\n const voiceRecognitionConfig = config?.voiceRecognition ?? {};\n const voiceRecognitionEnabled = voiceRecognitionConfig.enabled === true;\n let micButton: HTMLButtonElement | null = null;\n let micButtonWrapper: HTMLElement | null = null;\n \n // Check browser support for speech recognition\n const hasSpeechRecognition = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n \n if (voiceRecognitionEnabled && hasSpeechRecognition) {\n micButtonWrapper = createElement(\"div\", \"tvw-send-button-wrapper\");\n micButton = createElement(\n \"button\",\n \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n \n micButton.type = \"button\";\n micButton.setAttribute(\"aria-label\", \"Start voice recognition\");\n \n const micIconName = voiceRecognitionConfig.iconName ?? \"mic\";\n const micIconSize = voiceRecognitionConfig.iconSize ?? buttonSize;\n const micIconSizeNum = parseFloat(micIconSize) || 24;\n \n // Use dedicated colors from voice recognition config, fallback to send button colors\n const micBackgroundColor = voiceRecognitionConfig.backgroundColor ?? backgroundColor;\n const micIconColor = voiceRecognitionConfig.iconColor ?? textColor;\n \n micButton.style.width = micIconSize;\n micButton.style.height = micIconSize;\n micButton.style.minWidth = micIconSize;\n micButton.style.minHeight = micIconSize;\n micButton.style.fontSize = \"18px\";\n micButton.style.lineHeight = \"1\";\n \n // Use Lucide mic icon with configured color (stroke width 1.5 for minimalist outline style)\n const iconColorValue = micIconColor || \"currentColor\";\n const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColorValue, 1.5);\n if (micIconSvg) {\n micButton.appendChild(micIconSvg);\n micButton.style.color = iconColorValue;\n } else {\n // Fallback to text if icon fails\n micButton.textContent = \"🎤\";\n micButton.style.color = iconColorValue;\n }\n \n // Apply background color\n if (micBackgroundColor) {\n micButton.style.backgroundColor = micBackgroundColor;\n } else {\n micButton.classList.add(\"tvw-bg-cw-primary\");\n }\n \n // Apply icon/text color\n if (micIconColor) {\n micButton.style.color = micIconColor;\n } else if (!micIconColor && !textColor) {\n micButton.classList.add(\"tvw-text-white\");\n }\n \n // Apply border styling\n if (voiceRecognitionConfig.borderWidth) {\n micButton.style.borderWidth = voiceRecognitionConfig.borderWidth;\n micButton.style.borderStyle = \"solid\";\n }\n if (voiceRecognitionConfig.borderColor) {\n micButton.style.borderColor = voiceRecognitionConfig.borderColor;\n }\n \n // Apply padding styling\n if (voiceRecognitionConfig.paddingX) {\n micButton.style.paddingLeft = voiceRecognitionConfig.paddingX;\n micButton.style.paddingRight = voiceRecognitionConfig.paddingX;\n }\n if (voiceRecognitionConfig.paddingY) {\n micButton.style.paddingTop = voiceRecognitionConfig.paddingY;\n micButton.style.paddingBottom = voiceRecognitionConfig.paddingY;\n }\n \n micButtonWrapper.appendChild(micButton);\n \n // Add tooltip if enabled\n const tooltipText = voiceRecognitionConfig.tooltipText ?? \"Start voice recognition\";\n const showTooltip = voiceRecognitionConfig.showTooltip ?? false;\n if (showTooltip && tooltipText) {\n const tooltip = createElement(\"div\", \"tvw-send-button-tooltip\");\n tooltip.textContent = tooltipText;\n micButtonWrapper.appendChild(tooltip);\n }\n }\n \n // Focus textarea when composer form container is clicked\n composerForm.addEventListener(\"click\", (e) => {\n // Don't focus if clicking on the send button, mic button, or their wrappers\n if (e.target !== sendButton && e.target !== sendButtonWrapper && \n e.target !== micButton && e.target !== micButtonWrapper) {\n textarea.focus();\n }\n });\n \n // Append elements: textarea, mic button (if exists), send button\n composerForm.append(textarea);\n if (micButtonWrapper) {\n composerForm.append(micButtonWrapper);\n }\n composerForm.append(sendButtonWrapper);\n\n const statusText = createElement(\n \"div\",\n \"tvw-mt-2 tvw-text-right tvw-text-xs tvw-text-cw-muted\"\n );\n \n // Apply status indicator config\n const statusConfig = config?.statusIndicator ?? {};\n const isVisible = statusConfig.visible ?? true;\n statusText.style.display = isVisible ? \"\" : \"none\";\n statusText.textContent = statusConfig.idleText ?? \"Online\";\n\n footer.append(suggestions, composerForm, statusText);\n\n container.append(header, body, footer);\n\n return {\n container,\n body,\n messagesWrapper,\n suggestions,\n textarea,\n sendButton,\n sendButtonWrapper,\n micButton,\n micButtonWrapper,\n composerForm,\n statusText,\n introTitle,\n introSubtitle,\n closeButton,\n closeButtonWrapper,\n clearChatButton,\n clearChatButtonWrapper,\n iconHolder,\n headerTitle: title,\n headerSubtitle: subtitle\n };\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage } from \"../types\";\n\nexport type MessageTransform = (context: {\n text: string;\n message: AgentWidgetMessage;\n streaming: boolean;\n raw?: string;\n}) => string;\n\n// Create typing indicator element\nexport const createTypingIndicator = (): HTMLElement => {\n const container = document.createElement(\"div\");\n container.className = \"tvw-flex tvw-items-center tvw-space-x-1 tvw-h-5 tvw-mt-2\";\n\n const dot1 = document.createElement(\"div\");\n dot1.className = \"tvw-bg-cw-primary tvw-animate-typing tvw-rounded-full tvw-h-1.5 tvw-w-1.5\";\n dot1.style.animationDelay = \"0ms\";\n\n const dot2 = document.createElement(\"div\");\n dot2.className = \"tvw-bg-cw-primary tvw-animate-typing tvw-rounded-full tvw-h-1.5 tvw-w-1.5\";\n dot2.style.animationDelay = \"250ms\";\n\n const dot3 = document.createElement(\"div\");\n dot3.className = \"tvw-bg-cw-primary tvw-animate-typing tvw-rounded-full tvw-h-1.5 tvw-w-1.5\";\n dot3.style.animationDelay = \"500ms\";\n\n const srOnly = document.createElement(\"span\");\n srOnly.className = \"tvw-sr-only\";\n srOnly.textContent = \"Loading\";\n\n container.appendChild(dot1);\n container.appendChild(dot2);\n container.appendChild(dot3);\n container.appendChild(srOnly);\n\n return container;\n};\n\nexport const createStandardBubble = (\n message: AgentWidgetMessage,\n transform: MessageTransform\n): HTMLElement => {\n const classes = [\n \"vanilla-message-bubble\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-text-sm\",\n \"tvw-leading-relaxed\",\n \"tvw-shadow-sm\"\n ];\n\n if (message.role === \"user\") {\n classes.push(\n \"vanilla-message-user-bubble\",\n \"tvw-ml-auto\",\n \"tvw-bg-cw-accent\",\n \"tvw-text-white\",\n \"tvw-px-5\",\n \"tvw-py-3\"\n );\n } else {\n classes.push(\n \"vanilla-message-assistant-bubble\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-px-5\",\n \"tvw-py-3\"\n );\n }\n\n const bubble = createElement(\"div\", classes.join(\" \"));\n\n // Add message content\n const contentDiv = document.createElement(\"div\");\n contentDiv.innerHTML = transform({\n text: message.content,\n message,\n streaming: Boolean(message.streaming),\n raw: message.rawContent\n });\n bubble.appendChild(contentDiv);\n\n // Add typing indicator if this is a streaming assistant message\n // Show it when streaming starts (even if content is empty), hide it once content appears\n if (message.streaming && message.role === \"assistant\") {\n // Only show typing indicator if content is empty or just starting\n // Hide it once we have substantial content\n if (!message.content || !message.content.trim()) {\n const typingIndicator = createTypingIndicator();\n bubble.appendChild(typingIndicator);\n }\n }\n\n return bubble;\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage } from \"../types\";\nimport { describeReasonStatus } from \"../utils/formatting\";\nimport { renderLucideIcon } from \"../utils/icons\";\n\n// Expansion state per widget instance\nconst reasoningExpansionState = new Set<string>();\n\nexport const createReasoningBubble = (message: AgentWidgetMessage): HTMLElement => {\n const reasoning = message.reasoning;\n const bubble = createElement(\n \"div\",\n [\n \"vanilla-message-bubble\",\n \"vanilla-reasoning-bubble\",\n \"tvw-w-full\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-shadow-sm\",\n \"tvw-overflow-hidden\",\n \"tvw-px-0\",\n \"tvw-py-0\"\n ].join(\" \")\n );\n\n if (!reasoning) {\n return bubble;\n }\n\n let expanded = reasoningExpansionState.has(message.id);\n const header = createElement(\n \"button\",\n \"tvw-flex tvw-w-full tvw-items-center tvw-justify-between tvw-gap-3 tvw-bg-transparent tvw-px-4 tvw-py-3 tvw-text-left tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n header.type = \"button\";\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n\n const headerContent = createElement(\"div\", \"tvw-flex tvw-flex-col tvw-text-left\");\n const title = createElement(\"span\", \"tvw-text-xs tvw-text-cw-primary\");\n title.textContent = \"Thinking...\";\n headerContent.appendChild(title);\n\n const status = createElement(\"span\", \"tvw-text-xs tvw-text-cw-primary\");\n status.textContent = describeReasonStatus(reasoning);\n headerContent.appendChild(status);\n\n if (reasoning.status === \"complete\") {\n title.style.display = \"none\";\n } else {\n title.style.display = \"\";\n }\n\n const toggleIcon = createElement(\"div\", \"tvw-flex tvw-items-center\");\n const iconColor = \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n\n const headerMeta = createElement(\"div\", \"tvw-flex tvw-items-center tvw-ml-auto\");\n headerMeta.append(toggleIcon);\n\n header.append(headerContent, headerMeta);\n\n const content = createElement(\n \"div\",\n \"tvw-border-t tvw-border-gray-200 tvw-bg-gray-50 tvw-px-4 tvw-py-3\"\n );\n content.style.display = expanded ? \"\" : \"none\";\n\n const text = reasoning.chunks.join(\"\");\n const body = createElement(\n \"div\",\n \"tvw-whitespace-pre-wrap tvw-text-xs tvw-leading-snug tvw-text-cw-muted\"\n );\n body.textContent =\n text ||\n (reasoning.status === \"complete\"\n ? \"No additional context was shared.\"\n : \"Waiting for details…\");\n content.appendChild(body);\n\n const applyExpansionState = () => {\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n // Update chevron icon\n toggleIcon.innerHTML = \"\";\n const iconColor = \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n content.style.display = expanded ? \"\" : \"none\";\n };\n\n const toggleExpansion = () => {\n expanded = !expanded;\n if (expanded) {\n reasoningExpansionState.add(message.id);\n } else {\n reasoningExpansionState.delete(message.id);\n }\n applyExpansionState();\n };\n\n header.addEventListener(\"pointerdown\", (event) => {\n event.preventDefault();\n toggleExpansion();\n });\n\n header.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n toggleExpansion();\n }\n });\n\n applyExpansionState();\n\n bubble.append(header, content);\n return bubble;\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage, AgentWidgetConfig } from \"../types\";\nimport { formatUnknownValue, describeToolTitle } from \"../utils/formatting\";\nimport { renderLucideIcon } from \"../utils/icons\";\n\n// Expansion state per widget instance\nconst toolExpansionState = new Set<string>();\n\nexport const createToolBubble = (message: AgentWidgetMessage, config?: AgentWidgetConfig): HTMLElement => {\n const tool = message.toolCall;\n const toolCallConfig = config?.toolCall ?? {};\n \n const bubble = createElement(\n \"div\",\n [\n \"vanilla-message-bubble\",\n \"vanilla-tool-bubble\",\n \"tvw-w-full\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-shadow-sm\",\n \"tvw-overflow-hidden\",\n \"tvw-px-0\",\n \"tvw-py-0\"\n ].join(\" \")\n );\n\n // Apply bubble-level styles\n if (toolCallConfig.backgroundColor) {\n bubble.style.backgroundColor = toolCallConfig.backgroundColor;\n }\n if (toolCallConfig.borderColor) {\n bubble.style.borderColor = toolCallConfig.borderColor;\n }\n if (toolCallConfig.borderWidth) {\n bubble.style.borderWidth = toolCallConfig.borderWidth;\n }\n if (toolCallConfig.borderRadius) {\n bubble.style.borderRadius = toolCallConfig.borderRadius;\n }\n\n if (!tool) {\n return bubble;\n }\n\n let expanded = toolExpansionState.has(message.id);\n const header = createElement(\n \"button\",\n \"tvw-flex tvw-w-full tvw-items-center tvw-justify-between tvw-gap-3 tvw-bg-transparent tvw-px-4 tvw-py-3 tvw-text-left tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n header.type = \"button\";\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n\n // Apply header styles\n if (toolCallConfig.headerBackgroundColor) {\n header.style.backgroundColor = toolCallConfig.headerBackgroundColor;\n }\n if (toolCallConfig.headerPaddingX) {\n header.style.paddingLeft = toolCallConfig.headerPaddingX;\n header.style.paddingRight = toolCallConfig.headerPaddingX;\n }\n if (toolCallConfig.headerPaddingY) {\n header.style.paddingTop = toolCallConfig.headerPaddingY;\n header.style.paddingBottom = toolCallConfig.headerPaddingY;\n }\n\n const headerContent = createElement(\"div\", \"tvw-flex tvw-flex-col tvw-text-left\");\n const title = createElement(\"span\", \"tvw-text-xs tvw-text-cw-primary\");\n if (toolCallConfig.headerTextColor) {\n title.style.color = toolCallConfig.headerTextColor;\n }\n title.textContent = describeToolTitle(tool);\n headerContent.appendChild(title);\n\n const toggleIcon = createElement(\"div\", \"tvw-flex tvw-items-center\");\n const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n\n const headerMeta = createElement(\"div\", \"tvw-flex tvw-items-center tvw-gap-2 tvw-ml-auto\");\n headerMeta.append(toggleIcon);\n\n header.append(headerContent, headerMeta);\n\n const content = createElement(\n \"div\",\n \"tvw-border-t tvw-border-gray-200 tvw-bg-gray-50 tvw-space-y-3 tvw-px-4 tvw-py-3\"\n );\n content.style.display = expanded ? \"\" : \"none\";\n\n // Apply content styles\n if (toolCallConfig.contentBackgroundColor) {\n content.style.backgroundColor = toolCallConfig.contentBackgroundColor;\n }\n if (toolCallConfig.contentTextColor) {\n content.style.color = toolCallConfig.contentTextColor;\n }\n if (toolCallConfig.contentPaddingX) {\n content.style.paddingLeft = toolCallConfig.contentPaddingX;\n content.style.paddingRight = toolCallConfig.contentPaddingX;\n }\n if (toolCallConfig.contentPaddingY) {\n content.style.paddingTop = toolCallConfig.contentPaddingY;\n content.style.paddingBottom = toolCallConfig.contentPaddingY;\n }\n\n // Add tool name at the top of content\n if (tool.name) {\n const toolName = createElement(\"div\", \"tvw-text-xs tvw-text-cw-muted tvw-italic\");\n if (toolCallConfig.contentTextColor) {\n toolName.style.color = toolCallConfig.contentTextColor;\n } else if (toolCallConfig.headerTextColor) {\n toolName.style.color = toolCallConfig.headerTextColor;\n }\n toolName.textContent = tool.name;\n content.appendChild(toolName);\n }\n\n if (tool.args !== undefined) {\n const argsBlock = createElement(\"div\", \"tvw-space-y-1\");\n const argsLabel = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.labelTextColor) {\n argsLabel.style.color = toolCallConfig.labelTextColor;\n }\n argsLabel.textContent = \"Arguments\";\n const argsPre = createElement(\n \"pre\",\n \"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary\"\n );\n // Ensure font size matches header text (0.75rem / 12px)\n argsPre.style.fontSize = \"0.75rem\";\n argsPre.style.lineHeight = \"1rem\";\n if (toolCallConfig.codeBlockBackgroundColor) {\n argsPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;\n }\n if (toolCallConfig.codeBlockBorderColor) {\n argsPre.style.borderColor = toolCallConfig.codeBlockBorderColor;\n }\n if (toolCallConfig.codeBlockTextColor) {\n argsPre.style.color = toolCallConfig.codeBlockTextColor;\n }\n argsPre.textContent = formatUnknownValue(tool.args);\n argsBlock.append(argsLabel, argsPre);\n content.appendChild(argsBlock);\n }\n\n if (tool.chunks && tool.chunks.length) {\n const logsBlock = createElement(\"div\", \"tvw-space-y-1\");\n const logsLabel = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.labelTextColor) {\n logsLabel.style.color = toolCallConfig.labelTextColor;\n }\n logsLabel.textContent = \"Activity\";\n const logsPre = createElement(\n \"pre\",\n \"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary\"\n );\n // Ensure font size matches header text (0.75rem / 12px)\n logsPre.style.fontSize = \"0.75rem\";\n logsPre.style.lineHeight = \"1rem\";\n if (toolCallConfig.codeBlockBackgroundColor) {\n logsPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;\n }\n if (toolCallConfig.codeBlockBorderColor) {\n logsPre.style.borderColor = toolCallConfig.codeBlockBorderColor;\n }\n if (toolCallConfig.codeBlockTextColor) {\n logsPre.style.color = toolCallConfig.codeBlockTextColor;\n }\n logsPre.textContent = tool.chunks.join(\"\\n\");\n logsBlock.append(logsLabel, logsPre);\n content.appendChild(logsBlock);\n }\n\n if (tool.status === \"complete\" && tool.result !== undefined) {\n const resultBlock = createElement(\"div\", \"tvw-space-y-1\");\n const resultLabel = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.labelTextColor) {\n resultLabel.style.color = toolCallConfig.labelTextColor;\n }\n resultLabel.textContent = \"Result\";\n const resultPre = createElement(\n \"pre\",\n \"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary\"\n );\n // Ensure font size matches header text (0.75rem / 12px)\n resultPre.style.fontSize = \"0.75rem\";\n resultPre.style.lineHeight = \"1rem\";\n if (toolCallConfig.codeBlockBackgroundColor) {\n resultPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;\n }\n if (toolCallConfig.codeBlockBorderColor) {\n resultPre.style.borderColor = toolCallConfig.codeBlockBorderColor;\n }\n if (toolCallConfig.codeBlockTextColor) {\n resultPre.style.color = toolCallConfig.codeBlockTextColor;\n }\n resultPre.textContent = formatUnknownValue(tool.result);\n resultBlock.append(resultLabel, resultPre);\n content.appendChild(resultBlock);\n }\n\n if (tool.status === \"complete\" && typeof tool.duration === \"number\") {\n const duration = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.contentTextColor) {\n duration.style.color = toolCallConfig.contentTextColor;\n }\n duration.textContent = `Duration: ${tool.duration}ms`;\n content.appendChild(duration);\n }\n\n const applyToolExpansion = () => {\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n // Update chevron icon\n toggleIcon.innerHTML = \"\";\n const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n content.style.display = expanded ? \"\" : \"none\";\n };\n\n const toggleToolExpansion = () => {\n expanded = !expanded;\n if (expanded) {\n toolExpansionState.add(message.id);\n } else {\n toolExpansionState.delete(message.id);\n }\n applyToolExpansion();\n };\n\n header.addEventListener(\"pointerdown\", (event) => {\n event.preventDefault();\n toggleToolExpansion();\n });\n\n header.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n toggleToolExpansion();\n }\n });\n\n applyToolExpansion();\n\n bubble.append(header, content);\n return bubble;\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetSession } from \"../session\";\nimport { AgentWidgetMessage, AgentWidgetSuggestionChipsConfig } from \"../types\";\n\nexport interface SuggestionButtons {\n buttons: HTMLButtonElement[];\n render: (\n chips: string[] | undefined,\n session: AgentWidgetSession,\n textarea: HTMLTextAreaElement,\n messages?: AgentWidgetMessage[],\n config?: AgentWidgetSuggestionChipsConfig\n ) => void;\n}\n\nexport const createSuggestions = (container: HTMLElement): SuggestionButtons => {\n const suggestionButtons: HTMLButtonElement[] = [];\n\n const render = (\n chips: string[] | undefined,\n session: AgentWidgetSession,\n textarea: HTMLTextAreaElement,\n messages?: AgentWidgetMessage[],\n chipsConfig?: AgentWidgetSuggestionChipsConfig\n ) => {\n container.innerHTML = \"\";\n suggestionButtons.length = 0;\n if (!chips || !chips.length) return;\n\n // Hide suggestions after the first user message is sent\n // Use provided messages or get from session\n const messagesToCheck = messages ?? (session ? session.getMessages() : []);\n const hasUserMessage = messagesToCheck.some((msg) => msg.role === \"user\");\n if (hasUserMessage) return;\n\n const fragment = document.createDocumentFragment();\n const streaming = session ? session.isStreaming() : false;\n\n // Get font family mapping function\n const getFontFamilyValue = (family: \"sans-serif\" | \"serif\" | \"mono\"): string => {\n switch (family) {\n case \"serif\":\n return 'Georgia, \"Times New Roman\", Times, serif';\n case \"mono\":\n return '\"Courier New\", Courier, \"Lucida Console\", Monaco, monospace';\n case \"sans-serif\":\n default:\n return '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif';\n }\n };\n\n chips.forEach((chip) => {\n const btn = createElement(\n \"button\",\n \"tvw-rounded-button tvw-bg-cw-surface tvw-px-3 tvw-py-1.5 tvw-text-xs tvw-font-medium tvw-text-cw-muted hover:tvw-opacity-90 tvw-cursor-pointer tvw-border tvw-border-gray-200\"\n ) as HTMLButtonElement;\n btn.type = \"button\";\n btn.textContent = chip;\n btn.disabled = streaming;\n\n // Apply typography settings\n if (chipsConfig?.fontFamily) {\n btn.style.fontFamily = getFontFamilyValue(chipsConfig.fontFamily);\n }\n if (chipsConfig?.fontWeight) {\n btn.style.fontWeight = chipsConfig.fontWeight;\n }\n\n // Apply padding settings\n if (chipsConfig?.paddingX) {\n btn.style.paddingLeft = chipsConfig.paddingX;\n btn.style.paddingRight = chipsConfig.paddingX;\n }\n if (chipsConfig?.paddingY) {\n btn.style.paddingTop = chipsConfig.paddingY;\n btn.style.paddingBottom = chipsConfig.paddingY;\n }\n\n btn.addEventListener(\"click\", () => {\n if (!session || session.isStreaming()) return;\n textarea.value = \"\";\n session.sendMessage(chip);\n });\n fragment.appendChild(btn);\n suggestionButtons.push(btn);\n });\n container.appendChild(fragment);\n };\n\n return {\n buttons: suggestionButtons,\n render\n };\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage, AgentWidgetConfig } from \"../types\";\nimport { AgentWidgetSession } from \"../session\";\n\nexport const formDefinitions: Record<\n string,\n {\n title: string;\n description?: string;\n fields: Array<{\n name: string;\n label: string;\n placeholder?: string;\n type?: \"text\" | \"email\" | \"textarea\";\n required?: boolean;\n }>;\n submitLabel?: string;\n }\n> = {\n init: {\n title: \"Schedule a Demo\",\n description: \"Share the basics and we'll follow up with a confirmation.\",\n fields: [\n { name: \"name\", label: \"Full name\", placeholder: \"Jane Doe\", required: true },\n { name: \"email\", label: \"Work email\", placeholder: \"jane@example.com\", type: \"email\", required: true },\n { name: \"notes\", label: \"What would you like to cover?\", type: \"textarea\" }\n ],\n submitLabel: \"Submit details\"\n },\n followup: {\n title: \"Additional Information\",\n description: \"Provide any extra details to tailor the next steps.\",\n fields: [\n { name: \"company\", label: \"Company\", placeholder: \"Acme Inc.\" },\n { name: \"context\", label: \"Context\", type: \"textarea\", placeholder: \"Share more about your use case\" }\n ],\n submitLabel: \"Send\"\n }\n};\n\nexport const enhanceWithForms = (\n bubble: HTMLElement,\n message: AgentWidgetMessage,\n config: AgentWidgetConfig,\n session: AgentWidgetSession\n) => {\n const placeholders = bubble.querySelectorAll<HTMLElement>(\"[data-tv-form]\");\n if (placeholders.length) {\n placeholders.forEach((placeholder) => {\n if (placeholder.dataset.enhanced === \"true\") return;\n const type = placeholder.dataset.tvForm ?? \"init\";\n placeholder.dataset.enhanced = \"true\";\n\n const definition = formDefinitions[type] ?? formDefinitions.init;\n placeholder.classList.add(\"tvw-form-card\", \"tvw-space-y-4\");\n\n const heading = createElement(\"div\", \"tvw-space-y-1\");\n const title = createElement(\n \"h3\",\n \"tvw-text-base tvw-font-semibold tvw-text-cw-primary\"\n );\n title.textContent = definition.title;\n heading.appendChild(title);\n if (definition.description) {\n const desc = createElement(\n \"p\",\n \"tvw-text-sm tvw-text-cw-muted\"\n );\n desc.textContent = definition.description;\n heading.appendChild(desc);\n }\n\n const form = document.createElement(\"form\");\n form.className = \"tvw-form-grid tvw-space-y-3\";\n\n definition.fields.forEach((field) => {\n const group = createElement(\"label\", \"tvw-form-field tvw-flex tvw-flex-col tvw-gap-1\");\n group.htmlFor = `${message.id}-${type}-${field.name}`;\n const label = createElement(\"span\", \"tvw-text-xs tvw-font-medium tvw-text-cw-muted\");\n label.textContent = field.label;\n group.appendChild(label);\n\n const inputType = field.type ?? \"text\";\n let control: HTMLInputElement | HTMLTextAreaElement;\n if (inputType === \"textarea\") {\n control = document.createElement(\"textarea\");\n control.rows = 3;\n } else {\n control = document.createElement(\"input\");\n control.type = inputType;\n }\n control.className =\n \"tvw-rounded-xl tvw-border tvw-border-gray-200 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-sm tvw-text-cw-primary focus:tvw-outline-none focus:tvw-border-cw-primary\";\n control.id = `${message.id}-${type}-${field.name}`;\n control.name = field.name;\n control.placeholder = field.placeholder ?? \"\";\n if (field.required) {\n control.required = true;\n }\n group.appendChild(control);\n form.appendChild(group);\n });\n\n const actions = createElement(\n \"div\",\n \"tvw-flex tvw-items-center tvw-justify-between tvw-gap-2\"\n );\n const status = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted tvw-min-h-[1.5rem]\"\n );\n const submit = createElement(\n \"button\",\n \"tvw-inline-flex tvw-items-center tvw-rounded-full tvw-bg-cw-primary tvw-px-4 tvw-py-2 tvw-text-sm tvw-font-semibold tvw-text-white disabled:tvw-opacity-60 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n submit.type = \"submit\";\n submit.textContent = definition.submitLabel ?? \"Submit\";\n actions.appendChild(status);\n actions.appendChild(submit);\n form.appendChild(actions);\n\n placeholder.replaceChildren(heading, form);\n\n form.addEventListener(\"submit\", async (event) => {\n event.preventDefault();\n const formEndpoint = config.formEndpoint ?? \"/form\";\n const formData = new FormData(form as HTMLFormElement);\n const payload: Record<string, unknown> = {};\n formData.forEach((value, key) => {\n payload[key] = value;\n });\n payload[\"type\"] = type;\n\n submit.disabled = true;\n status.textContent = \"Submitting…\";\n\n try {\n const response = await fetch(formEndpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(payload)\n });\n if (!response.ok) {\n throw new Error(`Form submission failed (${response.status})`);\n }\n const data = await response.json();\n status.textContent = data.message ?? \"Thanks! We'll be in touch soon.\";\n if (data.success && data.nextPrompt) {\n await session.sendMessage(String(data.nextPrompt));\n }\n } catch (error) {\n status.textContent =\n error instanceof Error ? error.message : \"Something went wrong. Please try again.\";\n } finally {\n submit.disabled = false;\n }\n });\n });\n }\n};\n\n\n\n\n\n\n\n","import { AgentWidgetPlugin } from \"./types\";\n\nclass PluginRegistry {\n private plugins: Map<string, AgentWidgetPlugin> = new Map();\n\n /**\n * Register a plugin\n */\n register(plugin: AgentWidgetPlugin): void {\n if (this.plugins.has(plugin.id)) {\n console.warn(`Plugin \"${plugin.id}\" is already registered. Overwriting.`);\n }\n\n this.plugins.set(plugin.id, plugin);\n plugin.onRegister?.();\n }\n\n /**\n * Unregister a plugin\n */\n unregister(pluginId: string): void {\n const plugin = this.plugins.get(pluginId);\n if (plugin) {\n plugin.onUnregister?.();\n this.plugins.delete(pluginId);\n }\n }\n\n /**\n * Get all plugins sorted by priority\n */\n getAll(): AgentWidgetPlugin[] {\n return Array.from(this.plugins.values()).sort(\n (a, b) => (b.priority ?? 0) - (a.priority ?? 0)\n );\n }\n\n /**\n * Get plugins for a specific instance (from config)\n * Merges instance plugins with globally registered plugins\n */\n getForInstance(instancePlugins?: AgentWidgetPlugin[]): AgentWidgetPlugin[] {\n const allPlugins = this.getAll();\n\n if (!instancePlugins || instancePlugins.length === 0) {\n return allPlugins;\n }\n\n // Merge instance plugins with global plugins\n // Instance plugins override global plugins with the same ID\n const instanceIds = new Set(instancePlugins.map(p => p.id));\n const merged = [\n ...allPlugins.filter(p => !instanceIds.has(p.id)),\n ...instancePlugins\n ];\n\n return merged.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n }\n\n /**\n * Clear all plugins\n */\n clear(): void {\n this.plugins.forEach(plugin => plugin.onUnregister?.());\n this.plugins.clear();\n }\n}\n\nexport const pluginRegistry = new PluginRegistry();\n\n\n\n\n\n\n\n","import type { AgentWidgetConfig } from \"./types\";\n\n/**\n * Default widget configuration\n * Single source of truth for all default values\n */\nexport const DEFAULT_WIDGET_CONFIG: Partial<AgentWidgetConfig> = {\n apiUrl: \"http://localhost:43111/api/chat/dispatch\",\n theme: {\n primary: \"#111827\",\n accent: \"#1d4ed8\",\n surface: \"#ffffff\",\n muted: \"#6b7280\",\n container: \"#f8fafc\",\n border: \"#f1f5f9\",\n divider: \"#f1f5f9\",\n messageBorder: \"#f1f5f9\",\n inputBackground: \"#ffffff\",\n callToAction: \"#000000\",\n callToActionBackground: \"#ffffff\",\n sendButtonBackgroundColor: \"#111827\",\n sendButtonTextColor: \"#ffffff\",\n sendButtonBorderColor: \"#60a5fa\",\n closeButtonColor: \"#6b7280\",\n closeButtonBackgroundColor: \"transparent\",\n closeButtonBorderColor: \"\",\n clearChatIconColor: \"#6b7280\",\n clearChatBackgroundColor: \"transparent\",\n clearChatBorderColor: \"transparent\",\n micIconColor: \"#111827\",\n micBackgroundColor: \"transparent\",\n micBorderColor: \"transparent\",\n recordingIconColor: \"#ffffff\",\n recordingBackgroundColor: \"#ef4444\",\n recordingBorderColor: \"transparent\",\n inputFontFamily: \"sans-serif\",\n inputFontWeight: \"400\",\n radiusSm: \"0.75rem\",\n radiusMd: \"1rem\",\n radiusLg: \"1.5rem\",\n launcherRadius: \"9999px\",\n buttonRadius: \"9999px\",\n },\n launcher: {\n enabled: true,\n title: \"Chat Assistant\",\n subtitle: \"Here to help you get answers fast\",\n agentIconText: \"💬\",\n position: \"bottom-right\",\n width: \"min(400px, calc(100vw - 24px))\",\n autoExpand: false,\n callToActionIconHidden: false,\n agentIconSize: \"40px\",\n headerIconSize: \"40px\",\n closeButtonSize: \"32px\",\n callToActionIconName: \"arrow-up-right\",\n callToActionIconText: \"\",\n callToActionIconSize: \"32px\",\n callToActionIconPadding: \"5px\",\n callToActionIconColor: \"#000000\",\n callToActionIconBackgroundColor: \"#ffffff\",\n closeButtonColor: \"#6b7280\",\n closeButtonBackgroundColor: \"transparent\",\n clearChat: {\n iconColor: \"#6b7280\",\n backgroundColor: \"transparent\",\n borderColor: \"transparent\",\n enabled: true,\n iconName: \"refresh-cw\",\n size: \"29px\",\n showTooltip: true,\n tooltipText: \"Clear chat\",\n paddingX: \"0px\",\n paddingY: \"0px\",\n },\n headerIconHidden: false,\n },\n copy: {\n welcomeTitle: \"Hello 👋\",\n welcomeSubtitle: \"Ask anything about your account or products.\",\n inputPlaceholder: \"How can I help...\",\n sendButtonLabel: \"Send\",\n },\n sendButton: {\n borderWidth: \"0px\",\n paddingX: \"12px\",\n paddingY: \"10px\",\n backgroundColor: \"#111827\",\n textColor: \"#ffffff\",\n borderColor: \"#60a5fa\",\n useIcon: true,\n iconText: \"↑\",\n size: \"40px\",\n showTooltip: true,\n tooltipText: \"Send message\",\n iconName: \"send\",\n },\n statusIndicator: {\n visible: true,\n idleText: \"Online\",\n connectingText: \"Connecting…\",\n connectedText: \"Streaming…\",\n errorText: \"Offline\",\n },\n voiceRecognition: {\n enabled: true,\n pauseDuration: 2000,\n iconName: \"mic\",\n iconSize: \"39px\",\n borderWidth: \"0px\",\n paddingX: \"9px\",\n paddingY: \"14px\",\n iconColor: \"#111827\",\n backgroundColor: \"transparent\",\n borderColor: \"transparent\",\n recordingIconColor: \"#ffffff\",\n recordingBackgroundColor: \"#ef4444\",\n recordingBorderColor: \"transparent\",\n showTooltip: true,\n tooltipText: \"Start voice recognition\",\n },\n features: {\n showReasoning: true,\n showToolCalls: true,\n },\n suggestionChips: [\n \"What can you help me with?\",\n \"Tell me about your features\",\n \"How does this work?\",\n ],\n suggestionChipsConfig: {\n fontFamily: \"sans-serif\",\n fontWeight: \"500\",\n paddingX: \"12px\",\n paddingY: \"6px\",\n },\n debug: false,\n};\n\n/**\n * Helper to deep merge user config with defaults\n * This ensures all default values are present while allowing selective overrides\n */\nexport function mergeWithDefaults(\n config?: Partial<AgentWidgetConfig>\n): Partial<AgentWidgetConfig> {\n if (!config) return DEFAULT_WIDGET_CONFIG;\n\n return {\n ...DEFAULT_WIDGET_CONFIG,\n ...config,\n theme: {\n ...DEFAULT_WIDGET_CONFIG.theme,\n ...config.theme,\n },\n launcher: {\n ...DEFAULT_WIDGET_CONFIG.launcher,\n ...config.launcher,\n clearChat: {\n ...DEFAULT_WIDGET_CONFIG.launcher?.clearChat,\n ...config.launcher?.clearChat,\n },\n },\n copy: {\n ...DEFAULT_WIDGET_CONFIG.copy,\n ...config.copy,\n },\n sendButton: {\n ...DEFAULT_WIDGET_CONFIG.sendButton,\n ...config.sendButton,\n },\n statusIndicator: {\n ...DEFAULT_WIDGET_CONFIG.statusIndicator,\n ...config.statusIndicator,\n },\n voiceRecognition: {\n ...DEFAULT_WIDGET_CONFIG.voiceRecognition,\n ...config.voiceRecognition,\n },\n features: {\n ...DEFAULT_WIDGET_CONFIG.features,\n ...config.features,\n },\n suggestionChips: config.suggestionChips ?? DEFAULT_WIDGET_CONFIG.suggestionChips,\n suggestionChipsConfig: {\n ...DEFAULT_WIDGET_CONFIG.suggestionChipsConfig,\n ...config.suggestionChipsConfig,\n },\n };\n}\n","type Handler<T> = (payload: T) => void;\n\nexport type EventUnsubscribe = () => void;\n\nexport const createEventBus = <EventMap extends Record<string, any>>() => {\n const listeners = new Map<keyof EventMap, Set<Handler<any>>>();\n\n const on = <K extends keyof EventMap>(\n event: K,\n handler: Handler<EventMap[K]>\n ): EventUnsubscribe => {\n if (!listeners.has(event)) {\n listeners.set(event, new Set());\n }\n listeners.get(event)!.add(handler as Handler<any>);\n return () => off(event, handler);\n };\n\n const off = <K extends keyof EventMap>(\n event: K,\n handler: Handler<EventMap[K]>\n ) => {\n listeners.get(event)?.delete(handler as Handler<any>);\n };\n\n const emit = <K extends keyof EventMap>(event: K, payload: EventMap[K]) => {\n listeners.get(event)?.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Event handler error:\", error);\n }\n }\n });\n };\n\n return { on, off, emit };\n};\n\n","import type {\n AgentWidgetActionContext,\n AgentWidgetActionEventPayload,\n AgentWidgetActionHandler,\n AgentWidgetActionHandlerResult,\n AgentWidgetActionParser,\n AgentWidgetParsedAction,\n AgentWidgetControllerEventMap,\n AgentWidgetMessage\n} from \"../types\";\n\ntype ActionManagerProcessContext = {\n text: string;\n message: AgentWidgetMessage;\n streaming: boolean;\n raw?: string;\n};\n\ntype ActionManagerOptions = {\n parsers: AgentWidgetActionParser[];\n handlers: AgentWidgetActionHandler[];\n getMetadata: () => Record<string, unknown>;\n updateMetadata: (\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) => void;\n emit: <K extends keyof AgentWidgetControllerEventMap>(\n event: K,\n payload: AgentWidgetControllerEventMap[K]\n ) => void;\n documentRef: Document | null;\n};\n\nconst stripCodeFence = (value: string) => {\n const match = value.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n return match ? match[1] : value;\n};\n\nconst extractJsonObject = (value: string) => {\n const trimmed = value.trim();\n const start = trimmed.indexOf(\"{\");\n if (start === -1) return null;\n\n let depth = 0;\n for (let i = start; i < trimmed.length; i += 1) {\n const char = trimmed[i];\n if (char === \"{\") depth += 1;\n if (char === \"}\") {\n depth -= 1;\n if (depth === 0) {\n return trimmed.slice(start, i + 1);\n }\n }\n }\n return null;\n};\n\nexport const defaultJsonActionParser: AgentWidgetActionParser = ({ text }) => {\n if (!text) return null;\n if (!text.includes(\"{\")) return null;\n\n try {\n const withoutFence = stripCodeFence(text);\n const jsonBody = extractJsonObject(withoutFence);\n if (!jsonBody) return null;\n const parsed = JSON.parse(jsonBody);\n if (!parsed || typeof parsed !== \"object\" || !parsed.action) {\n return null;\n }\n const { action, ...payload } = parsed;\n return {\n type: String(action),\n payload,\n raw: parsed\n };\n } catch {\n return null;\n }\n};\n\nconst asString = (value: unknown) =>\n typeof value === \"string\" ? value : value == null ? \"\" : String(value);\n\nexport const defaultActionHandlers: Record<\n string,\n AgentWidgetActionHandler\n> = {\n message: (action) => {\n if (action.type !== \"message\") return;\n const text = asString((action.payload as Record<string, unknown>).text);\n return {\n handled: true,\n displayText: text\n };\n },\n messageAndClick: (action, context) => {\n if (action.type !== \"message_and_click\") return;\n const payload = action.payload as Record<string, unknown>;\n const selector = asString(payload.element);\n if (selector && context.document?.querySelector) {\n const element = context.document.querySelector<HTMLElement>(selector);\n if (element) {\n setTimeout(() => {\n element.click();\n }, 400);\n } else if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.warn(\"[AgentWidget] Element not found for selector:\", selector);\n }\n }\n return {\n handled: true,\n displayText: asString(payload.text)\n };\n }\n};\n\nconst ensureArrayOfStrings = (value: unknown): string[] => {\n if (Array.isArray(value)) {\n return value.map((entry) => String(entry));\n }\n return [];\n};\n\nexport const createActionManager = (options: ActionManagerOptions) => {\n let processedIds = new Set(\n ensureArrayOfStrings(options.getMetadata().processedActionMessageIds)\n );\n\n const syncFromMetadata = () => {\n processedIds = new Set(\n ensureArrayOfStrings(options.getMetadata().processedActionMessageIds)\n );\n };\n\n const persistProcessedIds = () => {\n const latestIds = Array.from(processedIds);\n options.updateMetadata((prev) => ({\n ...prev,\n processedActionMessageIds: latestIds\n }));\n };\n\n const process = (context: ActionManagerProcessContext): { text: string; persist: boolean } | null => {\n if (\n context.streaming ||\n context.message.role !== \"assistant\" ||\n !context.text ||\n processedIds.has(context.message.id)\n ) {\n return null;\n }\n\n const parseSource =\n (typeof context.raw === \"string\" && context.raw) ||\n (typeof context.message.rawContent === \"string\" &&\n context.message.rawContent) ||\n (typeof context.text === \"string\" && context.text) ||\n null;\n\n if (\n !parseSource &&\n typeof context.text === \"string\" &&\n context.text.trim().startsWith(\"{\") &&\n typeof console !== \"undefined\"\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n \"[AgentWidget] Structured response detected but no raw payload was provided. Ensure your stream parser returns { text, raw }.\"\n );\n }\n\n const action = parseSource\n ? options.parsers.reduce<AgentWidgetParsedAction | null>(\n (acc, parser) =>\n acc || parser?.({ text: parseSource, message: context.message }) || null,\n null\n )\n : null;\n\n if (!action) {\n return null;\n }\n\n processedIds.add(context.message.id);\n persistProcessedIds();\n\n const eventPayload: AgentWidgetActionEventPayload = {\n action,\n message: context.message\n };\n options.emit(\"action:detected\", eventPayload);\n\n for (const handler of options.handlers) {\n if (!handler) continue;\n try {\n const handlerResult = handler(action, {\n message: context.message,\n metadata: options.getMetadata(),\n updateMetadata: options.updateMetadata,\n document: options.documentRef\n } as AgentWidgetActionContext) as AgentWidgetActionHandlerResult | void;\n\n if (!handlerResult) continue;\n\n if (handlerResult.handled) {\n // persistMessage defaults to true if not specified\n const persist = handlerResult.persistMessage !== false;\n const displayText = handlerResult.displayText !== undefined ? handlerResult.displayText : \"\";\n return { text: displayText, persist };\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Action handler error:\", error);\n }\n }\n }\n\n return { text: \"\", persist: true };\n };\n\n return {\n process,\n syncFromMetadata\n };\n};\n\n","import { escapeHtml } from \"./postprocessors\";\nimport { AgentWidgetSession, AgentWidgetSessionStatus } from \"./session\";\nimport {\n AgentWidgetConfig,\n AgentWidgetMessage,\n AgentWidgetEvent,\n AgentWidgetStorageAdapter,\n AgentWidgetStoredState,\n AgentWidgetControllerEventMap,\n AgentWidgetVoiceStateEvent,\n AgentWidgetStateEvent,\n AgentWidgetStateSnapshot\n} from \"./types\";\nimport { applyThemeVariables } from \"./utils/theme\";\nimport { renderLucideIcon } from \"./utils/icons\";\nimport { createElement } from \"./utils/dom\";\nimport { statusCopy } from \"./utils/constants\";\nimport { createLauncherButton } from \"./components/launcher\";\nimport { createWrapper, buildPanel } from \"./components/panel\";\nimport { MessageTransform } from \"./components/message-bubble\";\nimport { createStandardBubble, createTypingIndicator } from \"./components/message-bubble\";\nimport { createReasoningBubble } from \"./components/reasoning-bubble\";\nimport { createToolBubble } from \"./components/tool-bubble\";\nimport { createSuggestions } from \"./components/suggestions\";\nimport { enhanceWithForms } from \"./components/forms\";\nimport { pluginRegistry } from \"./plugins/registry\";\nimport { mergeWithDefaults } from \"./defaults\";\nimport { createEventBus } from \"./utils/events\";\nimport {\n createActionManager,\n defaultActionHandlers,\n defaultJsonActionParser\n} from \"./utils/actions\";\n\n// Default localStorage key for chat history (automatically cleared on clear chat)\nconst DEFAULT_CHAT_HISTORY_STORAGE_KEY = \"vanilla-agent-chat-history\";\nconst VOICE_STATE_RESTORE_WINDOW = 30 * 1000;\n\nconst ensureRecord = (value: unknown): Record<string, unknown> => {\n if (!value || typeof value !== \"object\") {\n return {};\n }\n return { ...(value as Record<string, unknown>) };\n};\n\nconst stripStreamingFromMessages = (messages: AgentWidgetMessage[]) =>\n messages.map((message) => ({\n ...message,\n streaming: false\n }));\n\ntype Controller = {\n update: (config: AgentWidgetConfig) => void;\n destroy: () => void;\n open: () => void;\n close: () => void;\n toggle: () => void;\n clearChat: () => void;\n setMessage: (message: string) => boolean;\n submitMessage: (message?: string) => boolean;\n startVoiceRecognition: () => boolean;\n stopVoiceRecognition: () => boolean;\n injectTestMessage: (event: AgentWidgetEvent) => void;\n getMessages: () => AgentWidgetMessage[];\n getStatus: () => AgentWidgetSessionStatus;\n getPersistentMetadata: () => Record<string, unknown>;\n updatePersistentMetadata: (\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) => void;\n on: <K extends keyof AgentWidgetControllerEventMap>(\n event: K,\n handler: (payload: AgentWidgetControllerEventMap[K]) => void\n ) => () => void;\n off: <K extends keyof AgentWidgetControllerEventMap>(\n event: K,\n handler: (payload: AgentWidgetControllerEventMap[K]) => void\n ) => void;\n // State query methods\n isOpen: () => boolean;\n isVoiceActive: () => boolean;\n getState: () => AgentWidgetStateSnapshot;\n};\n\nconst buildPostprocessor = (\n cfg: AgentWidgetConfig | undefined,\n actionManager?: ReturnType<typeof createActionManager>\n): MessageTransform => {\n return (context) => {\n let nextText = context.text ?? \"\";\n const rawPayload = context.message.rawContent ?? null;\n\n if (actionManager) {\n const actionResult = actionManager.process({\n text: nextText,\n raw: rawPayload ?? nextText,\n message: context.message,\n streaming: context.streaming\n });\n if (actionResult !== null) {\n nextText = actionResult.text;\n // Mark message as non-persistable if persist is false\n if (!actionResult.persist) {\n (context.message as any).__skipPersist = true;\n }\n }\n }\n\n if (cfg?.postprocessMessage) {\n return cfg.postprocessMessage({\n ...context,\n text: nextText,\n raw: rawPayload ?? context.text ?? \"\"\n });\n }\n\n return escapeHtml(nextText);\n };\n};\n\nexport const createAgentExperience = (\n mount: HTMLElement,\n initialConfig?: AgentWidgetConfig,\n runtimeOptions?: { debugTools?: boolean }\n): Controller => {\n // Tailwind config uses important: \"#vanilla-agent-root\", so ensure mount has this ID\n if (!mount.id || mount.id !== \"vanilla-agent-root\") {\n mount.id = \"vanilla-agent-root\";\n }\n\n let config = mergeWithDefaults(initialConfig) as AgentWidgetConfig;\n applyThemeVariables(mount, config);\n\n // Get plugins for this instance\n const plugins = pluginRegistry.getForInstance(config.plugins);\n const eventBus = createEventBus<AgentWidgetControllerEventMap>();\n\n const storageAdapter: AgentWidgetStorageAdapter | undefined =\n config.storageAdapter;\n let persistentMetadata: Record<string, unknown> = {};\n let pendingStoredState: Promise<AgentWidgetStoredState | null> | null = null;\n\n if (storageAdapter?.load) {\n try {\n const storedState = storageAdapter.load();\n if (storedState && typeof (storedState as Promise<any>).then === \"function\") {\n pendingStoredState = storedState as Promise<AgentWidgetStoredState | null>;\n } else if (storedState) {\n const immediateState = storedState as AgentWidgetStoredState;\n if (immediateState.metadata) {\n persistentMetadata = ensureRecord(immediateState.metadata);\n }\n if (immediateState.messages?.length) {\n config = { ...config, initialMessages: immediateState.messages };\n }\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to load stored state:\", error);\n }\n }\n }\n\n const getMetadata = () => persistentMetadata;\n const updateMetadata = (\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) => {\n const next = updater({ ...persistentMetadata }) ?? {};\n persistentMetadata = next;\n persistState();\n };\n\n const resolvedActionParsers =\n config.actionParsers && config.actionParsers.length\n ? config.actionParsers\n : [defaultJsonActionParser];\n\n const resolvedActionHandlers =\n config.actionHandlers && config.actionHandlers.length\n ? config.actionHandlers\n : [defaultActionHandlers.message, defaultActionHandlers.messageAndClick];\n\n let actionManager = createActionManager({\n parsers: resolvedActionParsers,\n handlers: resolvedActionHandlers,\n getMetadata,\n updateMetadata,\n emit: eventBus.emit,\n documentRef: typeof document !== \"undefined\" ? document : null\n });\n actionManager.syncFromMetadata();\n\n let launcherEnabled = config.launcher?.enabled ?? true;\n let autoExpand = config.launcher?.autoExpand ?? false;\n let prevAutoExpand = autoExpand;\n let prevLauncherEnabled = launcherEnabled;\n let open = launcherEnabled ? autoExpand : true;\n let postprocess = buildPostprocessor(config, actionManager);\n let showReasoning = config.features?.showReasoning ?? true;\n let showToolCalls = config.features?.showToolCalls ?? true;\n \n // Get status indicator config\n const statusConfig = config.statusIndicator ?? {};\n const getStatusText = (status: AgentWidgetSessionStatus): string => {\n if (status === \"idle\") return statusConfig.idleText ?? statusCopy.idle;\n if (status === \"connecting\") return statusConfig.connectingText ?? statusCopy.connecting;\n if (status === \"connected\") return statusConfig.connectedText ?? statusCopy.connected;\n if (status === \"error\") return statusConfig.errorText ?? statusCopy.error;\n return statusCopy[status];\n };\n\n const { wrapper, panel } = createWrapper(config);\n const panelElements = buildPanel(config, launcherEnabled);\n const {\n container,\n body,\n messagesWrapper,\n suggestions,\n textarea,\n sendButton,\n sendButtonWrapper,\n composerForm,\n statusText,\n introTitle,\n introSubtitle,\n closeButton,\n iconHolder,\n headerTitle,\n headerSubtitle\n } = panelElements;\n \n // Use mutable references for mic button so we can update them dynamically\n let micButton: HTMLButtonElement | null = panelElements.micButton;\n let micButtonWrapper: HTMLElement | null = panelElements.micButtonWrapper;\n\n panel.appendChild(container);\n mount.appendChild(wrapper);\n\n const destroyCallbacks: Array<() => void> = [];\n const suggestionsManager = createSuggestions(suggestions);\n let closeHandler: (() => void) | null = null;\n let session: AgentWidgetSession;\n let isStreaming = false;\n let shouldAutoScroll = true;\n let lastScrollTop = 0;\n let lastAutoScrollTime = 0;\n let scrollRAF: number | null = null;\n let isAutoScrollBlocked = false;\n let blockUntilTime = 0;\n let isAutoScrolling = false;\n\n const AUTO_SCROLL_THROTTLE = 125;\n const AUTO_SCROLL_BLOCK_TIME = 2000;\n const USER_SCROLL_THRESHOLD = 5;\n const BOTTOM_THRESHOLD = 50;\n const messageState = new Map<\n string,\n { streaming?: boolean; role: AgentWidgetMessage[\"role\"] }\n >();\n const voiceState = {\n active: false,\n manuallyDeactivated: false,\n lastUserMessageWasVoice: false\n };\n const voiceAutoResumeMode = config.voiceRecognition?.autoResume ?? false;\n const emitVoiceState = (source: AgentWidgetVoiceStateEvent[\"source\"]) => {\n eventBus.emit(\"voice:state\", {\n active: voiceState.active,\n source,\n timestamp: Date.now()\n });\n };\n const persistVoiceMetadata = () => {\n updateMetadata((prev) => ({\n ...prev,\n voiceState: {\n active: voiceState.active,\n timestamp: Date.now(),\n manuallyDeactivated: voiceState.manuallyDeactivated\n }\n }));\n };\n const maybeRestoreVoiceFromMetadata = () => {\n if (config.voiceRecognition?.enabled === false) return;\n const rawVoiceState = ensureRecord((persistentMetadata as any).voiceState);\n const wasActive = Boolean(rawVoiceState.active);\n const timestamp = Number(rawVoiceState.timestamp ?? 0);\n voiceState.manuallyDeactivated = Boolean(rawVoiceState.manuallyDeactivated);\n if (wasActive && Date.now() - timestamp < VOICE_STATE_RESTORE_WINDOW) {\n setTimeout(() => {\n if (!voiceState.active) {\n voiceState.manuallyDeactivated = false;\n startVoiceRecognition(\"restore\");\n }\n }, 1000);\n }\n };\n\n const getMessagesForPersistence = () =>\n session \n ? stripStreamingFromMessages(session.getMessages()).filter(msg => !(msg as any).__skipPersist)\n : [];\n\n function persistState(messagesOverride?: AgentWidgetMessage[]) {\n if (!storageAdapter?.save || !session) return;\n const payload = {\n messages: messagesOverride\n ? stripStreamingFromMessages(messagesOverride)\n : getMessagesForPersistence(),\n metadata: persistentMetadata\n };\n try {\n const result = storageAdapter.save(payload);\n if (result instanceof Promise) {\n result.catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to persist state:\", error);\n }\n });\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to persist state:\", error);\n }\n }\n }\n\n const scheduleAutoScroll = (force = false) => {\n if (!shouldAutoScroll) return;\n\n const now = Date.now();\n\n if (isAutoScrollBlocked && now < blockUntilTime) {\n if (!force) return;\n }\n\n if (isAutoScrollBlocked && now >= blockUntilTime) {\n isAutoScrollBlocked = false;\n }\n\n if (!force && !isStreaming) return;\n\n if (now - lastAutoScrollTime < AUTO_SCROLL_THROTTLE) return;\n lastAutoScrollTime = now;\n\n if (scrollRAF) {\n cancelAnimationFrame(scrollRAF);\n }\n\n scrollRAF = requestAnimationFrame(() => {\n if (isAutoScrollBlocked || !shouldAutoScroll) return;\n isAutoScrolling = true;\n body.scrollTop = body.scrollHeight;\n lastScrollTop = body.scrollTop;\n requestAnimationFrame(() => {\n isAutoScrolling = false;\n });\n scrollRAF = null;\n });\n };\n\n // Track ongoing smooth scroll animation\n let smoothScrollRAF: number | null = null;\n\n // Get the scrollable container using its unique ID\n const getScrollableContainer = (): HTMLElement => {\n // Use the unique ID for reliable selection\n const scrollable = wrapper.querySelector('#vanilla-agent-scroll-container') as HTMLElement;\n // Fallback to body if ID not found (shouldn't happen, but safe fallback)\n return scrollable || body;\n };\n\n // Custom smooth scroll animation with easing\n const smoothScrollToBottom = (element: HTMLElement, duration = 500) => {\n const start = element.scrollTop;\n const clientHeight = element.clientHeight;\n // Recalculate target dynamically to handle layout changes\n let target = element.scrollHeight;\n let distance = target - start;\n\n // Check if already at bottom: scrollTop + clientHeight should be >= scrollHeight\n // Add a small threshold (2px) to account for rounding/subpixel differences\n const isAtBottom = start + clientHeight >= target - 2;\n \n // If already at bottom or very close, skip animation to prevent glitch\n if (isAtBottom || Math.abs(distance) < 5) {\n return;\n }\n\n // Cancel any ongoing smooth scroll animation\n if (smoothScrollRAF !== null) {\n cancelAnimationFrame(smoothScrollRAF);\n smoothScrollRAF = null;\n }\n\n const startTime = performance.now();\n\n // Easing function: ease-out cubic for smooth deceleration\n const easeOutCubic = (t: number): number => {\n return 1 - Math.pow(1 - t, 3);\n };\n\n const animate = (currentTime: number) => {\n // Recalculate target each frame in case scrollHeight changed\n const currentTarget = element.scrollHeight;\n if (currentTarget !== target) {\n target = currentTarget;\n distance = target - start;\n }\n\n const elapsed = currentTime - startTime;\n const progress = Math.min(elapsed / duration, 1);\n const eased = easeOutCubic(progress);\n \n const currentScroll = start + distance * eased;\n element.scrollTop = currentScroll;\n\n if (progress < 1) {\n smoothScrollRAF = requestAnimationFrame(animate);\n } else {\n // Ensure we end exactly at the target\n element.scrollTop = element.scrollHeight;\n smoothScrollRAF = null;\n }\n };\n\n smoothScrollRAF = requestAnimationFrame(animate);\n };\n\n const trackMessages = (messages: AgentWidgetMessage[]) => {\n const nextState = new Map<\n string,\n { streaming?: boolean; role: AgentWidgetMessage[\"role\"] }\n >();\n\n messages.forEach((message) => {\n const previous = messageState.get(message.id);\n nextState.set(message.id, {\n streaming: message.streaming,\n role: message.role\n });\n\n if (!previous && message.role === \"assistant\") {\n eventBus.emit(\"assistant:message\", message);\n }\n\n if (\n message.role === \"assistant\" &&\n previous?.streaming &&\n message.streaming === false\n ) {\n eventBus.emit(\"assistant:complete\", message);\n }\n });\n\n messageState.clear();\n nextState.forEach((value, key) => {\n messageState.set(key, value);\n });\n };\n\n\n // Message rendering with plugin support\n const renderMessagesWithPlugins = (\n container: HTMLElement,\n messages: AgentWidgetMessage[],\n transform: MessageTransform\n ) => {\n container.innerHTML = \"\";\n const fragment = document.createDocumentFragment();\n\n messages.forEach((message) => {\n let bubble: HTMLElement | null = null;\n\n // Try plugins first\n const matchingPlugin = plugins.find((p) => {\n if (message.variant === \"reasoning\" && p.renderReasoning) {\n return true;\n }\n if (message.variant === \"tool\" && p.renderToolCall) {\n return true;\n }\n if (!message.variant && p.renderMessage) {\n return true;\n }\n return false;\n });\n\n if (matchingPlugin) {\n if (message.variant === \"reasoning\" && message.reasoning && matchingPlugin.renderReasoning) {\n if (!showReasoning) return;\n bubble = matchingPlugin.renderReasoning({\n message,\n defaultRenderer: () => createReasoningBubble(message),\n config\n });\n } else if (message.variant === \"tool\" && message.toolCall && matchingPlugin.renderToolCall) {\n if (!showToolCalls) return;\n bubble = matchingPlugin.renderToolCall({\n message,\n defaultRenderer: () => createToolBubble(message, config),\n config\n });\n } else if (matchingPlugin.renderMessage) {\n bubble = matchingPlugin.renderMessage({\n message,\n defaultRenderer: () => {\n const b = createStandardBubble(message, transform);\n if (message.role !== \"user\") {\n enhanceWithForms(b, message, config, session);\n }\n return b;\n },\n config\n });\n }\n }\n\n // Fallback to default rendering if plugin returned null or no plugin matched\n if (!bubble) {\n if (message.variant === \"reasoning\" && message.reasoning) {\n if (!showReasoning) return;\n bubble = createReasoningBubble(message);\n } else if (message.variant === \"tool\" && message.toolCall) {\n if (!showToolCalls) return;\n bubble = createToolBubble(message, config);\n } else {\n bubble = createStandardBubble(message, transform);\n if (message.role !== \"user\") {\n enhanceWithForms(bubble, message, config, session);\n }\n }\n }\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"tvw-flex\";\n if (message.role === \"user\") {\n wrapper.classList.add(\"tvw-justify-end\");\n }\n wrapper.appendChild(bubble);\n fragment.appendChild(wrapper);\n });\n\n // Add standalone typing indicator only if streaming but no assistant message is streaming yet\n // (This shows while waiting for the stream to start)\n // Check for ANY streaming assistant message, even if empty (to avoid duplicate bubbles)\n const hasStreamingAssistantMessage = messages.some(\n (msg) => msg.role === \"assistant\" && msg.streaming\n );\n\n if (isStreaming && messages.some((msg) => msg.role === \"user\") && !hasStreamingAssistantMessage) {\n const typingIndicator = createTypingIndicator();\n\n // Create a bubble wrapper for the typing indicator (similar to assistant messages)\n const typingBubble = document.createElement(\"div\");\n typingBubble.className = [\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-text-sm\",\n \"tvw-leading-relaxed\",\n \"tvw-shadow-sm\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-px-5\",\n \"tvw-py-3\"\n ].join(\" \");\n\n typingBubble.appendChild(typingIndicator);\n\n const typingWrapper = document.createElement(\"div\");\n typingWrapper.className = \"tvw-flex\";\n typingWrapper.appendChild(typingBubble);\n fragment.appendChild(typingWrapper);\n }\n\n container.appendChild(fragment);\n // Defer scroll to next frame for smoother animation and to prevent jolt\n // This allows the browser to update layout (e.g., typing indicator removal) before scrolling\n // Use double RAF to ensure layout has fully settled before starting scroll animation\n // Get the scrollable container using its unique ID (#vanilla-agent-scroll-container)\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n const scrollableContainer = getScrollableContainer();\n smoothScrollToBottom(scrollableContainer);\n });\n });\n };\n\n const updateOpenState = () => {\n if (!launcherEnabled) return;\n if (open) {\n wrapper.classList.remove(\"tvw-pointer-events-none\", \"tvw-opacity-0\");\n panel.classList.remove(\"tvw-scale-95\", \"tvw-opacity-0\");\n panel.classList.add(\"tvw-scale-100\", \"tvw-opacity-100\");\n // Hide launcher button when widget is open\n if (launcherButtonInstance) {\n launcherButtonInstance.element.style.display = \"none\";\n }\n } else {\n wrapper.classList.add(\"tvw-pointer-events-none\", \"tvw-opacity-0\");\n panel.classList.remove(\"tvw-scale-100\", \"tvw-opacity-100\");\n panel.classList.add(\"tvw-scale-95\", \"tvw-opacity-0\");\n // Show launcher button when widget is closed\n if (launcherButtonInstance) {\n launcherButtonInstance.element.style.display = \"\";\n }\n }\n };\n\n const setOpenState = (nextOpen: boolean, source: \"user\" | \"auto\" | \"api\" | \"system\" = \"user\") => {\n if (!launcherEnabled) return;\n if (open === nextOpen) return;\n \n const prevOpen = open;\n open = nextOpen;\n updateOpenState();\n \n if (open) {\n recalcPanelHeight();\n scheduleAutoScroll(true);\n }\n \n // Emit widget state events\n const stateEvent: AgentWidgetStateEvent = {\n open,\n source,\n timestamp: Date.now()\n };\n \n if (open && !prevOpen) {\n eventBus.emit(\"widget:opened\", stateEvent);\n } else if (!open && prevOpen) {\n eventBus.emit(\"widget:closed\", stateEvent);\n }\n \n // Emit general state snapshot\n eventBus.emit(\"widget:state\", {\n open,\n launcherEnabled,\n voiceActive: voiceState.active,\n streaming: session.isStreaming()\n });\n };\n\n const setComposerDisabled = (disabled: boolean) => {\n textarea.disabled = disabled;\n sendButton.disabled = disabled;\n if (micButton) {\n micButton.disabled = disabled;\n }\n suggestionsManager.buttons.forEach((btn) => {\n btn.disabled = disabled;\n });\n };\n\n const updateCopy = () => {\n introTitle.textContent = config.copy?.welcomeTitle ?? \"Hello 👋\";\n introSubtitle.textContent =\n config.copy?.welcomeSubtitle ??\n \"Ask anything about your account or products.\";\n textarea.placeholder = config.copy?.inputPlaceholder ?? \"How can I help...\";\n\n // Only update send button text if NOT using icon mode\n const useIcon = config.sendButton?.useIcon ?? false;\n if (!useIcon) {\n sendButton.textContent = config.copy?.sendButtonLabel ?? \"Send\";\n }\n\n // Update textarea font family and weight\n const fontFamily = config.theme?.inputFontFamily ?? \"sans-serif\";\n const fontWeight = config.theme?.inputFontWeight ?? \"400\";\n \n const getFontFamilyValue = (family: \"sans-serif\" | \"serif\" | \"mono\"): string => {\n switch (family) {\n case \"serif\":\n return 'Georgia, \"Times New Roman\", Times, serif';\n case \"mono\":\n return '\"Courier New\", Courier, \"Lucida Console\", Monaco, monospace';\n case \"sans-serif\":\n default:\n return '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif';\n }\n };\n \n textarea.style.fontFamily = getFontFamilyValue(fontFamily);\n textarea.style.fontWeight = fontWeight;\n };\n\n session = new AgentWidgetSession(config, {\n onMessagesChanged(messages) {\n renderMessagesWithPlugins(messagesWrapper, messages, postprocess);\n // Re-render suggestions to hide them after first user message\n // Pass messages directly to avoid calling session.getMessages() during construction\n if (session) {\n const hasUserMessage = messages.some((msg) => msg.role === \"user\");\n if (hasUserMessage) {\n // Hide suggestions if user message exists\n suggestionsManager.render([], session, textarea, messages);\n } else {\n // Show suggestions if no user message yet\n suggestionsManager.render(config.suggestionChips, session, textarea, messages, config.suggestionChipsConfig);\n }\n }\n scheduleAutoScroll(!isStreaming);\n trackMessages(messages);\n\n const lastUserMessage = [...messages]\n .reverse()\n .find((msg) => msg.role === \"user\");\n voiceState.lastUserMessageWasVoice = Boolean(lastUserMessage?.viaVoice);\n persistState(messages);\n },\n onStatusChanged(status) {\n const currentStatusConfig = config.statusIndicator ?? {};\n const getCurrentStatusText = (status: AgentWidgetSessionStatus): string => {\n if (status === \"idle\") return currentStatusConfig.idleText ?? statusCopy.idle;\n if (status === \"connecting\") return currentStatusConfig.connectingText ?? statusCopy.connecting;\n if (status === \"connected\") return currentStatusConfig.connectedText ?? statusCopy.connected;\n if (status === \"error\") return currentStatusConfig.errorText ?? statusCopy.error;\n return statusCopy[status];\n };\n statusText.textContent = getCurrentStatusText(status);\n },\n onStreamingChanged(streaming) {\n isStreaming = streaming;\n setComposerDisabled(streaming);\n // Re-render messages to show/hide typing indicator\n if (session) {\n renderMessagesWithPlugins(messagesWrapper, session.getMessages(), postprocess);\n }\n if (!streaming) {\n scheduleAutoScroll(true);\n }\n }\n });\n\n if (pendingStoredState) {\n pendingStoredState\n .then((state) => {\n if (!state) return;\n if (state.metadata) {\n persistentMetadata = ensureRecord(state.metadata);\n actionManager.syncFromMetadata();\n }\n if (state.messages?.length) {\n session.hydrateMessages(state.messages);\n }\n })\n .catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to hydrate stored state:\", error);\n }\n });\n }\n\n const handleSubmit = (event: Event) => {\n event.preventDefault();\n const value = textarea.value.trim();\n if (!value) return;\n textarea.value = \"\";\n session.sendMessage(value);\n };\n\n const handleInputEnter = (event: KeyboardEvent) => {\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n sendButton.click();\n }\n };\n\n // Voice recognition state and logic\n let speechRecognition: any = null;\n let isRecording = false;\n let pauseTimer: number | null = null;\n let originalMicStyles: {\n backgroundColor: string;\n color: string;\n borderColor: string;\n } | null = null;\n\n const getSpeechRecognitionClass = (): any => {\n if (typeof window === 'undefined') return null;\n return (window as any).webkitSpeechRecognition || (window as any).SpeechRecognition || null;\n };\n\n const startVoiceRecognition = (\n source: AgentWidgetVoiceStateEvent[\"source\"] = \"user\"\n ) => {\n if (isRecording || session.isStreaming()) return;\n\n const SpeechRecognitionClass = getSpeechRecognitionClass();\n if (!SpeechRecognitionClass) return;\n\n speechRecognition = new SpeechRecognitionClass();\n const voiceConfig = config.voiceRecognition ?? {};\n const pauseDuration = voiceConfig.pauseDuration ?? 2000;\n\n speechRecognition.continuous = true;\n speechRecognition.interimResults = true;\n speechRecognition.lang = 'en-US';\n\n // Store the initial text that was in the textarea\n const initialText = textarea.value;\n\n speechRecognition.onresult = (event: any) => {\n // Build the complete transcript from all results\n let fullTranscript = \"\";\n let interimTranscript = \"\";\n \n // Process all results from the beginning\n for (let i = 0; i < event.results.length; i++) {\n const result = event.results[i];\n const transcript = result[0].transcript;\n \n if (result.isFinal) {\n fullTranscript += transcript + \" \";\n } else {\n // Only take the last interim result\n interimTranscript = transcript;\n }\n }\n \n // Update textarea with initial text + full transcript + interim\n const newValue = initialText + fullTranscript + interimTranscript;\n textarea.value = newValue;\n\n // Reset pause timer on each result\n if (pauseTimer) {\n clearTimeout(pauseTimer);\n }\n\n // Set timer to auto-submit after pause when we have any speech\n if (fullTranscript || interimTranscript) {\n pauseTimer = window.setTimeout(() => {\n const finalValue = textarea.value.trim();\n if (finalValue && speechRecognition && isRecording) {\n stopVoiceRecognition();\n textarea.value = \"\";\n session.sendMessage(finalValue, { viaVoice: true });\n }\n }, pauseDuration);\n }\n };\n\n speechRecognition.onerror = (event: any) => {\n // Don't stop on \"no-speech\" error, just ignore it\n if (event.error !== 'no-speech') {\n stopVoiceRecognition();\n }\n };\n\n speechRecognition.onend = () => {\n // If recognition ended naturally (not manually stopped), submit if there's text\n if (isRecording) {\n const finalValue = textarea.value.trim();\n if (finalValue && finalValue !== initialText.trim()) {\n textarea.value = \"\";\n session.sendMessage(finalValue, { viaVoice: true });\n }\n stopVoiceRecognition();\n }\n };\n\n try {\n speechRecognition.start();\n isRecording = true;\n voiceState.active = true;\n if (source !== \"system\") {\n voiceState.manuallyDeactivated = false;\n }\n emitVoiceState(source);\n persistVoiceMetadata();\n if (micButton) {\n // Store original styles\n originalMicStyles = {\n backgroundColor: micButton.style.backgroundColor,\n color: micButton.style.color,\n borderColor: micButton.style.borderColor\n };\n \n // Apply recording state styles from config\n const voiceConfig = config.voiceRecognition ?? {};\n const recordingBackgroundColor = voiceConfig.recordingBackgroundColor ?? \"#ef4444\";\n const recordingIconColor = voiceConfig.recordingIconColor;\n const recordingBorderColor = voiceConfig.recordingBorderColor;\n \n micButton.classList.add(\"tvw-voice-recording\");\n micButton.style.backgroundColor = recordingBackgroundColor;\n \n if (recordingIconColor) {\n micButton.style.color = recordingIconColor;\n // Update SVG stroke color if present\n const svg = micButton.querySelector(\"svg\");\n if (svg) {\n svg.setAttribute(\"stroke\", recordingIconColor);\n }\n }\n \n if (recordingBorderColor) {\n micButton.style.borderColor = recordingBorderColor;\n }\n \n micButton.setAttribute(\"aria-label\", \"Stop voice recognition\");\n }\n } catch (error) {\n stopVoiceRecognition(\"system\");\n }\n };\n\n const stopVoiceRecognition = (\n source: AgentWidgetVoiceStateEvent[\"source\"] = \"user\"\n ) => {\n if (!isRecording) return;\n\n isRecording = false;\n if (pauseTimer) {\n clearTimeout(pauseTimer);\n pauseTimer = null;\n }\n\n if (speechRecognition) {\n try {\n speechRecognition.stop();\n } catch (error) {\n // Ignore errors when stopping\n }\n speechRecognition = null;\n }\n\n voiceState.active = false;\n emitVoiceState(source);\n persistVoiceMetadata();\n\n if (micButton) {\n micButton.classList.remove(\"tvw-voice-recording\");\n \n // Restore original styles\n if (originalMicStyles) {\n micButton.style.backgroundColor = originalMicStyles.backgroundColor;\n micButton.style.color = originalMicStyles.color;\n micButton.style.borderColor = originalMicStyles.borderColor;\n \n // Restore SVG stroke color if present\n const svg = micButton.querySelector(\"svg\");\n if (svg) {\n svg.setAttribute(\"stroke\", originalMicStyles.color || \"currentColor\");\n }\n \n originalMicStyles = null;\n }\n \n micButton.setAttribute(\"aria-label\", \"Start voice recognition\");\n }\n };\n\n // Function to create mic button dynamically\n const createMicButton = (voiceConfig: AgentWidgetConfig['voiceRecognition'], sendButtonConfig: AgentWidgetConfig['sendButton']): { micButton: HTMLButtonElement; micButtonWrapper: HTMLElement } | null => {\n const hasSpeechRecognition = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n \n if (!hasSpeechRecognition) return null;\n\n const micButtonWrapper = createElement(\"div\", \"tvw-send-button-wrapper\");\n const micButton = createElement(\n \"button\",\n \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n \n micButton.type = \"button\";\n micButton.setAttribute(\"aria-label\", \"Start voice recognition\");\n \n const micIconName = voiceConfig?.iconName ?? \"mic\";\n const buttonSize = sendButtonConfig?.size ?? \"40px\";\n const micIconSize = voiceConfig?.iconSize ?? buttonSize;\n const micIconSizeNum = parseFloat(micIconSize) || 24;\n \n // Use dedicated colors from voice recognition config, fallback to send button colors\n const backgroundColor = voiceConfig?.backgroundColor ?? sendButtonConfig?.backgroundColor;\n const iconColor = voiceConfig?.iconColor ?? sendButtonConfig?.textColor;\n \n micButton.style.width = micIconSize;\n micButton.style.height = micIconSize;\n micButton.style.minWidth = micIconSize;\n micButton.style.minHeight = micIconSize;\n micButton.style.fontSize = \"18px\";\n micButton.style.lineHeight = \"1\";\n \n // Use Lucide mic icon with configured color (stroke width 1.5 for minimalist outline style)\n const iconColorValue = iconColor || \"currentColor\";\n const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColorValue, 1.5);\n if (micIconSvg) {\n micButton.appendChild(micIconSvg);\n micButton.style.color = iconColorValue;\n } else {\n // Fallback to text if icon fails\n micButton.textContent = \"🎤\";\n micButton.style.color = iconColorValue;\n }\n \n // Apply background color\n if (backgroundColor) {\n micButton.style.backgroundColor = backgroundColor;\n } else {\n micButton.classList.add(\"tvw-bg-cw-primary\");\n }\n \n // Apply icon/text color\n if (iconColor) {\n micButton.style.color = iconColor;\n } else if (!iconColor && !sendButtonConfig?.textColor) {\n micButton.classList.add(\"tvw-text-white\");\n }\n \n // Apply border styling\n if (voiceConfig?.borderWidth) {\n micButton.style.borderWidth = voiceConfig.borderWidth;\n micButton.style.borderStyle = \"solid\";\n }\n if (voiceConfig?.borderColor) {\n micButton.style.borderColor = voiceConfig.borderColor;\n }\n \n // Apply padding styling\n if (voiceConfig?.paddingX) {\n micButton.style.paddingLeft = voiceConfig.paddingX;\n micButton.style.paddingRight = voiceConfig.paddingX;\n }\n if (voiceConfig?.paddingY) {\n micButton.style.paddingTop = voiceConfig.paddingY;\n micButton.style.paddingBottom = voiceConfig.paddingY;\n }\n \n micButtonWrapper.appendChild(micButton);\n \n // Add tooltip if enabled\n const tooltipText = voiceConfig?.tooltipText ?? \"Start voice recognition\";\n const showTooltip = voiceConfig?.showTooltip ?? false;\n if (showTooltip && tooltipText) {\n const tooltip = createElement(\"div\", \"tvw-send-button-tooltip\");\n tooltip.textContent = tooltipText;\n micButtonWrapper.appendChild(tooltip);\n }\n \n return { micButton, micButtonWrapper };\n };\n\n // Wire up mic button click handler\n const handleMicButtonClick = () => {\n if (isRecording) {\n // Stop recording and submit\n const finalValue = textarea.value.trim();\n voiceState.manuallyDeactivated = true;\n persistVoiceMetadata();\n stopVoiceRecognition(\"user\");\n if (finalValue) {\n textarea.value = \"\";\n session.sendMessage(finalValue);\n }\n } else {\n // Start recording\n voiceState.manuallyDeactivated = false;\n persistVoiceMetadata();\n startVoiceRecognition(\"user\");\n }\n };\n\n if (micButton) {\n micButton.addEventListener(\"click\", handleMicButtonClick);\n\n destroyCallbacks.push(() => {\n stopVoiceRecognition(\"system\");\n if (micButton) {\n micButton.removeEventListener(\"click\", handleMicButtonClick);\n }\n });\n }\n\n const autoResumeUnsub = eventBus.on(\"assistant:complete\", () => {\n if (!voiceAutoResumeMode) return;\n if (voiceState.active || voiceState.manuallyDeactivated) return;\n if (voiceAutoResumeMode === \"assistant\" && !voiceState.lastUserMessageWasVoice) {\n return;\n }\n setTimeout(() => {\n if (!voiceState.active && !voiceState.manuallyDeactivated) {\n startVoiceRecognition(\"auto\");\n }\n }, 600);\n });\n destroyCallbacks.push(autoResumeUnsub);\n\n const toggleOpen = () => {\n setOpenState(!open, \"user\");\n };\n\n let launcherButtonInstance = launcherEnabled\n ? createLauncherButton(config, toggleOpen)\n : null;\n\n if (launcherButtonInstance) {\n mount.appendChild(launcherButtonInstance.element);\n }\n updateOpenState();\n suggestionsManager.render(config.suggestionChips, session, textarea, undefined, config.suggestionChipsConfig);\n updateCopy();\n setComposerDisabled(session.isStreaming());\n scheduleAutoScroll(true);\n maybeRestoreVoiceFromMetadata();\n\n const recalcPanelHeight = () => {\n if (!launcherEnabled) {\n panel.style.height = \"\";\n panel.style.width = \"\";\n return;\n }\n const launcherWidth = config?.launcher?.width ?? config?.launcherWidth;\n const width = launcherWidth ?? \"min(400px, calc(100vw - 24px))\";\n panel.style.width = width;\n panel.style.maxWidth = width;\n const viewportHeight = window.innerHeight;\n const verticalMargin = 64; // leave space for launcher's offset\n const available = Math.max(200, viewportHeight - verticalMargin);\n const clamped = Math.min(640, available);\n panel.style.height = `${clamped}px`;\n };\n\n recalcPanelHeight();\n window.addEventListener(\"resize\", recalcPanelHeight);\n destroyCallbacks.push(() => window.removeEventListener(\"resize\", recalcPanelHeight));\n\n lastScrollTop = body.scrollTop;\n\n const handleScroll = () => {\n const scrollTop = body.scrollTop;\n const scrollHeight = body.scrollHeight;\n const clientHeight = body.clientHeight;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n const delta = Math.abs(scrollTop - lastScrollTop);\n lastScrollTop = scrollTop;\n\n if (isAutoScrolling) return;\n if (delta <= USER_SCROLL_THRESHOLD) return;\n\n if (!shouldAutoScroll && distanceFromBottom < BOTTOM_THRESHOLD) {\n isAutoScrollBlocked = false;\n shouldAutoScroll = true;\n return;\n }\n\n if (shouldAutoScroll && distanceFromBottom > BOTTOM_THRESHOLD) {\n isAutoScrollBlocked = true;\n blockUntilTime = Date.now() + AUTO_SCROLL_BLOCK_TIME;\n shouldAutoScroll = false;\n }\n };\n\n body.addEventListener(\"scroll\", handleScroll, { passive: true });\n destroyCallbacks.push(() => body.removeEventListener(\"scroll\", handleScroll));\n destroyCallbacks.push(() => {\n if (scrollRAF) cancelAnimationFrame(scrollRAF);\n });\n\n const refreshCloseButton = () => {\n if (!closeButton) return;\n if (closeHandler) {\n closeButton.removeEventListener(\"click\", closeHandler);\n closeHandler = null;\n }\n if (launcherEnabled) {\n closeButton.style.display = \"\";\n closeHandler = () => {\n open = false;\n updateOpenState();\n };\n closeButton.addEventListener(\"click\", closeHandler);\n } else {\n closeButton.style.display = \"none\";\n }\n };\n\n refreshCloseButton();\n\n // Setup clear chat button click handler\n const setupClearChatButton = () => {\n const { clearChatButton } = panelElements;\n if (!clearChatButton) return;\n\n clearChatButton.addEventListener(\"click\", () => {\n // Clear messages in session (this will trigger onMessagesChanged which re-renders)\n session.clearMessages();\n\n // Always clear the default localStorage key\n try {\n localStorage.removeItem(DEFAULT_CHAT_HISTORY_STORAGE_KEY);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared default localStorage key: ${DEFAULT_CHAT_HISTORY_STORAGE_KEY}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear default localStorage:\", error);\n }\n\n // Also clear custom localStorage key if configured\n if (config.clearChatHistoryStorageKey && config.clearChatHistoryStorageKey !== DEFAULT_CHAT_HISTORY_STORAGE_KEY) {\n try {\n localStorage.removeItem(config.clearChatHistoryStorageKey);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared custom localStorage key: ${config.clearChatHistoryStorageKey}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear custom localStorage:\", error);\n }\n }\n\n // Dispatch custom event for external handlers (e.g., localStorage clearing in examples)\n const clearEvent = new CustomEvent(\"vanilla-agent:clear-chat\", {\n detail: { timestamp: new Date().toISOString() }\n });\n window.dispatchEvent(clearEvent);\n\n if (storageAdapter?.clear) {\n try {\n const result = storageAdapter.clear();\n if (result instanceof Promise) {\n result.catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n });\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n }\n }\n persistentMetadata = {};\n actionManager.syncFromMetadata();\n });\n };\n\n setupClearChatButton();\n\n composerForm.addEventListener(\"submit\", handleSubmit);\n textarea.addEventListener(\"keydown\", handleInputEnter);\n\n destroyCallbacks.push(() => {\n composerForm.removeEventListener(\"submit\", handleSubmit);\n textarea.removeEventListener(\"keydown\", handleInputEnter);\n });\n\n destroyCallbacks.push(() => {\n session.cancel();\n });\n\n if (launcherButtonInstance) {\n destroyCallbacks.push(() => {\n launcherButtonInstance?.destroy();\n });\n }\n\n const controller: Controller = {\n update(nextConfig: AgentWidgetConfig) {\n const previousToolCallConfig = config.toolCall;\n config = { ...config, ...nextConfig };\n applyThemeVariables(mount, config);\n\n // Update plugins\n const newPlugins = pluginRegistry.getForInstance(config.plugins);\n plugins.length = 0;\n plugins.push(...newPlugins);\n\n launcherEnabled = config.launcher?.enabled ?? true;\n autoExpand = config.launcher?.autoExpand ?? false;\n showReasoning = config.features?.showReasoning ?? true;\n showToolCalls = config.features?.showToolCalls ?? true;\n\n if (config.launcher?.enabled === false && launcherButtonInstance) {\n launcherButtonInstance.destroy();\n launcherButtonInstance = null;\n }\n\n if (config.launcher?.enabled !== false && !launcherButtonInstance) {\n launcherButtonInstance = createLauncherButton(config, toggleOpen);\n mount.appendChild(launcherButtonInstance.element);\n }\n\n if (launcherButtonInstance) {\n launcherButtonInstance.update(config);\n }\n\n // Update panel header title and subtitle\n if (headerTitle && config.launcher?.title !== undefined) {\n headerTitle.textContent = config.launcher.title;\n }\n if (headerSubtitle && config.launcher?.subtitle !== undefined) {\n headerSubtitle.textContent = config.launcher.subtitle;\n }\n\n // Only update open state if launcher enabled state changed or autoExpand value changed\n const launcherEnabledChanged = launcherEnabled !== prevLauncherEnabled;\n const autoExpandChanged = autoExpand !== prevAutoExpand;\n\n if (launcherEnabledChanged) {\n // Launcher was enabled/disabled - update state accordingly\n if (!launcherEnabled) {\n // When launcher is disabled, always keep panel open\n open = true;\n updateOpenState();\n } else {\n // Launcher was just enabled - respect autoExpand setting\n setOpenState(autoExpand, \"auto\");\n }\n } else if (autoExpandChanged) {\n // autoExpand value changed - update state to match\n setOpenState(autoExpand, \"auto\");\n }\n // Otherwise, preserve current open state (user may have manually opened/closed)\n\n // Update previous values for next comparison\n prevAutoExpand = autoExpand;\n prevLauncherEnabled = launcherEnabled;\n recalcPanelHeight();\n refreshCloseButton();\n\n // Re-render messages if toolCall config changed (to apply new styles)\n const toolCallConfigChanged = JSON.stringify(nextConfig.toolCall) !== JSON.stringify(previousToolCallConfig);\n if (toolCallConfigChanged && session) {\n renderMessagesWithPlugins(messagesWrapper, session.getMessages(), postprocess);\n }\n\n // Update panel icon sizes\n const launcher = config.launcher ?? {};\n const headerIconHidden = launcher.headerIconHidden ?? false;\n const headerIconName = launcher.headerIconName;\n const headerIconSize = launcher.headerIconSize ?? \"48px\";\n \n if (iconHolder) {\n const header = container.querySelector(\".tvw-border-b-cw-divider\");\n const headerCopy = header?.querySelector(\".tvw-flex-col\");\n \n // Handle hide/show\n if (headerIconHidden) {\n // Hide iconHolder\n iconHolder.style.display = \"none\";\n // Ensure headerCopy is still in header\n if (header && headerCopy && !header.contains(headerCopy)) {\n header.insertBefore(headerCopy, header.firstChild);\n }\n } else {\n // Show iconHolder\n iconHolder.style.display = \"\";\n iconHolder.style.height = headerIconSize;\n iconHolder.style.width = headerIconSize;\n \n // Ensure iconHolder is before headerCopy in header\n if (header && headerCopy) {\n if (!header.contains(iconHolder)) {\n header.insertBefore(iconHolder, headerCopy);\n } else if (iconHolder.nextSibling !== headerCopy) {\n // Reorder if needed\n iconHolder.remove();\n header.insertBefore(iconHolder, headerCopy);\n }\n }\n \n // Update icon content based on priority: Lucide icon > iconUrl > agentIconText\n if (headerIconName) {\n // Use Lucide icon\n const iconSize = parseFloat(headerIconSize) || 24;\n const iconSvg = renderLucideIcon(headerIconName, iconSize * 0.6, \"#ffffff\", 2);\n if (iconSvg) {\n iconHolder.replaceChildren(iconSvg);\n } else {\n // Fallback to agentIconText if Lucide icon fails\n iconHolder.textContent = launcher.agentIconText ?? \"💬\";\n }\n } else if (launcher.iconUrl) {\n // Use image URL\n const img = iconHolder.querySelector(\"img\");\n if (img) {\n img.src = launcher.iconUrl;\n img.style.height = headerIconSize;\n img.style.width = headerIconSize;\n } else {\n // Create new img if it doesn't exist\n const newImg = document.createElement(\"img\");\n newImg.src = launcher.iconUrl;\n newImg.alt = \"\";\n newImg.className = \"tvw-rounded-xl tvw-object-cover\";\n newImg.style.height = headerIconSize;\n newImg.style.width = headerIconSize;\n iconHolder.replaceChildren(newImg);\n }\n } else {\n // Use text/emoji - clear any SVG or img first\n const existingSvg = iconHolder.querySelector(\"svg\");\n const existingImg = iconHolder.querySelector(\"img\");\n if (existingSvg || existingImg) {\n iconHolder.replaceChildren();\n }\n iconHolder.textContent = launcher.agentIconText ?? \"💬\";\n }\n \n // Update image size if present\n const img = iconHolder.querySelector(\"img\");\n if (img) {\n img.style.height = headerIconSize;\n img.style.width = headerIconSize;\n }\n }\n }\n if (closeButton) {\n const closeButtonSize = launcher.closeButtonSize ?? \"32px\";\n const closeButtonPlacement = launcher.closeButtonPlacement ?? \"inline\";\n closeButton.style.height = closeButtonSize;\n closeButton.style.width = closeButtonSize;\n \n // Update placement if changed\n const isTopRight = closeButtonPlacement === \"top-right\";\n const hasTopRightClasses = closeButton.classList.contains(\"tvw-absolute\");\n \n if (isTopRight !== hasTopRightClasses) {\n // Placement changed - need to move button and update classes\n closeButton.remove();\n \n // Update classes\n if (isTopRight) {\n closeButton.className = \"tvw-absolute tvw-top-4 tvw-right-4 tvw-z-50 tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\";\n container.style.position = \"relative\";\n container.appendChild(closeButton);\n } else {\n closeButton.className = \"tvw-ml-auto tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\";\n // Find header element (first child of container)\n const header = container.querySelector(\".tvw-border-b-cw-divider\");\n if (header) {\n header.appendChild(closeButton);\n }\n }\n }\n \n // Apply close button styling from config\n if (launcher.closeButtonColor) {\n closeButton.style.color = launcher.closeButtonColor;\n closeButton.classList.remove(\"tvw-text-cw-muted\");\n } else {\n closeButton.style.color = \"\";\n closeButton.classList.add(\"tvw-text-cw-muted\");\n }\n \n if (launcher.closeButtonBackgroundColor) {\n closeButton.style.backgroundColor = launcher.closeButtonBackgroundColor;\n closeButton.classList.remove(\"hover:tvw-bg-gray-100\");\n } else {\n closeButton.style.backgroundColor = \"\";\n closeButton.classList.add(\"hover:tvw-bg-gray-100\");\n }\n \n // Apply border if width and/or color are provided\n if (launcher.closeButtonBorderWidth || launcher.closeButtonBorderColor) {\n const borderWidth = launcher.closeButtonBorderWidth || \"0px\";\n const borderColor = launcher.closeButtonBorderColor || \"transparent\";\n closeButton.style.border = `${borderWidth} solid ${borderColor}`;\n closeButton.classList.remove(\"tvw-border-none\");\n } else {\n closeButton.style.border = \"\";\n closeButton.classList.add(\"tvw-border-none\");\n }\n \n if (launcher.closeButtonBorderRadius) {\n closeButton.style.borderRadius = launcher.closeButtonBorderRadius;\n closeButton.classList.remove(\"tvw-rounded-full\");\n } else {\n closeButton.style.borderRadius = \"\";\n closeButton.classList.add(\"tvw-rounded-full\");\n }\n\n // Update padding\n if (launcher.closeButtonPaddingX) {\n closeButton.style.paddingLeft = launcher.closeButtonPaddingX;\n closeButton.style.paddingRight = launcher.closeButtonPaddingX;\n } else {\n closeButton.style.paddingLeft = \"\";\n closeButton.style.paddingRight = \"\";\n }\n if (launcher.closeButtonPaddingY) {\n closeButton.style.paddingTop = launcher.closeButtonPaddingY;\n closeButton.style.paddingBottom = launcher.closeButtonPaddingY;\n } else {\n closeButton.style.paddingTop = \"\";\n closeButton.style.paddingBottom = \"\";\n }\n\n // Update icon\n const closeButtonIconName = launcher.closeButtonIconName ?? \"x\";\n const closeButtonIconText = launcher.closeButtonIconText ?? \"×\";\n\n // Clear existing content and render new icon\n closeButton.innerHTML = \"\";\n const iconSvg = renderLucideIcon(closeButtonIconName, \"20px\", launcher.closeButtonColor || \"\", 2);\n if (iconSvg) {\n closeButton.appendChild(iconSvg);\n } else {\n closeButton.textContent = closeButtonIconText;\n }\n\n // Update tooltip\n const { closeButtonWrapper } = panelElements;\n const closeButtonTooltipText = launcher.closeButtonTooltipText ?? \"Close chat\";\n const closeButtonShowTooltip = launcher.closeButtonShowTooltip ?? true;\n\n closeButton.setAttribute(\"aria-label\", closeButtonTooltipText);\n\n if (closeButtonWrapper) {\n // Clean up old tooltip event listeners if they exist\n if ((closeButtonWrapper as any)._cleanupTooltip) {\n (closeButtonWrapper as any)._cleanupTooltip();\n delete (closeButtonWrapper as any)._cleanupTooltip;\n }\n\n // Set up new portaled tooltip with event listeners\n if (closeButtonShowTooltip && closeButtonTooltipText) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip || !closeButton) return; // Already showing or button doesn't exist\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = closeButtonTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = closeButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n closeButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n closeButton.addEventListener(\"focus\", showTooltip);\n closeButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the wrapper for later use\n (closeButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n if (closeButtonWrapper) {\n closeButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n }\n if (closeButton) {\n closeButton.removeEventListener(\"focus\", showTooltip);\n closeButton.removeEventListener(\"blur\", hideTooltip);\n }\n };\n }\n }\n }\n\n // Update clear chat button styling from config\n const { clearChatButton, clearChatButtonWrapper } = panelElements;\n if (clearChatButton) {\n const clearChatConfig = launcher.clearChat ?? {};\n const clearChatEnabled = clearChatConfig.enabled ?? true;\n\n // Show/hide button based on enabled state\n if (clearChatButtonWrapper) {\n clearChatButtonWrapper.style.display = clearChatEnabled ? \"\" : \"none\";\n }\n\n if (clearChatEnabled) {\n // Update size\n const clearChatSize = clearChatConfig.size ?? \"32px\";\n clearChatButton.style.height = clearChatSize;\n clearChatButton.style.width = clearChatSize;\n\n // Update icon\n const clearChatIconName = clearChatConfig.iconName ?? \"refresh-cw\";\n const clearChatIconColor = clearChatConfig.iconColor ?? \"\";\n\n // Clear existing icon and render new one\n clearChatButton.innerHTML = \"\";\n const iconSvg = renderLucideIcon(clearChatIconName, \"20px\", clearChatIconColor || \"\", 2);\n if (iconSvg) {\n clearChatButton.appendChild(iconSvg);\n }\n\n // Update icon color\n if (clearChatIconColor) {\n clearChatButton.style.color = clearChatIconColor;\n clearChatButton.classList.remove(\"tvw-text-cw-muted\");\n } else {\n clearChatButton.style.color = \"\";\n clearChatButton.classList.add(\"tvw-text-cw-muted\");\n }\n\n // Update background color\n if (clearChatConfig.backgroundColor) {\n clearChatButton.style.backgroundColor = clearChatConfig.backgroundColor;\n clearChatButton.classList.remove(\"hover:tvw-bg-gray-100\");\n } else {\n clearChatButton.style.backgroundColor = \"\";\n clearChatButton.classList.add(\"hover:tvw-bg-gray-100\");\n }\n\n // Update border\n if (clearChatConfig.borderWidth || clearChatConfig.borderColor) {\n const borderWidth = clearChatConfig.borderWidth || \"0px\";\n const borderColor = clearChatConfig.borderColor || \"transparent\";\n clearChatButton.style.border = `${borderWidth} solid ${borderColor}`;\n clearChatButton.classList.remove(\"tvw-border-none\");\n } else {\n clearChatButton.style.border = \"\";\n clearChatButton.classList.add(\"tvw-border-none\");\n }\n\n // Update border radius\n if (clearChatConfig.borderRadius) {\n clearChatButton.style.borderRadius = clearChatConfig.borderRadius;\n clearChatButton.classList.remove(\"tvw-rounded-full\");\n } else {\n clearChatButton.style.borderRadius = \"\";\n clearChatButton.classList.add(\"tvw-rounded-full\");\n }\n\n // Update padding\n if (clearChatConfig.paddingX) {\n clearChatButton.style.paddingLeft = clearChatConfig.paddingX;\n clearChatButton.style.paddingRight = clearChatConfig.paddingX;\n } else {\n clearChatButton.style.paddingLeft = \"\";\n clearChatButton.style.paddingRight = \"\";\n }\n if (clearChatConfig.paddingY) {\n clearChatButton.style.paddingTop = clearChatConfig.paddingY;\n clearChatButton.style.paddingBottom = clearChatConfig.paddingY;\n } else {\n clearChatButton.style.paddingTop = \"\";\n clearChatButton.style.paddingBottom = \"\";\n }\n\n const clearChatTooltipText = clearChatConfig.tooltipText ?? \"Clear chat\";\n const clearChatShowTooltip = clearChatConfig.showTooltip ?? true;\n\n clearChatButton.setAttribute(\"aria-label\", clearChatTooltipText);\n\n if (clearChatButtonWrapper) {\n // Clean up old tooltip event listeners if they exist\n if ((clearChatButtonWrapper as any)._cleanupTooltip) {\n (clearChatButtonWrapper as any)._cleanupTooltip();\n delete (clearChatButtonWrapper as any)._cleanupTooltip;\n }\n\n // Set up new portaled tooltip with event listeners\n if (clearChatShowTooltip && clearChatTooltipText) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip || !clearChatButton) return; // Already showing or button doesn't exist\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = clearChatTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = clearChatButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n clearChatButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n clearChatButton.addEventListener(\"focus\", showTooltip);\n clearChatButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the button for later use\n (clearChatButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n if (clearChatButtonWrapper) {\n clearChatButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n }\n if (clearChatButton) {\n clearChatButton.removeEventListener(\"focus\", showTooltip);\n clearChatButton.removeEventListener(\"blur\", hideTooltip);\n }\n };\n }\n }\n }\n }\n\n const nextParsers =\n config.actionParsers && config.actionParsers.length\n ? config.actionParsers\n : [defaultJsonActionParser];\n const nextHandlers =\n config.actionHandlers && config.actionHandlers.length\n ? config.actionHandlers\n : [defaultActionHandlers.message, defaultActionHandlers.messageAndClick];\n\n actionManager = createActionManager({\n parsers: nextParsers,\n handlers: nextHandlers,\n getMetadata,\n updateMetadata,\n emit: eventBus.emit,\n documentRef: typeof document !== \"undefined\" ? document : null\n });\n\n postprocess = buildPostprocessor(config, actionManager);\n session.updateConfig(config);\n renderMessagesWithPlugins(\n messagesWrapper,\n session.getMessages(),\n postprocess\n );\n suggestionsManager.render(config.suggestionChips, session, textarea, undefined, config.suggestionChipsConfig);\n updateCopy();\n setComposerDisabled(session.isStreaming());\n \n // Update voice recognition mic button visibility\n const voiceRecognitionEnabled = config.voiceRecognition?.enabled === true;\n const hasSpeechRecognition = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n \n // Update composer form gap based on voice recognition\n const shouldUseSmallGap = voiceRecognitionEnabled && hasSpeechRecognition;\n composerForm.classList.remove(\"tvw-gap-1\", \"tvw-gap-3\");\n composerForm.classList.add(shouldUseSmallGap ? \"tvw-gap-1\" : \"tvw-gap-3\");\n \n if (voiceRecognitionEnabled && hasSpeechRecognition) {\n // Create or update mic button\n if (!micButton || !micButtonWrapper) {\n // Create new mic button\n const micButtonResult = createMicButton(config.voiceRecognition, config.sendButton);\n if (micButtonResult) {\n // Update the mutable references\n micButton = micButtonResult.micButton;\n micButtonWrapper = micButtonResult.micButtonWrapper;\n \n // Insert before send button wrapper\n composerForm.insertBefore(micButtonWrapper, sendButtonWrapper);\n \n // Wire up click handler\n micButton.addEventListener(\"click\", handleMicButtonClick);\n \n // Set disabled state\n micButton.disabled = session.isStreaming();\n }\n } else {\n // Update existing mic button with new config\n const voiceConfig = config.voiceRecognition ?? {};\n const sendButtonConfig = config.sendButton ?? {};\n \n // Update icon name and size\n const micIconName = voiceConfig.iconName ?? \"mic\";\n const buttonSize = sendButtonConfig.size ?? \"40px\";\n const micIconSize = voiceConfig.iconSize ?? buttonSize;\n const micIconSizeNum = parseFloat(micIconSize) || 24;\n \n micButton.style.width = micIconSize;\n micButton.style.height = micIconSize;\n micButton.style.minWidth = micIconSize;\n micButton.style.minHeight = micIconSize;\n \n // Update icon\n const iconColor = voiceConfig.iconColor ?? sendButtonConfig.textColor ?? \"currentColor\";\n micButton.innerHTML = \"\";\n const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColor, 2);\n if (micIconSvg) {\n micButton.appendChild(micIconSvg);\n } else {\n micButton.textContent = \"🎤\";\n }\n \n // Update colors\n const backgroundColor = voiceConfig.backgroundColor ?? sendButtonConfig.backgroundColor;\n if (backgroundColor) {\n micButton.style.backgroundColor = backgroundColor;\n micButton.classList.remove(\"tvw-bg-cw-primary\");\n } else {\n micButton.style.backgroundColor = \"\";\n micButton.classList.add(\"tvw-bg-cw-primary\");\n }\n \n if (iconColor) {\n micButton.style.color = iconColor;\n micButton.classList.remove(\"tvw-text-white\");\n } else if (!iconColor && !sendButtonConfig.textColor) {\n micButton.style.color = \"\";\n micButton.classList.add(\"tvw-text-white\");\n }\n \n // Update border styling\n if (voiceConfig.borderWidth) {\n micButton.style.borderWidth = voiceConfig.borderWidth;\n micButton.style.borderStyle = \"solid\";\n } else {\n micButton.style.borderWidth = \"\";\n micButton.style.borderStyle = \"\";\n }\n if (voiceConfig.borderColor) {\n micButton.style.borderColor = voiceConfig.borderColor;\n } else {\n micButton.style.borderColor = \"\";\n }\n \n // Update padding styling\n if (voiceConfig.paddingX) {\n micButton.style.paddingLeft = voiceConfig.paddingX;\n micButton.style.paddingRight = voiceConfig.paddingX;\n } else {\n micButton.style.paddingLeft = \"\";\n micButton.style.paddingRight = \"\";\n }\n if (voiceConfig.paddingY) {\n micButton.style.paddingTop = voiceConfig.paddingY;\n micButton.style.paddingBottom = voiceConfig.paddingY;\n } else {\n micButton.style.paddingTop = \"\";\n micButton.style.paddingBottom = \"\";\n }\n \n // Update tooltip\n const tooltip = micButtonWrapper?.querySelector(\".tvw-send-button-tooltip\") as HTMLElement | null;\n const tooltipText = voiceConfig.tooltipText ?? \"Start voice recognition\";\n const showTooltip = voiceConfig.showTooltip ?? false;\n if (showTooltip && tooltipText) {\n if (!tooltip) {\n // Create tooltip if it doesn't exist\n const newTooltip = document.createElement(\"div\");\n newTooltip.className = \"tvw-send-button-tooltip\";\n newTooltip.textContent = tooltipText;\n micButtonWrapper?.insertBefore(newTooltip, micButton);\n } else {\n tooltip.textContent = tooltipText;\n tooltip.style.display = \"\";\n }\n } else if (tooltip) {\n // Hide tooltip if disabled\n tooltip.style.display = \"none\";\n }\n \n // Show and update disabled state\n micButtonWrapper.style.display = \"\";\n micButton.disabled = session.isStreaming();\n }\n } else {\n // Hide mic button\n if (micButton && micButtonWrapper) {\n micButtonWrapper.style.display = \"none\";\n // Stop any active recording if disabling\n if (isRecording) {\n stopVoiceRecognition();\n }\n }\n }\n \n // Update send button styling\n const sendButtonConfig = config.sendButton ?? {};\n const useIcon = sendButtonConfig.useIcon ?? false;\n const iconText = sendButtonConfig.iconText ?? \"↑\";\n const iconName = sendButtonConfig.iconName;\n const tooltipText = sendButtonConfig.tooltipText ?? \"Send message\";\n const showTooltip = sendButtonConfig.showTooltip ?? false;\n const buttonSize = sendButtonConfig.size ?? \"40px\";\n const backgroundColor = sendButtonConfig.backgroundColor;\n const textColor = sendButtonConfig.textColor;\n\n // Update button content and styling based on mode\n if (useIcon) {\n // Icon mode: circular button\n sendButton.style.width = buttonSize;\n sendButton.style.height = buttonSize;\n sendButton.style.minWidth = buttonSize;\n sendButton.style.minHeight = buttonSize;\n sendButton.style.fontSize = \"18px\";\n sendButton.style.lineHeight = \"1\";\n \n // Clear existing content\n sendButton.innerHTML = \"\";\n \n // Use Lucide icon if iconName is provided, otherwise fall back to iconText\n if (iconName) {\n const iconSize = parseFloat(buttonSize) || 24;\n const iconColor = textColor && typeof textColor === 'string' && textColor.trim() ? textColor.trim() : \"currentColor\";\n const iconSvg = renderLucideIcon(iconName, iconSize, iconColor, 2);\n if (iconSvg) {\n sendButton.appendChild(iconSvg);\n sendButton.style.color = iconColor;\n } else {\n // Fallback to text if icon fails to render\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n } else {\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n \n // Update classes\n sendButton.className = \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\";\n \n if (backgroundColor) {\n sendButton.style.backgroundColor = backgroundColor;\n sendButton.classList.remove(\"tvw-bg-cw-primary\");\n } else {\n sendButton.classList.add(\"tvw-bg-cw-primary\");\n }\n } else {\n // Text mode: existing behavior\n sendButton.textContent = config.copy?.sendButtonLabel ?? \"Send\";\n sendButton.style.width = \"\";\n sendButton.style.height = \"\";\n sendButton.style.minWidth = \"\";\n sendButton.style.minHeight = \"\";\n sendButton.style.fontSize = \"\";\n sendButton.style.lineHeight = \"\";\n \n // Update classes\n sendButton.className = \"tvw-rounded-button tvw-bg-cw-accent tvw-px-4 tvw-py-2 tvw-text-sm tvw-font-semibold tvw-text-white disabled:tvw-opacity-50 tvw-cursor-pointer\";\n \n if (backgroundColor) {\n sendButton.style.backgroundColor = backgroundColor;\n sendButton.classList.remove(\"tvw-bg-cw-accent\");\n } else {\n sendButton.classList.add(\"tvw-bg-cw-accent\");\n }\n \n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n\n // Apply border styling\n if (sendButtonConfig.borderWidth) {\n sendButton.style.borderWidth = sendButtonConfig.borderWidth;\n sendButton.style.borderStyle = \"solid\";\n } else {\n sendButton.style.borderWidth = \"\";\n sendButton.style.borderStyle = \"\";\n }\n if (sendButtonConfig.borderColor) {\n sendButton.style.borderColor = sendButtonConfig.borderColor;\n } else {\n sendButton.style.borderColor = \"\";\n }\n\n // Apply padding styling (works in both icon and text mode)\n if (sendButtonConfig.paddingX) {\n sendButton.style.paddingLeft = sendButtonConfig.paddingX;\n sendButton.style.paddingRight = sendButtonConfig.paddingX;\n } else {\n sendButton.style.paddingLeft = \"\";\n sendButton.style.paddingRight = \"\";\n }\n if (sendButtonConfig.paddingY) {\n sendButton.style.paddingTop = sendButtonConfig.paddingY;\n sendButton.style.paddingBottom = sendButtonConfig.paddingY;\n } else {\n sendButton.style.paddingTop = \"\";\n sendButton.style.paddingBottom = \"\";\n }\n\n // Update tooltip\n const tooltip = sendButtonWrapper?.querySelector(\".tvw-send-button-tooltip\") as HTMLElement | null;\n if (showTooltip && tooltipText) {\n if (!tooltip) {\n // Create tooltip if it doesn't exist\n const newTooltip = document.createElement(\"div\");\n newTooltip.className = \"tvw-send-button-tooltip\";\n newTooltip.textContent = tooltipText;\n sendButtonWrapper?.insertBefore(newTooltip, sendButton);\n } else {\n tooltip.textContent = tooltipText;\n tooltip.style.display = \"\";\n }\n } else if (tooltip) {\n tooltip.style.display = \"none\";\n }\n \n // Update status indicator visibility and text\n const statusIndicatorConfig = config.statusIndicator ?? {};\n const isVisible = statusIndicatorConfig.visible ?? true;\n statusText.style.display = isVisible ? \"\" : \"none\";\n \n // Update status text if status is currently set\n if (session) {\n const currentStatus = session.getStatus();\n const getCurrentStatusText = (status: AgentWidgetSessionStatus): string => {\n if (status === \"idle\") return statusIndicatorConfig.idleText ?? statusCopy.idle;\n if (status === \"connecting\") return statusIndicatorConfig.connectingText ?? statusCopy.connecting;\n if (status === \"connected\") return statusIndicatorConfig.connectedText ?? statusCopy.connected;\n if (status === \"error\") return statusIndicatorConfig.errorText ?? statusCopy.error;\n return statusCopy[status];\n };\n statusText.textContent = getCurrentStatusText(currentStatus);\n }\n },\n open() {\n if (!launcherEnabled) return;\n setOpenState(true, \"api\");\n },\n close() {\n if (!launcherEnabled) return;\n setOpenState(false, \"api\");\n },\n toggle() {\n if (!launcherEnabled) return;\n setOpenState(!open, \"api\");\n },\n clearChat() {\n // Clear messages in session (this will trigger onMessagesChanged which re-renders)\n session.clearMessages();\n\n // Always clear the default localStorage key\n try {\n localStorage.removeItem(DEFAULT_CHAT_HISTORY_STORAGE_KEY);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared default localStorage key: ${DEFAULT_CHAT_HISTORY_STORAGE_KEY}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear default localStorage:\", error);\n }\n\n // Also clear custom localStorage key if configured\n if (config.clearChatHistoryStorageKey && config.clearChatHistoryStorageKey !== DEFAULT_CHAT_HISTORY_STORAGE_KEY) {\n try {\n localStorage.removeItem(config.clearChatHistoryStorageKey);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared custom localStorage key: ${config.clearChatHistoryStorageKey}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear custom localStorage:\", error);\n }\n }\n\n // Dispatch custom event for external handlers (e.g., localStorage clearing in examples)\n const clearEvent = new CustomEvent(\"vanilla-agent:clear-chat\", {\n detail: { timestamp: new Date().toISOString() }\n });\n window.dispatchEvent(clearEvent);\n\n if (storageAdapter?.clear) {\n try {\n const result = storageAdapter.clear();\n if (result instanceof Promise) {\n result.catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n });\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n }\n }\n persistentMetadata = {};\n actionManager.syncFromMetadata();\n },\n setMessage(message: string): boolean {\n if (!textarea) return false;\n if (session.isStreaming()) return false;\n \n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n \n textarea.value = message;\n // Trigger input event for any listeners\n textarea.dispatchEvent(new Event('input', { bubbles: true }));\n return true;\n },\n submitMessage(message?: string): boolean {\n if (session.isStreaming()) return false;\n \n const valueToSubmit = message?.trim() || textarea.value.trim();\n if (!valueToSubmit) return false;\n \n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n \n textarea.value = \"\";\n session.sendMessage(valueToSubmit);\n return true;\n },\n startVoiceRecognition(): boolean {\n if (isRecording || session.isStreaming()) return false;\n \n const SpeechRecognitionClass = getSpeechRecognitionClass();\n if (!SpeechRecognitionClass) return false;\n \n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n \n voiceState.manuallyDeactivated = false;\n persistVoiceMetadata();\n startVoiceRecognition(\"user\");\n return true;\n },\n stopVoiceRecognition(): boolean {\n if (!isRecording) return false;\n \n voiceState.manuallyDeactivated = true;\n persistVoiceMetadata();\n stopVoiceRecognition(\"user\");\n return true;\n },\n injectTestMessage(event: AgentWidgetEvent) {\n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n session.injectTestEvent(event);\n },\n getMessages() {\n return session.getMessages();\n },\n getStatus() {\n return session.getStatus();\n },\n getPersistentMetadata() {\n return { ...persistentMetadata };\n },\n updatePersistentMetadata(\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) {\n updateMetadata(updater);\n },\n on(event, handler) {\n return eventBus.on(event, handler);\n },\n off(event, handler) {\n eventBus.off(event, handler);\n },\n // State query methods\n isOpen(): boolean {\n return launcherEnabled && open;\n },\n isVoiceActive(): boolean {\n return voiceState.active;\n },\n getState(): AgentWidgetStateSnapshot {\n return {\n open: launcherEnabled && open,\n launcherEnabled,\n voiceActive: voiceState.active,\n streaming: session.isStreaming()\n };\n },\n destroy() {\n destroyCallbacks.forEach((cb) => cb());\n wrapper.remove();\n launcherButtonInstance?.destroy();\n if (closeHandler) {\n closeButton.removeEventListener(\"click\", closeHandler);\n }\n }\n };\n\n const shouldExposeDebugApi =\n (runtimeOptions?.debugTools ?? false) || Boolean(config.debug);\n\n if (shouldExposeDebugApi && typeof window !== \"undefined\") {\n const previousDebug = (window as any).AgentWidgetBrowser;\n const debugApi = {\n controller,\n getMessages: controller.getMessages,\n getStatus: controller.getStatus,\n getMetadata: controller.getPersistentMetadata,\n updateMetadata: controller.updatePersistentMetadata,\n clearHistory: () => controller.clearChat(),\n setVoiceActive: (active: boolean) =>\n active\n ? controller.startVoiceRecognition()\n : controller.stopVoiceRecognition()\n };\n (window as any).AgentWidgetBrowser = debugApi;\n destroyCallbacks.push(() => {\n if ((window as any).AgentWidgetBrowser === debugApi) {\n (window as any).AgentWidgetBrowser = previousDebug;\n }\n });\n }\n\n return controller;\n};\n\nexport type AgentWidgetController = Controller;\n","import { createAgentExperience, AgentWidgetController } from \"../ui\";\nimport { AgentWidgetConfig, AgentWidgetInitOptions, AgentWidgetEvent } from \"../types\";\n\nconst ensureTarget = (target: string | HTMLElement): HTMLElement => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n throw new Error(\"Chat widget can only be mounted in a browser environment\");\n }\n\n if (typeof target === \"string\") {\n const element = document.querySelector<HTMLElement>(target);\n if (!element) {\n throw new Error(`Chat widget target \"${target}\" was not found`);\n }\n return element;\n }\n\n return target;\n};\n\nconst widgetCssHref = (): string | null => {\n try {\n // This works in ESM builds but not in IIFE builds\n if (typeof import.meta !== \"undefined\" && import.meta.url) {\n return new URL(\"../widget.css\", import.meta.url).href;\n }\n } catch {\n // Fallback for IIFE builds where CSS should be loaded separately\n }\n return null;\n};\n\nconst mountStyles = (root: ShadowRoot | HTMLElement) => {\n const href = widgetCssHref();\n\n const adoptExistingStylesheet = () => {\n if (!(root instanceof ShadowRoot)) {\n return;\n }\n\n if (root.querySelector('link[data-vanilla-agent]')) {\n return;\n }\n\n const globalLink = document.head.querySelector<HTMLLinkElement>(\n 'link[data-vanilla-agent]'\n );\n if (!globalLink) {\n return;\n }\n\n const clonedLink = globalLink.cloneNode(true) as HTMLLinkElement;\n root.insertBefore(clonedLink, root.firstChild);\n };\n\n if (root instanceof ShadowRoot) {\n // For shadow DOM, we need to load CSS into the shadow root\n if (href) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.setAttribute(\"data-vanilla-agent\", \"true\");\n root.insertBefore(link, root.firstChild);\n } else {\n adoptExistingStylesheet();\n }\n // If href is null (IIFE build), CSS should already be loaded globally\n } else {\n // For non-shadow DOM, check if CSS is already loaded\n const existing = document.head.querySelector<HTMLLinkElement>(\n \"link[data-vanilla-agent]\"\n );\n if (!existing) {\n if (href) {\n // ESM build - load CSS dynamically\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.setAttribute(\"data-vanilla-agent\", \"true\");\n document.head.appendChild(link);\n }\n // IIFE build - CSS should be loaded via <link> tag before script\n // If not found, we'll assume it's loaded globally or warn in dev\n }\n }\n};\n\nexport type AgentWidgetInitHandle = AgentWidgetController & { host: HTMLElement };\n\nexport const initAgentWidget = (\n options: AgentWidgetInitOptions\n): AgentWidgetInitHandle => {\n const target = ensureTarget(options.target);\n const host = document.createElement(\"div\");\n host.className = \"vanilla-agent-host\";\n target.appendChild(host);\n\n const useShadow = options.useShadowDom !== false;\n let mount: HTMLElement;\n let root: ShadowRoot | HTMLElement;\n\n if (useShadow) {\n const shadowRoot = host.attachShadow({ mode: \"open\" });\n root = shadowRoot;\n mount = document.createElement(\"div\");\n mount.id = \"vanilla-agent-root\";\n shadowRoot.appendChild(mount);\n mountStyles(shadowRoot);\n } else {\n root = host;\n mount = document.createElement(\"div\");\n mount.id = \"vanilla-agent-root\";\n host.appendChild(mount);\n mountStyles(host);\n }\n\n let controller = createAgentExperience(mount, options.config, {\n debugTools: options.debugTools\n });\n options.onReady?.();\n\n const handle: AgentWidgetInitHandle = {\n ...controller,\n host,\n destroy() {\n controller.destroy();\n host.remove();\n if (options.windowKey && typeof window !== \"undefined\") {\n delete (window as any)[options.windowKey];\n }\n }\n };\n\n // Store on window if windowKey is provided\n if (options.windowKey && typeof window !== 'undefined') {\n (window as any)[options.windowKey] = handle;\n }\n\n return handle;\n};\n","import type {\n AgentWidgetMessage,\n AgentWidgetStorageAdapter,\n AgentWidgetStoredState\n} from \"../types\";\n\nconst safeJsonParse = (value: string | null) => {\n if (!value) return null;\n try {\n return JSON.parse(value);\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to parse stored state:\", error);\n }\n return null;\n }\n};\n\nconst sanitizeMessages = (messages: AgentWidgetMessage[]) =>\n messages.map((message) => ({\n ...message,\n streaming: false\n }));\n\nexport const createLocalStorageAdapter = (\n key = \"vanilla-agent-state\"\n): AgentWidgetStorageAdapter => {\n const getStorage = () => {\n if (typeof window === \"undefined\" || !window.localStorage) {\n return null;\n }\n return window.localStorage;\n };\n\n return {\n load: () => {\n const storage = getStorage();\n if (!storage) return null;\n return safeJsonParse(storage.getItem(key));\n },\n save: (state: AgentWidgetStoredState) => {\n const storage = getStorage();\n if (!storage) return;\n try {\n const payload: AgentWidgetStoredState = {\n ...state,\n messages: state.messages ? sanitizeMessages(state.messages) : undefined\n };\n storage.setItem(key, JSON.stringify(payload));\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to persist state:\", error);\n }\n }\n },\n clear: () => {\n const storage = getStorage();\n if (!storage) return;\n try {\n storage.removeItem(key);\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear stored state:\", error);\n }\n }\n }\n };\n};\n\n","import {\n initAgentWidget as initAgentWidgetFn,\n type AgentWidgetInitHandle\n} from \"./runtime/init\";\n\nexport type {\n AgentWidgetConfig,\n AgentWidgetTheme,\n AgentWidgetFeatureFlags,\n AgentWidgetInitOptions,\n AgentWidgetMessage,\n AgentWidgetLauncherConfig,\n AgentWidgetEvent,\n AgentWidgetStreamParser,\n AgentWidgetStreamParserResult\n} from \"./types\";\n\nexport { initAgentWidgetFn as initAgentWidget };\nexport {\n createAgentExperience,\n type AgentWidgetController\n} from \"./ui\";\nexport {\n AgentWidgetSession,\n type AgentWidgetSessionStatus\n} from \"./session\";\nexport { AgentWidgetClient } from \"./client\";\nexport { createLocalStorageAdapter } from \"./utils/storage\";\nexport {\n createActionManager,\n defaultActionHandlers,\n defaultJsonActionParser\n} from \"./utils/actions\";\nexport {\n markdownPostprocessor,\n escapeHtml,\n directivePostprocessor\n} from \"./postprocessors\";\nexport { \n createPlainTextParser,\n createJsonStreamParser,\n createFlexibleJsonStreamParser,\n createRegexJsonParser,\n createXmlParser\n} from \"./utils/formatting\";\nexport type { AgentWidgetInitHandle };\n\n// Plugin system exports\nexport type { AgentWidgetPlugin } from \"./plugins/types\";\nexport { pluginRegistry } from \"./plugins/registry\";\n\n// Default configuration exports\nexport { DEFAULT_WIDGET_CONFIG, mergeWithDefaults } from \"./defaults\";\n\nexport default initAgentWidgetFn;\n"],"mappings":"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","names":["marked","markdownPostprocessor","text","escapeHtml","escapeAttribute","value","makeToken","idx","directiveReplacer","source","placeholders","working","match","jsonText","parsed","token","_","type","directivePostprocessor","withTokens","html","tokenRegex","replacement","parsePartialJson","STR","OBJ","formatUnknownValue","value","formatReasoningDuration","reasoning","_a","_b","end","start","seconds","describeReasonStatus","formatToolDuration","tool","_c","describeToolTitle","tool","formatToolDuration","createRegexJsonParserInternal","extractedText","processedLength","extractTextFromIncompleteJson","jsonString","textFieldRegex","match","incompleteTextFieldRegex","incompleteMatch","accumulatedContent","trimmed","extracted","extractTextFromJson","parsed","createPlainTextParser","parser","createRegexJsonParser","_a","regexParser","createJsonStreamParser","parsePartialJson","STR","OBJ","createFlexibleJsonStreamParser","textExtractor","extractText","newText","createXmlParser","DEFAULT_ENDPOINT","getParserFromType","parserType","createJsonStreamParser","createRegexJsonParser","createXmlParser","createPlainTextParser","AgentWidgetClient","config","_a","_b","_c","options","onEvent","controller","body","response","error","messages","payload","a","b","timeA","timeB","message","contextAggregate","provider","result","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","_V","_W","_X","_Y","_Z","__","_$","_aa","reader","decoder","buffer","baseSequence","sequenceCounter","nextSequence","cloneMessage","msg","reasoning","toolCall","tools","tool","emitMessage","assistantMessage","reasoningMessages","toolMessages","reasoningContext","toolContext","normalizeKey","value","getStepKey","getToolCallKey","ensureAssistantMessage","trackReasoningId","stepKey","id","resolveReasoningId","allowCreate","rawId","resolved","existing","generated","ensureReasoningMessage","reasoningId","trackToolId","callKey","resolveToolId","ensureToolMessage","toolId","resolveTimestamp","parsed","dateParsed","ensureStringContent","streamParsers","rawContentBuffers","done","events","event","lines","eventType","data","line","payloadType","reasoningMessage","chunk","start","toolMessage","chunkText","stepType","executionType","assistant","accumulatedRaw","parser","looksLikeJson","parsedResult","text","currentAssistant","finalContent","rawBuffer","contentToProcess","extractedText","extractTextFromJson","parserToClose","closeResult","hasExtractedText","currentExtractedText","finalExtractedText","stringContent","displayContent","currentText","AgentWidgetSession","config","callbacks","event","_a","_b","message","AgentWidgetClient","next","rawInput","options","_c","_d","_e","input","userMessage","controller","snapshot","error","fallback","messages","status","streaming","withSequence","index","m","existing","idx","a","b","timeA","timeB","seqA","seqB","applyThemeVariables","element","config","_a","theme","key","value","kebabKey","letter","icons","renderLucideIcon","iconName","size","color","strokeWidth","pascalName","word","iconData","createSvgFromIconData","error","svg","elementData","tagName","attrs","element","key","value","createElement","tag","className","element","statusCopy","positionMap","createLauncherButton","config","onToggle","button","createElement","update","newConfig","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","launcher","titleEl","subtitleEl","textContainer","icon","iconSize","iconSizeNum","iconSvg","renderLucideIcon","img","callToActionIconEl","callToActionIconSize","paddingTotal","containerSize","positionClass","positionMap","base","destroy","createWrapper","config","_a","_b","_c","_d","_e","wrapper","createElement","panel","launcher","position","positionMap","launcherWidth","width","buildPanel","showClose","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","_V","_W","_X","_Y","_Z","__","_$","_aa","_ba","_ca","_da","_ea","_fa","container","header","headerIconSize","closeButtonSize","closeButtonPlacement","headerIconHidden","headerIconName","iconHolder","iconSize","iconSvg","renderLucideIcon","img","headerCopy","title","subtitle","clearChatConfig","clearChatEnabled","clearChatButton","clearChatButtonWrapper","clearChatSize","clearChatIconName","clearChatIconColor","clearChatBgColor","clearChatBorderWidth","clearChatBorderColor","clearChatBorderRadius","clearChatPaddingX","clearChatPaddingY","clearChatTooltipText","clearChatShowTooltip","borderWidth","borderColor","portaledTooltip","showTooltip","arrow","buttonRect","hideTooltip","closeButtonWrapper","closeButton","closeButtonTooltipText","closeButtonShowTooltip","closeButtonIconName","closeButtonIconText","body","introCard","introTitle","introSubtitle","messagesWrapper","footer","suggestions","voiceRecognitionEnabledForGap","hasSpeechRecognitionForGap","composerForm","textarea","fontFamily","fontWeight","getFontFamilyValue","family","sendButtonConfig","useIcon","iconText","iconName","tooltipText","buttonSize","backgroundColor","textColor","sendButtonWrapper","sendButton","iconColor","tooltip","voiceRecognitionConfig","voiceRecognitionEnabled","micButton","micButtonWrapper","hasSpeechRecognition","micIconName","micIconSize","micIconSizeNum","micBackgroundColor","micIconColor","iconColorValue","micIconSvg","e","statusText","statusConfig","isVisible","createTypingIndicator","container","dot1","dot2","dot3","srOnly","createStandardBubble","message","transform","classes","bubble","createElement","contentDiv","typingIndicator","reasoningExpansionState","createReasoningBubble","message","reasoning","bubble","createElement","expanded","header","headerContent","title","status","describeReasonStatus","toggleIcon","chevronIcon","renderLucideIcon","headerMeta","content","text","body","applyExpansionState","toggleExpansion","event","toolExpansionState","createToolBubble","message","config","_a","tool","toolCallConfig","bubble","createElement","expanded","header","headerContent","title","describeToolTitle","toggleIcon","iconColor","chevronIcon","renderLucideIcon","headerMeta","content","toolName","argsBlock","argsLabel","argsPre","formatUnknownValue","logsBlock","logsLabel","logsPre","resultBlock","resultLabel","resultPre","duration","applyToolExpansion","toggleToolExpansion","event","createSuggestions","container","suggestionButtons","chips","session","textarea","messages","chipsConfig","msg","fragment","streaming","getFontFamilyValue","family","chip","btn","createElement","formDefinitions","enhanceWithForms","bubble","message","config","session","placeholders","placeholder","_a","_b","_c","type","definition","heading","createElement","title","desc","form","field","group","label","inputType","control","actions","status","submit","event","formEndpoint","formData","payload","value","key","response","data","error","PluginRegistry","plugin","_a","pluginId","a","b","_b","instancePlugins","allPlugins","instanceIds","p","pluginRegistry","DEFAULT_WIDGET_CONFIG","mergeWithDefaults","config","_a","_b","_c","createEventBus","listeners","on","event","handler","off","_a","payload","error","stripCodeFence","value","match","extractJsonObject","trimmed","start","depth","i","char","defaultJsonActionParser","text","withoutFence","jsonBody","parsed","action","payload","asString","defaultActionHandlers","context","_a","selector","element","ensureArrayOfStrings","entry","createActionManager","options","processedIds","syncFromMetadata","persistProcessedIds","latestIds","prev","parseSource","acc","parser","eventPayload","handler","handlerResult","persist","error","DEFAULT_CHAT_HISTORY_STORAGE_KEY","VOICE_STATE_RESTORE_WINDOW","ensureRecord","value","stripStreamingFromMessages","messages","message","buildPostprocessor","cfg","actionManager","context","_a","_b","_c","nextText","rawPayload","actionResult","escapeHtml","createAgentExperience","mount","initialConfig","runtimeOptions","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","config","mergeWithDefaults","applyThemeVariables","plugins","pluginRegistry","eventBus","createEventBus","storageAdapter","persistentMetadata","pendingStoredState","storedState","immediateState","error","getMetadata","updateMetadata","updater","persistState","resolvedActionParsers","defaultJsonActionParser","resolvedActionHandlers","defaultActionHandlers","createActionManager","launcherEnabled","autoExpand","prevAutoExpand","prevLauncherEnabled","open","postprocess","showReasoning","showToolCalls","statusConfig","getStatusText","status","statusCopy","wrapper","panel","createWrapper","panelElements","buildPanel","container","body","messagesWrapper","suggestions","textarea","sendButton","sendButtonWrapper","composerForm","statusText","introTitle","introSubtitle","closeButton","iconHolder","headerTitle","headerSubtitle","micButton","micButtonWrapper","destroyCallbacks","suggestionsManager","createSuggestions","closeHandler","session","isStreaming","shouldAutoScroll","lastScrollTop","lastAutoScrollTime","scrollRAF","isAutoScrollBlocked","blockUntilTime","isAutoScrolling","AUTO_SCROLL_THROTTLE","AUTO_SCROLL_BLOCK_TIME","USER_SCROLL_THRESHOLD","BOTTOM_THRESHOLD","messageState","voiceState","voiceAutoResumeMode","emitVoiceState","source","persistVoiceMetadata","prev","maybeRestoreVoiceFromMetadata","rawVoiceState","wasActive","timestamp","startVoiceRecognition","getMessagesForPersistence","msg","messagesOverride","payload","result","scheduleAutoScroll","force","now","smoothScrollRAF","getScrollableContainer","smoothScrollToBottom","element","duration","start","clientHeight","target","distance","startTime","easeOutCubic","t","animate","currentTime","currentTarget","elapsed","progress","eased","currentScroll","trackMessages","nextState","previous","key","renderMessagesWithPlugins","transform","fragment","bubble","matchingPlugin","createReasoningBubble","createToolBubble","b","createStandardBubble","enhanceWithForms","hasStreamingAssistantMessage","typingIndicator","createTypingIndicator","typingBubble","typingWrapper","scrollableContainer","updateOpenState","launcherButtonInstance","setOpenState","nextOpen","prevOpen","recalcPanelHeight","stateEvent","setComposerDisabled","disabled","btn","updateCopy","_n","fontFamily","fontWeight","getFontFamilyValue","family","AgentWidgetSession","lastUserMessage","currentStatusConfig","getCurrentStatusText","streaming","state","handleSubmit","event","handleInputEnter","speechRecognition","isRecording","pauseTimer","originalMicStyles","getSpeechRecognitionClass","SpeechRecognitionClass","pauseDuration","initialText","fullTranscript","interimTranscript","i","transcript","newValue","finalValue","stopVoiceRecognition","voiceConfig","recordingBackgroundColor","recordingIconColor","recordingBorderColor","svg","createMicButton","sendButtonConfig","createElement","micIconName","buttonSize","micIconSize","micIconSizeNum","backgroundColor","iconColor","iconColorValue","micIconSvg","renderLucideIcon","tooltipText","tooltip","handleMicButtonClick","autoResumeUnsub","toggleOpen","createLauncherButton","launcherWidth","width","viewportHeight","available","clamped","handleScroll","scrollTop","scrollHeight","distanceFromBottom","delta","refreshCloseButton","clearChatButton","clearEvent","controller","nextConfig","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","_V","_W","_X","_Y","previousToolCallConfig","newPlugins","launcher","headerIconHidden","headerIconName","headerIconSize","header","headerCopy","iconSize","iconSvg","img","newImg","existingSvg","existingImg","closeButtonSize","closeButtonPlacement","isTopRight","hasTopRightClasses","borderWidth","borderColor","closeButtonIconName","closeButtonIconText","closeButtonWrapper","closeButtonTooltipText","closeButtonShowTooltip","portaledTooltip","showTooltip","arrow","buttonRect","hideTooltip","clearChatButtonWrapper","clearChatConfig","clearChatEnabled","clearChatSize","clearChatIconName","clearChatIconColor","clearChatTooltipText","clearChatShowTooltip","nextParsers","nextHandlers","voiceRecognitionEnabled","hasSpeechRecognition","shouldUseSmallGap","micButtonResult","newTooltip","useIcon","iconText","iconName","textColor","statusIndicatorConfig","isVisible","currentStatus","valueToSubmit","handler","cb","previousDebug","debugApi","active","import_meta","ensureTarget","target","element","widgetCssHref","mountStyles","root","href","adoptExistingStylesheet","globalLink","clonedLink","link","initAgentWidget","options","_a","host","useShadow","mount","shadowRoot","controller","createAgentExperience","handle","safeJsonParse","value","error","sanitizeMessages","messages","message","createLocalStorageAdapter","key","getStorage","storage","state","payload","index_default","initAgentWidget"]}
|
|
1
|
+
{"version":3,"sources":["../src/postprocessors.ts","../src/utils/formatting.ts","../src/client.ts","../src/session.ts","../src/utils/theme.ts","../src/utils/icons.ts","../src/utils/dom.ts","../src/utils/constants.ts","../src/utils/positioning.ts","../src/components/launcher.ts","../src/components/panel.ts","../src/components/message-bubble.ts","../src/components/reasoning-bubble.ts","../src/components/tool-bubble.ts","../src/components/suggestions.ts","../src/components/forms.ts","../src/plugins/registry.ts","../src/defaults.ts","../src/utils/events.ts","../src/utils/actions.ts","../src/utils/storage.ts","../src/components/registry.ts","../src/utils/component-parser.ts","../src/utils/component-middleware.ts","../src/ui.ts","../src/runtime/init.ts","../src/index.ts"],"sourcesContent":["import { marked } from \"marked\";\n\nmarked.setOptions({ breaks: true });\n\n/**\n * Basic markdown renderer. Remember to sanitize the returned HTML if you render\n * untrusted content in your host page.\n */\nexport const markdownPostprocessor = (text: string): string => {\n return marked.parse(text) as string;\n};\n\n/**\n * Escapes HTML entities. Used as the default safe renderer.\n */\nexport const escapeHtml = (text: string): string =>\n text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n\nconst escapeAttribute = (value: string) =>\n value.replace(/\"/g, \""\").replace(/</g, \"<\").replace(/>/g, \">\");\n\nconst makeToken = (idx: number) => `%%FORM_PLACEHOLDER_${idx}%%`;\n\nconst directiveReplacer = (source: string, placeholders: Array<{ token: string; type: string }>) => {\n let working = source;\n\n // JSON directive pattern e.g. <Directive>{\"component\":\"form\",\"type\":\"init\"}</Directive>\n working = working.replace(/<Directive>([\\s\\S]*?)<\\/Directive>/gi, (match, jsonText) => {\n try {\n const parsed = JSON.parse(jsonText.trim());\n if (parsed && typeof parsed === \"object\" && parsed.component === \"form\" && parsed.type) {\n const token = makeToken(placeholders.length);\n placeholders.push({ token, type: String(parsed.type) });\n return token;\n }\n } catch (error) {\n return match;\n }\n return match;\n });\n\n // XML-style directive e.g. <Form type=\"init\" />\n working = working.replace(/<Form\\s+type=\"([^\"]+)\"\\s*\\/>/gi, (_, type) => {\n const token = makeToken(placeholders.length);\n placeholders.push({ token, type });\n return token;\n });\n\n return working;\n};\n\n/**\n * Converts special directives (either `<Form type=\"init\" />` or\n * `<Directive>{\"component\":\"form\",\"type\":\"init\"}</Directive>`) into placeholder\n * elements that the widget upgrades after render. Remaining text is rendered as\n * Markdown.\n */\nexport const directivePostprocessor = (text: string): string => {\n const placeholders: Array<{ token: string; type: string }> = [];\n const withTokens = directiveReplacer(text, placeholders);\n let html = markdownPostprocessor(withTokens);\n\n placeholders.forEach(({ token, type }) => {\n const tokenRegex = new RegExp(token.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"), \"g\");\n const safeType = escapeAttribute(type);\n const replacement = `<div class=\"tvw-form-directive\" data-tv-form=\"${safeType}\"></div>`;\n html = html.replace(tokenRegex, replacement);\n });\n\n return html;\n};\n","import { AgentWidgetReasoning, AgentWidgetToolCall, AgentWidgetStreamParser, AgentWidgetStreamParserResult } from \"../types\";\nimport { parse as parsePartialJson, STR, OBJ } from \"partial-json\";\n\nexport const formatUnknownValue = (value: unknown): string => {\n if (value === null) return \"null\";\n if (value === undefined) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n try {\n return JSON.stringify(value, null, 2);\n } catch (error) {\n return String(value);\n }\n};\n\nexport const formatReasoningDuration = (reasoning: AgentWidgetReasoning) => {\n const end = reasoning.completedAt ?? Date.now();\n const start = reasoning.startedAt ?? end;\n const durationMs =\n reasoning.durationMs !== undefined\n ? reasoning.durationMs\n : Math.max(0, end - start);\n const seconds = durationMs / 1000;\n if (seconds < 0.1) {\n return \"Thought for <0.1 seconds\";\n }\n const formatted =\n seconds >= 10\n ? Math.round(seconds).toString()\n : seconds.toFixed(1).replace(/\\.0$/, \"\");\n return `Thought for ${formatted} seconds`;\n};\n\nexport const describeReasonStatus = (reasoning: AgentWidgetReasoning) => {\n if (reasoning.status === \"complete\") return formatReasoningDuration(reasoning);\n if (reasoning.status === \"pending\") return \"Waiting\";\n return \"\";\n};\n\nexport const formatToolDuration = (tool: AgentWidgetToolCall) => {\n const durationMs =\n typeof tool.duration === \"number\"\n ? tool.duration\n : typeof tool.durationMs === \"number\"\n ? tool.durationMs\n : Math.max(\n 0,\n (tool.completedAt ?? Date.now()) -\n (tool.startedAt ?? tool.completedAt ?? Date.now())\n );\n const seconds = durationMs / 1000;\n if (seconds < 0.1) {\n return \"Used tool for <0.1 seconds\";\n }\n const formatted =\n seconds >= 10\n ? Math.round(seconds).toString()\n : seconds.toFixed(1).replace(/\\.0$/, \"\");\n return `Used tool for ${formatted} seconds`;\n};\n\nexport const describeToolStatus = (status: AgentWidgetToolCall[\"status\"]) => {\n if (status === \"complete\") return \"\";\n if (status === \"pending\") return \"Starting\";\n return \"Running\";\n};\n\nexport const describeToolTitle = (tool: AgentWidgetToolCall) => {\n if (tool.status === \"complete\") {\n return formatToolDuration(tool);\n }\n return \"Using tool...\";\n};\n\n/**\n * Creates a regex-based parser for extracting text from JSON streams.\n * This is a simpler alternative to schema-stream that uses regex to extract\n * the 'text' field incrementally as JSON streams in.\n * \n * This can be used as an alternative parser option.\n */\nconst createRegexJsonParserInternal = (): {\n processChunk(accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null>;\n getExtractedText(): string | null;\n close?(): Promise<void>;\n} => {\n let extractedText: string | null = null;\n let processedLength = 0;\n \n // Regex-based extraction for incremental JSON parsing\n const extractTextFromIncompleteJson = (jsonString: string): string | null => {\n // Look for \"text\": \"value\" pattern, handling incomplete strings\n // Match: \"text\": \" followed by any characters (including incomplete)\n const textFieldRegex = /\"text\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.|\")*?)\"/;\n const match = jsonString.match(textFieldRegex);\n \n if (match && match[1]) {\n // Unescape the string value\n try {\n // Replace escaped characters\n let unescaped = match[1]\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n return unescaped;\n } catch {\n return match[1];\n }\n }\n \n // Also try to match incomplete text field (text field that hasn't closed yet)\n // Look for \"text\": \" followed by content that may not be closed\n const incompleteTextFieldRegex = /\"text\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)/;\n const incompleteMatch = jsonString.match(incompleteTextFieldRegex);\n \n if (incompleteMatch && incompleteMatch[1]) {\n // Unescape the partial string value\n try {\n let unescaped = incompleteMatch[1]\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, '\\\\');\n return unescaped;\n } catch {\n return incompleteMatch[1];\n }\n }\n \n return null;\n };\n \n return {\n getExtractedText: () => extractedText,\n processChunk: async (accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null> => {\n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedText !== null\n ? { text: extractedText, raw: accumulatedContent }\n : null;\n }\n \n // Validate that the accumulated content looks like valid JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n \n // Try to extract text field using regex\n const extracted = extractTextFromIncompleteJson(accumulatedContent);\n if (extracted !== null) {\n extractedText = extracted;\n }\n \n // Update processed length\n processedLength = accumulatedContent.length;\n \n // Return both the extracted text and raw JSON\n if (extractedText !== null) {\n return {\n text: extractedText,\n raw: accumulatedContent\n };\n }\n\n return null;\n },\n close: async () => {\n // No cleanup needed for regex-based parser\n }\n };\n};\n\n/**\n * Extracts the text field from JSON (works with partial JSON during streaming).\n * For complete JSON, uses fast path. For incomplete JSON, returns null (use stateful parser in client.ts).\n * \n * @param jsonString - The JSON string (can be partial/incomplete during streaming)\n * @returns The extracted text value, or null if not found or invalid\n */\nexport const extractTextFromJson = (jsonString: string): string | null => {\n try {\n // Try to parse complete JSON first (fast path)\n const parsed = JSON.parse(jsonString);\n if (parsed && typeof parsed === \"object\" && typeof parsed.text === \"string\") {\n return parsed.text;\n }\n } catch {\n // For incomplete JSON, return null - use stateful parser in client.ts\n return null;\n }\n return null;\n};\n\n/**\n * Plain text parser - passes through text as-is without any parsing.\n * This is the default parser.\n */\nexport const createPlainTextParser = (): AgentWidgetStreamParser => {\n const parser: AgentWidgetStreamParser = {\n processChunk: (accumulatedContent: string): string | null => {\n // Always return null to indicate this isn't a structured format\n // Content will be displayed as plain text\n return null;\n },\n getExtractedText: (): string | null => {\n return null;\n }\n };\n // Mark this as a plain text parser\n (parser as any).__isPlainTextParser = true;\n return parser;\n};\n\n/**\n * JSON parser using regex-based extraction.\n * Extracts the 'text' field from JSON responses using regex patterns.\n * This is a simpler regex-based alternative to createJsonStreamParser.\n * Less robust for complex/malformed JSON but has no external dependencies.\n */\nexport const createRegexJsonParser = (): AgentWidgetStreamParser => {\n const regexParser = createRegexJsonParserInternal();\n \n return {\n processChunk: async (accumulatedContent: string): Promise<AgentWidgetStreamParserResult | string | null> => {\n // Only process if it looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n return regexParser.processChunk(accumulatedContent);\n },\n getExtractedText: regexParser.getExtractedText.bind(regexParser),\n close: regexParser.close?.bind(regexParser)\n };\n};\n\n/**\n * JSON stream parser using partial-json library.\n * Extracts the 'text' field from JSON responses using the partial-json library,\n * which is specifically designed for parsing incomplete JSON from LLMs.\n * This is the recommended parser as it's more robust than regex.\n * \n * Library: https://github.com/promplate/partial-json-parser-js\n */\nexport const createJsonStreamParser = (): AgentWidgetStreamParser => {\n let extractedText: string | null = null;\n let processedLength = 0;\n \n return {\n getExtractedText: () => extractedText,\n processChunk: (accumulatedContent: string): AgentWidgetStreamParserResult | string | null => {\n // Validate that the accumulated content looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n \n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedText !== null || extractedText === \"\"\n ? { text: extractedText || \"\", raw: accumulatedContent }\n : null;\n }\n \n try {\n // Parse partial JSON - allow partial strings and objects\n // STR | OBJ allows incomplete strings and objects during streaming\n const parsed = parsePartialJson(accumulatedContent, STR | OBJ);\n \n if (parsed && typeof parsed === \"object\") {\n // Check for component directives - extract text if present for combined text+component\n if (parsed.component && typeof parsed.component === \"string\") {\n // For component directives, extract text if present, otherwise empty\n extractedText = typeof parsed.text === \"string\" ? parsed.text : \"\";\n }\n // Check for form directives - these also don't have text fields\n else if (parsed.type === \"init\" && parsed.form) {\n // For form directives, return empty - they're handled by form postprocessor\n extractedText = \"\";\n }\n // Extract text field if available\n else if (typeof parsed.text === \"string\") {\n extractedText = parsed.text;\n }\n }\n } catch (error) {\n // If parsing fails completely, keep the last extracted text\n // This can happen with very malformed JSON\n }\n \n // Update processed length\n processedLength = accumulatedContent.length;\n \n // Always return raw JSON for component/form directive detection\n // Return empty string for text if it's a component/form directive\n if (extractedText !== null) {\n return {\n text: extractedText,\n raw: accumulatedContent\n };\n }\n\n return null;\n },\n close: () => {\n // No cleanup needed\n }\n };\n};\n\n/**\n * Flexible JSON stream parser that can extract text from various field names.\n * This parser looks for display text in multiple possible fields, making it\n * compatible with different JSON response formats.\n * \n * @param textExtractor Optional function to extract display text from parsed JSON.\n * If not provided, looks for common text fields.\n */\nexport const createFlexibleJsonStreamParser = (\n textExtractor?: (parsed: any) => string | null\n): AgentWidgetStreamParser => {\n let extractedText: string | null = null;\n let processedLength = 0;\n \n // Default text extractor that handles common patterns\n const defaultExtractor = (parsed: any): string | null => {\n if (!parsed || typeof parsed !== \"object\") return null;\n\n // Check for component directives - extract text if present for combined text+component\n if (parsed.component && typeof parsed.component === \"string\") {\n // For component directives, extract text if present, otherwise empty\n return typeof parsed.text === \"string\" ? parsed.text : \"\";\n }\n \n // Check for form directives - these also don't have text fields\n if (parsed.type === \"init\" && parsed.form) {\n // For form directives, return empty - they're handled by form postprocessor\n return \"\";\n }\n \n // Check for action-based text fields\n if (parsed.action) {\n switch (parsed.action) {\n case 'nav_then_click':\n return parsed.on_load_text || parsed.text || null;\n case 'message':\n case 'message_and_click':\n case 'checkout':\n return parsed.text || null;\n default:\n return parsed.text || parsed.display_text || parsed.message || null;\n }\n }\n \n // Fallback to common text field names\n return parsed.text || parsed.display_text || parsed.message || parsed.content || null;\n };\n \n const extractText = textExtractor || defaultExtractor;\n \n return {\n getExtractedText: () => extractedText,\n processChunk: (accumulatedContent: string): AgentWidgetStreamParserResult | string | null => {\n // Validate that the accumulated content looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return null;\n }\n \n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedText !== null\n ? { text: extractedText, raw: accumulatedContent }\n : null;\n }\n \n try {\n // Parse partial JSON - allow partial strings and objects\n // STR | OBJ allows incomplete strings and objects during streaming\n const parsed = parsePartialJson(accumulatedContent, STR | OBJ);\n \n // Extract text using the provided or default extractor\n const newText = extractText(parsed);\n if (newText !== null) {\n extractedText = newText;\n }\n } catch (error) {\n // If parsing fails completely, keep the last extracted text\n // This can happen with very malformed JSON\n }\n \n // Update processed length\n processedLength = accumulatedContent.length;\n \n // Always return the raw JSON for action parsing and component detection\n // Text may be null or empty for component/form directives, that's ok\n return {\n text: extractedText || \"\",\n raw: accumulatedContent\n };\n },\n close: () => {\n // No cleanup needed\n }\n };\n};\n\n/**\n * XML stream parser.\n * Extracts text from <text>...</text> tags in XML responses.\n */\nexport const createXmlParser = (): AgentWidgetStreamParser => {\n let extractedText: string | null = null;\n \n return {\n processChunk: (accumulatedContent: string): AgentWidgetStreamParserResult | string | null => {\n // Return null if not XML format\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith('<')) {\n return null;\n }\n \n // Extract text from <text>...</text> tags\n // Handle both <text>content</text> and <text attr=\"value\">content</text>\n const match = accumulatedContent.match(/<text[^>]*>([\\s\\S]*?)<\\/text>/);\n if (match && match[1]) {\n extractedText = match[1];\n // For XML, we typically don't need the raw content for middleware\n // but we can include it for consistency\n return { text: extractedText, raw: accumulatedContent };\n }\n \n return null;\n },\n getExtractedText: (): string | null => {\n return extractedText;\n }\n };\n};\n\n\n\n\n\n\n\n","import {\n AgentWidgetConfig,\n AgentWidgetMessage,\n AgentWidgetEvent,\n AgentWidgetStreamParser,\n AgentWidgetContextProvider,\n AgentWidgetRequestMiddleware,\n AgentWidgetRequestPayload,\n AgentWidgetCustomFetch,\n AgentWidgetSSEEventParser,\n AgentWidgetHeadersFunction,\n AgentWidgetSSEEventResult\n} from \"./types\";\nimport { \n extractTextFromJson, \n createPlainTextParser,\n createJsonStreamParser,\n createRegexJsonParser,\n createXmlParser\n} from \"./utils/formatting\";\n\ntype DispatchOptions = {\n messages: AgentWidgetMessage[];\n signal?: AbortSignal;\n};\n\ntype SSEHandler = (event: AgentWidgetEvent) => void;\n\nconst DEFAULT_ENDPOINT = \"https://api.travrse.ai/v1/dispatch\";\n\n/**\n * Maps parserType string to the corresponding parser factory function\n */\nfunction getParserFromType(parserType?: \"plain\" | \"json\" | \"regex-json\" | \"xml\"): () => AgentWidgetStreamParser {\n switch (parserType) {\n case \"json\":\n return createJsonStreamParser;\n case \"regex-json\":\n return createRegexJsonParser;\n case \"xml\":\n return createXmlParser;\n case \"plain\":\n default:\n return createPlainTextParser;\n }\n}\n\nexport class AgentWidgetClient {\n private readonly apiUrl: string;\n private readonly headers: Record<string, string>;\n private readonly debug: boolean;\n private readonly createStreamParser: () => AgentWidgetStreamParser;\n private readonly contextProviders: AgentWidgetContextProvider[];\n private readonly requestMiddleware?: AgentWidgetRequestMiddleware;\n private readonly customFetch?: AgentWidgetCustomFetch;\n private readonly parseSSEEvent?: AgentWidgetSSEEventParser;\n private readonly getHeaders?: AgentWidgetHeadersFunction;\n\n constructor(private config: AgentWidgetConfig = {}) {\n this.apiUrl = config.apiUrl ?? DEFAULT_ENDPOINT;\n this.headers = {\n \"Content-Type\": \"application/json\",\n ...config.headers\n };\n this.debug = Boolean(config.debug);\n // Use custom stream parser if provided, otherwise use parserType, or fall back to plain text parser\n this.createStreamParser = config.streamParser ?? getParserFromType(config.parserType);\n this.contextProviders = config.contextProviders ?? [];\n this.requestMiddleware = config.requestMiddleware;\n this.customFetch = config.customFetch;\n this.parseSSEEvent = config.parseSSEEvent;\n this.getHeaders = config.getHeaders;\n }\n\n public async dispatch(options: DispatchOptions, onEvent: SSEHandler) {\n const controller = new AbortController();\n if (options.signal) {\n options.signal.addEventListener(\"abort\", () => controller.abort());\n }\n\n onEvent({ type: \"status\", status: \"connecting\" });\n\n const payload = await this.buildPayload(options.messages);\n\n if (this.debug) {\n // eslint-disable-next-line no-console\n console.debug(\"[AgentWidgetClient] dispatch payload\", payload);\n }\n\n // Build headers - merge static headers with dynamic headers if provided\n let headers = { ...this.headers };\n if (this.getHeaders) {\n try {\n const dynamicHeaders = await this.getHeaders();\n headers = { ...headers, ...dynamicHeaders };\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] getHeaders error:\", error);\n }\n }\n }\n\n // Use customFetch if provided, otherwise use default fetch\n let response: Response;\n if (this.customFetch) {\n try {\n response = await this.customFetch(\n this.apiUrl,\n {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal\n },\n payload\n );\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n onEvent({ type: \"error\", error: err });\n throw err;\n }\n } else {\n response = await fetch(this.apiUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n signal: controller.signal\n });\n }\n\n if (!response.ok || !response.body) {\n const error = new Error(\n `Chat backend request failed: ${response.status} ${response.statusText}`\n );\n onEvent({ type: \"error\", error });\n throw error;\n }\n\n onEvent({ type: \"status\", status: \"connected\" });\n try {\n await this.streamResponse(response.body, onEvent);\n } finally {\n onEvent({ type: \"status\", status: \"idle\" });\n }\n }\n\n private async buildPayload(\n messages: AgentWidgetMessage[]\n ): Promise<AgentWidgetRequestPayload> {\n const normalizedMessages = messages\n .slice()\n .sort((a, b) => {\n const timeA = new Date(a.createdAt).getTime();\n const timeB = new Date(b.createdAt).getTime();\n return timeA - timeB;\n })\n .map((message) => ({\n role: message.role,\n content: message.rawContent || message.content,\n createdAt: message.createdAt\n }));\n\n const payload: AgentWidgetRequestPayload = {\n messages: normalizedMessages,\n ...(this.config.flowId && { flowId: this.config.flowId })\n };\n\n if (this.contextProviders.length) {\n const contextAggregate: Record<string, unknown> = {};\n await Promise.all(\n this.contextProviders.map(async (provider) => {\n try {\n const result = await provider({\n messages,\n config: this.config\n });\n if (result && typeof result === \"object\") {\n Object.assign(contextAggregate, result);\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.warn(\"[AgentWidget] Context provider failed:\", error);\n }\n }\n })\n );\n\n if (Object.keys(contextAggregate).length) {\n payload.context = contextAggregate;\n }\n }\n\n if (this.requestMiddleware) {\n try {\n const result = await this.requestMiddleware({\n payload: { ...payload },\n config: this.config\n });\n if (result && typeof result === \"object\") {\n return result as AgentWidgetRequestPayload;\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Request middleware error:\", error);\n }\n }\n }\n\n return payload;\n }\n\n /**\n * Handle custom SSE event parsing via parseSSEEvent callback\n * Returns true if event was handled, false otherwise\n */\n private async handleCustomSSEEvent(\n payload: unknown,\n onEvent: SSEHandler,\n assistantMessageRef: { current: AgentWidgetMessage | null },\n emitMessage: (msg: AgentWidgetMessage) => void,\n nextSequence: () => number\n ): Promise<boolean> {\n if (!this.parseSSEEvent) return false;\n\n try {\n const result = await this.parseSSEEvent(payload);\n if (result === null) return false; // Event should be ignored\n\n const ensureAssistant = () => {\n if (assistantMessageRef.current) return assistantMessageRef.current;\n const msg: AgentWidgetMessage = {\n id: `assistant-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n variant: \"assistant\",\n sequence: nextSequence()\n };\n assistantMessageRef.current = msg;\n emitMessage(msg);\n return msg;\n };\n\n if (result.text !== undefined) {\n const assistant = ensureAssistant();\n assistant.content += result.text;\n emitMessage(assistant);\n }\n\n if (result.done) {\n if (assistantMessageRef.current) {\n assistantMessageRef.current.streaming = false;\n emitMessage(assistantMessageRef.current);\n }\n onEvent({ type: \"status\", status: \"idle\" });\n }\n\n if (result.error) {\n onEvent({\n type: \"error\",\n error: new Error(result.error)\n });\n }\n\n return true; // Event was handled\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] parseSSEEvent error:\", error);\n }\n return false;\n }\n }\n\n private async streamResponse(\n body: ReadableStream<Uint8Array>,\n onEvent: SSEHandler\n ) {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n const baseSequence = Date.now();\n let sequenceCounter = 0;\n const nextSequence = () => baseSequence + sequenceCounter++;\n\n const cloneMessage = (msg: AgentWidgetMessage): AgentWidgetMessage => {\n const reasoning = msg.reasoning\n ? {\n ...msg.reasoning,\n chunks: [...msg.reasoning.chunks]\n }\n : undefined;\n const toolCall = msg.toolCall\n ? {\n ...msg.toolCall,\n chunks: msg.toolCall.chunks ? [...msg.toolCall.chunks] : undefined\n }\n : undefined;\n const tools = msg.tools\n ? msg.tools.map((tool) => ({\n ...tool,\n chunks: tool.chunks ? [...tool.chunks] : undefined\n }))\n : undefined;\n\n return {\n ...msg,\n reasoning,\n toolCall,\n tools\n };\n };\n\n const emitMessage = (msg: AgentWidgetMessage) => {\n onEvent({\n type: \"message\",\n message: cloneMessage(msg)\n });\n };\n\n let assistantMessage: AgentWidgetMessage | null = null;\n // Reference to track assistant message for custom event handler\n const assistantMessageRef = { current: null as AgentWidgetMessage | null };\n const reasoningMessages = new Map<string, AgentWidgetMessage>();\n const toolMessages = new Map<string, AgentWidgetMessage>();\n const reasoningContext = {\n lastId: null as string | null,\n byStep: new Map<string, string>()\n };\n const toolContext = {\n lastId: null as string | null,\n byCall: new Map<string, string>()\n };\n\n const normalizeKey = (value: unknown): string | null => {\n if (value === null || value === undefined) return null;\n try {\n return String(value);\n } catch (error) {\n return null;\n }\n };\n\n const getStepKey = (payload: Record<string, any>) =>\n normalizeKey(\n payload.stepId ??\n payload.step_id ??\n payload.step ??\n payload.parentId ??\n payload.flowStepId ??\n payload.flow_step_id\n );\n\n const getToolCallKey = (payload: Record<string, any>) =>\n normalizeKey(\n payload.callId ??\n payload.call_id ??\n payload.requestId ??\n payload.request_id ??\n payload.toolCallId ??\n payload.tool_call_id ??\n payload.stepId ??\n payload.step_id\n );\n\n const ensureAssistantMessage = () => {\n if (assistantMessage) return assistantMessage;\n assistantMessage = {\n id: `assistant-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n sequence: nextSequence()\n };\n emitMessage(assistantMessage);\n return assistantMessage;\n };\n\n const trackReasoningId = (stepKey: string | null, id: string) => {\n reasoningContext.lastId = id;\n if (stepKey) {\n reasoningContext.byStep.set(stepKey, id);\n }\n };\n\n const resolveReasoningId = (\n payload: Record<string, any>,\n allowCreate: boolean\n ): string | null => {\n const rawId = payload.reasoningId ?? payload.id;\n const stepKey = getStepKey(payload);\n if (rawId) {\n const resolved = String(rawId);\n trackReasoningId(stepKey, resolved);\n return resolved;\n }\n if (stepKey) {\n const existing = reasoningContext.byStep.get(stepKey);\n if (existing) {\n reasoningContext.lastId = existing;\n return existing;\n }\n }\n if (reasoningContext.lastId && !allowCreate) {\n return reasoningContext.lastId;\n }\n if (!allowCreate) {\n return null;\n }\n const generated = `reason-${nextSequence()}`;\n trackReasoningId(stepKey, generated);\n return generated;\n };\n\n const ensureReasoningMessage = (reasoningId: string) => {\n const existing = reasoningMessages.get(reasoningId);\n if (existing) {\n return existing;\n }\n\n const message: AgentWidgetMessage = {\n id: `reason-${reasoningId}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n variant: \"reasoning\",\n sequence: nextSequence(),\n reasoning: {\n id: reasoningId,\n status: \"streaming\",\n chunks: []\n }\n };\n\n reasoningMessages.set(reasoningId, message);\n emitMessage(message);\n return message;\n };\n\n const trackToolId = (callKey: string | null, id: string) => {\n toolContext.lastId = id;\n if (callKey) {\n toolContext.byCall.set(callKey, id);\n }\n };\n\n const resolveToolId = (\n payload: Record<string, any>,\n allowCreate: boolean\n ): string | null => {\n const rawId = payload.toolId ?? payload.id;\n const callKey = getToolCallKey(payload);\n if (rawId) {\n const resolved = String(rawId);\n trackToolId(callKey, resolved);\n return resolved;\n }\n if (callKey) {\n const existing = toolContext.byCall.get(callKey);\n if (existing) {\n toolContext.lastId = existing;\n return existing;\n }\n }\n if (toolContext.lastId && !allowCreate) {\n return toolContext.lastId;\n }\n if (!allowCreate) {\n return null;\n }\n const generated = `tool-${nextSequence()}`;\n trackToolId(callKey, generated);\n return generated;\n };\n\n const ensureToolMessage = (toolId: string) => {\n const existing = toolMessages.get(toolId);\n if (existing) {\n return existing;\n }\n\n const message: AgentWidgetMessage = {\n id: `tool-${toolId}`,\n role: \"assistant\",\n content: \"\",\n createdAt: new Date().toISOString(),\n streaming: true,\n variant: \"tool\",\n sequence: nextSequence(),\n toolCall: {\n id: toolId,\n status: \"pending\"\n }\n };\n\n toolMessages.set(toolId, message);\n emitMessage(message);\n return message;\n };\n\n const resolveTimestamp = (value: unknown) => {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n if (typeof value === \"string\") {\n const parsed = Number(value);\n if (!Number.isNaN(parsed) && Number.isFinite(parsed)) {\n return parsed;\n }\n const dateParsed = Date.parse(value);\n if (!Number.isNaN(dateParsed)) {\n return dateParsed;\n }\n }\n return Date.now();\n };\n\n const ensureStringContent = (value: unknown): string => {\n if (typeof value === \"string\") {\n return value;\n }\n if (value === null || value === undefined) {\n return \"\";\n }\n // Convert objects/arrays to JSON string\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n };\n\n // Maintain stateful stream parsers per message for incremental parsing\n const streamParsers = new Map<string, AgentWidgetStreamParser>();\n // Track accumulated raw content for structured formats (JSON, XML, etc.)\n const rawContentBuffers = new Map<string, string>();\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 events = buffer.split(\"\\n\\n\");\n buffer = events.pop() ?? \"\";\n\n for (const event of events) {\n const lines = event.split(\"\\n\");\n let eventType = \"message\";\n let data = \"\";\n\n for (const line of lines) {\n if (line.startsWith(\"event:\")) {\n eventType = line.replace(\"event:\", \"\").trim();\n } else if (line.startsWith(\"data:\")) {\n data += line.replace(\"data:\", \"\").trim();\n }\n }\n\n if (!data) continue;\n let payload: any;\n try {\n payload = JSON.parse(data);\n } catch (error) {\n onEvent({\n type: \"error\",\n error:\n error instanceof Error\n ? error\n : new Error(\"Failed to parse chat stream payload\")\n });\n continue;\n }\n\n const payloadType =\n eventType !== \"message\" ? eventType : payload.type ?? \"message\";\n\n // If custom SSE event parser is provided, try it first\n if (this.parseSSEEvent) {\n // Keep assistant message ref in sync\n assistantMessageRef.current = assistantMessage;\n const handled = await this.handleCustomSSEEvent(\n payload,\n onEvent,\n assistantMessageRef,\n emitMessage,\n nextSequence\n );\n // Update assistantMessage from ref (in case it was created)\n if (assistantMessageRef.current && !assistantMessage) {\n assistantMessage = assistantMessageRef.current;\n }\n if (handled) continue; // Skip default handling if custom handler processed it\n }\n\n if (payloadType === \"reason_start\") {\n const reasoningId =\n resolveReasoningId(payload, true) ?? `reason-${nextSequence()}`;\n const reasoningMessage = ensureReasoningMessage(reasoningId);\n reasoningMessage.reasoning = reasoningMessage.reasoning ?? {\n id: reasoningId,\n status: \"streaming\",\n chunks: []\n };\n reasoningMessage.reasoning.startedAt =\n reasoningMessage.reasoning.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n reasoningMessage.reasoning.completedAt = undefined;\n reasoningMessage.reasoning.durationMs = undefined;\n reasoningMessage.streaming = true;\n reasoningMessage.reasoning.status = \"streaming\";\n emitMessage(reasoningMessage);\n } else if (payloadType === \"reason_chunk\") {\n const reasoningId =\n resolveReasoningId(payload, false) ??\n resolveReasoningId(payload, true) ??\n `reason-${nextSequence()}`;\n const reasoningMessage = ensureReasoningMessage(reasoningId);\n reasoningMessage.reasoning = reasoningMessage.reasoning ?? {\n id: reasoningId,\n status: \"streaming\",\n chunks: []\n };\n reasoningMessage.reasoning.startedAt =\n reasoningMessage.reasoning.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n const chunk =\n payload.reasoningText ??\n payload.text ??\n payload.delta ??\n \"\";\n if (chunk && payload.hidden !== true) {\n reasoningMessage.reasoning.chunks.push(String(chunk));\n }\n reasoningMessage.reasoning.status = payload.done ? \"complete\" : \"streaming\";\n if (payload.done) {\n reasoningMessage.reasoning.completedAt = resolveTimestamp(\n payload.completedAt ?? payload.timestamp\n );\n const start = reasoningMessage.reasoning.startedAt ?? Date.now();\n reasoningMessage.reasoning.durationMs = Math.max(\n 0,\n (reasoningMessage.reasoning.completedAt ?? Date.now()) - start\n );\n }\n reasoningMessage.streaming = reasoningMessage.reasoning.status !== \"complete\";\n emitMessage(reasoningMessage);\n } else if (payloadType === \"reason_complete\") {\n const reasoningId =\n resolveReasoningId(payload, false) ??\n resolveReasoningId(payload, true) ??\n `reason-${nextSequence()}`;\n const reasoningMessage = reasoningMessages.get(reasoningId);\n if (reasoningMessage?.reasoning) {\n reasoningMessage.reasoning.status = \"complete\";\n reasoningMessage.reasoning.completedAt = resolveTimestamp(\n payload.completedAt ?? payload.timestamp\n );\n const start = reasoningMessage.reasoning.startedAt ?? Date.now();\n reasoningMessage.reasoning.durationMs = Math.max(\n 0,\n (reasoningMessage.reasoning.completedAt ?? Date.now()) - start\n );\n reasoningMessage.streaming = false;\n emitMessage(reasoningMessage);\n }\n const stepKey = getStepKey(payload);\n if (stepKey) {\n reasoningContext.byStep.delete(stepKey);\n }\n } else if (payloadType === \"tool_start\") {\n const toolId =\n resolveToolId(payload, true) ?? `tool-${nextSequence()}`;\n const toolMessage = ensureToolMessage(toolId);\n const tool = toolMessage.toolCall ?? {\n id: toolId,\n status: \"pending\"\n };\n tool.name = payload.toolName ?? tool.name;\n tool.status = \"running\";\n if (payload.args !== undefined) {\n tool.args = payload.args;\n }\n tool.startedAt =\n tool.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n tool.completedAt = undefined;\n tool.durationMs = undefined;\n toolMessage.toolCall = tool;\n toolMessage.streaming = true;\n emitMessage(toolMessage);\n } else if (payloadType === \"tool_chunk\") {\n const toolId =\n resolveToolId(payload, false) ??\n resolveToolId(payload, true) ??\n `tool-${nextSequence()}`;\n const toolMessage = ensureToolMessage(toolId);\n const tool = toolMessage.toolCall ?? {\n id: toolId,\n status: \"running\"\n };\n tool.startedAt =\n tool.startedAt ??\n resolveTimestamp(payload.startedAt ?? payload.timestamp);\n const chunkText =\n payload.text ?? payload.delta ?? payload.message ?? \"\";\n if (chunkText) {\n tool.chunks = tool.chunks ?? [];\n tool.chunks.push(String(chunkText));\n }\n tool.status = \"running\";\n toolMessage.toolCall = tool;\n toolMessage.streaming = true;\n emitMessage(toolMessage);\n } else if (payloadType === \"tool_complete\") {\n const toolId =\n resolveToolId(payload, false) ??\n resolveToolId(payload, true) ??\n `tool-${nextSequence()}`;\n const toolMessage = ensureToolMessage(toolId);\n const tool = toolMessage.toolCall ?? {\n id: toolId,\n status: \"running\"\n };\n tool.status = \"complete\";\n if (payload.result !== undefined) {\n tool.result = payload.result;\n }\n if (typeof payload.duration === \"number\") {\n tool.duration = payload.duration;\n }\n tool.completedAt = resolveTimestamp(\n payload.completedAt ?? payload.timestamp\n );\n if (typeof payload.duration === \"number\") {\n tool.durationMs = payload.duration;\n } else {\n const start = tool.startedAt ?? Date.now();\n tool.durationMs = Math.max(\n 0,\n (tool.completedAt ?? Date.now()) - start\n );\n }\n toolMessage.toolCall = tool;\n toolMessage.streaming = false;\n emitMessage(toolMessage);\n const callKey = getToolCallKey(payload);\n if (callKey) {\n toolContext.byCall.delete(callKey);\n }\n } else if (payloadType === \"step_chunk\") {\n // Only process chunks for prompt steps, not tool/context steps\n const stepType = (payload as any).stepType;\n const executionType = (payload as any).executionType;\n if (stepType === \"tool\" || executionType === \"context\") {\n // Skip tool-related chunks - they're handled by tool_start/tool_complete\n continue;\n }\n const assistant = ensureAssistantMessage();\n // Support various field names: text, delta, content, chunk (Travrse uses 'chunk')\n const chunk = payload.text ?? payload.delta ?? payload.content ?? payload.chunk ?? \"\";\n if (chunk) {\n // Accumulate raw content for structured format parsing\n const rawBuffer = rawContentBuffers.get(assistant.id) ?? \"\";\n const accumulatedRaw = rawBuffer + chunk;\n // Store raw content for action parsing, but NEVER set assistant.content to raw JSON\n assistant.rawContent = accumulatedRaw;\n \n // Use stream parser to parse\n if (!streamParsers.has(assistant.id)) {\n streamParsers.set(assistant.id, this.createStreamParser());\n }\n const parser = streamParsers.get(assistant.id)!;\n \n // Check if content looks like JSON\n const looksLikeJson = accumulatedRaw.trim().startsWith('{') || accumulatedRaw.trim().startsWith('[');\n \n // Store raw buffer before processing (needed for step_complete handler)\n if (looksLikeJson) {\n rawContentBuffers.set(assistant.id, accumulatedRaw);\n }\n \n // Check if this is a plain text parser (marked with __isPlainTextParser)\n const isPlainTextParser = (parser as any).__isPlainTextParser === true;\n \n // If plain text parser, just append the chunk directly\n if (isPlainTextParser) {\n assistant.content += chunk;\n // Clear any raw buffer/parser since we're in plain text mode\n rawContentBuffers.delete(assistant.id);\n streamParsers.delete(assistant.id);\n assistant.rawContent = undefined;\n emitMessage(assistant);\n continue;\n }\n \n // Try to parse with the parser (for structured parsers)\n const parsedResult = parser.processChunk(accumulatedRaw);\n \n // Handle async parser result\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n // Parser successfully extracted text\n // Update the message content with extracted text\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n emitMessage(currentAssistant);\n }\n } else if (!looksLikeJson && !accumulatedRaw.trim().startsWith('<')) {\n // Not a structured format - show as plain text\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content += chunk;\n rawContentBuffers.delete(currentAssistant.id);\n streamParsers.delete(currentAssistant.id);\n currentAssistant.rawContent = undefined;\n emitMessage(currentAssistant);\n }\n }\n // Otherwise wait for more chunks (incomplete structured format)\n // Don't emit message if parser hasn't extracted text yet\n }).catch(() => {\n // On error, treat as plain text\n assistant.content += chunk;\n rawContentBuffers.delete(assistant.id);\n streamParsers.delete(assistant.id);\n assistant.rawContent = undefined;\n emitMessage(assistant);\n });\n } else {\n // Synchronous parser result\n // Extract text from result (could be string, null, or object)\n const text = typeof parsedResult === 'string' ? parsedResult : parsedResult?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n // Parser successfully extracted text\n // Buffer is already set above\n assistant.content = text;\n emitMessage(assistant);\n } else if (!looksLikeJson && !accumulatedRaw.trim().startsWith('<')) {\n // Not a structured format - show as plain text\n assistant.content += chunk;\n // Clear any raw buffer/parser if we were in structured format mode\n rawContentBuffers.delete(assistant.id);\n streamParsers.delete(assistant.id);\n assistant.rawContent = undefined;\n emitMessage(assistant);\n }\n // Otherwise wait for more chunks (incomplete structured format)\n // Don't emit message if parser hasn't extracted text yet\n }\n \n // IMPORTANT: Don't call getExtractedText() and emit messages here\n // This was causing raw JSON to be displayed because getExtractedText() \n // wasn't extracting the \"text\" field correctly during streaming\n }\n if (payload.isComplete) {\n const finalContent = payload.result?.response ?? assistant.content;\n if (finalContent) {\n // Check if we have raw content buffer that needs final processing\n const rawBuffer = rawContentBuffers.get(assistant.id);\n const contentToProcess = rawBuffer ?? ensureStringContent(finalContent);\n assistant.rawContent = contentToProcess;\n \n // Try to extract text from final structured content\n const parser = streamParsers.get(assistant.id);\n let extractedText: string | null = null;\n \n if (parser) {\n // First check if parser already has extracted text\n extractedText = parser.getExtractedText();\n \n if (extractedText === null) {\n // Try extracting with regex\n extractedText = extractTextFromJson(contentToProcess);\n }\n \n if (extractedText === null) {\n // Try parser.processChunk as last resort\n const parsedResult = parser.processChunk(contentToProcess);\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n if (text !== null) {\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n }\n });\n } else {\n // Extract text from synchronous result\n extractedText = typeof parsedResult === 'string' ? parsedResult : parsedResult?.text ?? null;\n }\n }\n }\n \n // Set content: use extracted text if available, otherwise use raw content\n if (extractedText !== null && extractedText.trim() !== \"\") {\n assistant.content = extractedText;\n } else if (!rawContentBuffers.has(assistant.id)) {\n // Only use raw final content if we didn't accumulate chunks\n assistant.content = ensureStringContent(finalContent);\n }\n \n // Clean up parser and buffer\n const parserToClose = streamParsers.get(assistant.id);\n if (parserToClose) {\n const closeResult = parserToClose.close?.();\n if (closeResult instanceof Promise) {\n closeResult.catch(() => {});\n }\n streamParsers.delete(assistant.id);\n }\n rawContentBuffers.delete(assistant.id);\n assistant.streaming = false;\n emitMessage(assistant);\n }\n }\n } else if (payloadType === \"step_complete\") {\n // Only process completions for prompt steps, not tool/context steps\n const stepType = (payload as any).stepType;\n const executionType = (payload as any).executionType;\n if (stepType === \"tool\" || executionType === \"context\") {\n // Skip tool-related completions - they're handled by tool_complete\n continue;\n }\n const finalContent = payload.result?.response;\n const assistant = ensureAssistantMessage();\n if (finalContent !== undefined && finalContent !== null) {\n // Check if we already have extracted text from streaming\n const parser = streamParsers.get(assistant.id);\n let hasExtractedText = false;\n \n if (parser) {\n // First check if parser already extracted text during streaming\n const currentExtractedText = parser.getExtractedText();\n const rawBuffer = rawContentBuffers.get(assistant.id);\n const contentToProcess = rawBuffer ?? ensureStringContent(finalContent);\n \n // Always set rawContent so action parsers can access the raw JSON\n assistant.rawContent = contentToProcess;\n \n if (currentExtractedText !== null && currentExtractedText.trim() !== \"\") {\n // We already have extracted text from streaming - use it\n assistant.content = currentExtractedText;\n hasExtractedText = true;\n } else {\n // No extracted text yet - try to extract from final content\n \n // Try fast path first\n const extractedText = extractTextFromJson(contentToProcess);\n if (extractedText !== null) {\n assistant.content = extractedText;\n hasExtractedText = true;\n } else {\n // Try parser\n const parsedResult = parser.processChunk(contentToProcess);\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n } else {\n // No extracted text - check if we should show raw content\n const finalExtractedText = parser.getExtractedText();\n if (finalExtractedText === null || finalExtractedText.trim() === \"\") {\n // No extracted text available - show raw content only if no streaming happened\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n // Only show raw content if we never had any extracted text\n if (!rawContentBuffers.has(assistant.id)) {\n currentAssistant.content = ensureStringContent(finalContent);\n }\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n }\n }\n });\n } else {\n // Extract text from synchronous result\n const text = typeof parsedResult === 'string' ? parsedResult : parsedResult?.text ?? null;\n \n if (text !== null && text.trim() !== \"\") {\n assistant.content = text;\n hasExtractedText = true;\n } else {\n // Check stub one more time\n const finalExtractedText = parser.getExtractedText();\n if (finalExtractedText !== null && finalExtractedText.trim() !== \"\") {\n assistant.content = finalExtractedText;\n hasExtractedText = true;\n }\n }\n }\n }\n }\n }\n \n // Ensure rawContent is set even if there's no parser (for action parsing)\n if (!assistant.rawContent) {\n const rawBuffer = rawContentBuffers.get(assistant.id);\n assistant.rawContent = rawBuffer ?? ensureStringContent(finalContent);\n }\n \n // Only show raw content if we never extracted any text and no buffer was used\n if (!hasExtractedText && !rawContentBuffers.has(assistant.id)) {\n // No extracted text and no streaming happened - show raw content\n assistant.content = ensureStringContent(finalContent);\n }\n \n // Clean up parser and buffer\n if (parser) {\n const closeResult = parser.close?.();\n if (closeResult instanceof Promise) {\n closeResult.catch(() => {});\n }\n }\n streamParsers.delete(assistant.id);\n rawContentBuffers.delete(assistant.id);\n assistant.streaming = false;\n emitMessage(assistant);\n } else {\n // No final content, just mark as complete and clean up\n streamParsers.delete(assistant.id);\n rawContentBuffers.delete(assistant.id);\n assistant.streaming = false;\n emitMessage(assistant);\n }\n } else if (payloadType === \"flow_complete\") {\n const finalContent = payload.result?.response;\n if (finalContent !== undefined && finalContent !== null) {\n const assistant = ensureAssistantMessage();\n // Check if we have raw content buffer that needs final processing\n const rawBuffer = rawContentBuffers.get(assistant.id);\n const stringContent = rawBuffer ?? ensureStringContent(finalContent);\n assistant.rawContent = stringContent;\n // Try to extract text from structured content\n let displayContent = ensureStringContent(finalContent);\n const parser = streamParsers.get(assistant.id);\n if (parser) {\n const extractedText = extractTextFromJson(stringContent);\n if (extractedText !== null) {\n displayContent = extractedText;\n } else {\n // Try parser if it exists\n const parsedResult = parser.processChunk(stringContent);\n if (parsedResult instanceof Promise) {\n parsedResult.then((result) => {\n // Extract text from result (could be string or object)\n const text = typeof result === 'string' ? result : result?.text ?? null;\n if (text !== null) {\n const currentAssistant = assistantMessage;\n if (currentAssistant && currentAssistant.id === assistant.id) {\n currentAssistant.content = text;\n currentAssistant.streaming = false;\n emitMessage(currentAssistant);\n }\n }\n });\n }\n const currentText = parser.getExtractedText();\n if (currentText !== null) {\n displayContent = currentText;\n }\n }\n }\n // Clean up parser and buffer\n streamParsers.delete(assistant.id);\n rawContentBuffers.delete(assistant.id);\n if (displayContent !== assistant.content) {\n assistant.content = displayContent;\n emitMessage(assistant);\n }\n assistant.streaming = false;\n emitMessage(assistant);\n } else {\n // No final content, just mark as complete and clean up\n if (assistantMessage !== null) {\n // Clean up any remaining parsers/buffers\n // TypeScript narrowing issue - assistantMessage is checked for null above\n const msg: AgentWidgetMessage = assistantMessage;\n streamParsers.delete(msg.id);\n rawContentBuffers.delete(msg.id);\n msg.streaming = false;\n emitMessage(msg);\n }\n }\n onEvent({ type: \"status\", status: \"idle\" });\n } else if (payloadType === \"error\" && payload.error) {\n onEvent({\n type: \"error\",\n error:\n payload.error instanceof Error\n ? payload.error\n : new Error(String(payload.error))\n });\n }\n }\n }\n }\n}\n","import { AgentWidgetClient } from \"./client\";\nimport {\n AgentWidgetConfig,\n AgentWidgetEvent,\n AgentWidgetMessage\n} from \"./types\";\n\nexport type AgentWidgetSessionStatus =\n | \"idle\"\n | \"connecting\"\n | \"connected\"\n | \"error\";\n\ntype SessionCallbacks = {\n onMessagesChanged: (messages: AgentWidgetMessage[]) => void;\n onStatusChanged: (status: AgentWidgetSessionStatus) => void;\n onStreamingChanged: (streaming: boolean) => void;\n onError?: (error: Error) => void;\n};\n\nexport class AgentWidgetSession {\n private client: AgentWidgetClient;\n private messages: AgentWidgetMessage[];\n private status: AgentWidgetSessionStatus = \"idle\";\n private streaming = false;\n private abortController: AbortController | null = null;\n private sequenceCounter = Date.now();\n\n constructor(\n private config: AgentWidgetConfig = {},\n private callbacks: SessionCallbacks\n ) {\n this.messages = [...(config.initialMessages ?? [])].map((message) => ({\n ...message,\n sequence: message.sequence ?? this.nextSequence()\n }));\n this.messages = this.sortMessages(this.messages);\n this.client = new AgentWidgetClient(config);\n\n if (this.messages.length) {\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n this.callbacks.onStatusChanged(this.status);\n }\n\n public updateConfig(next: AgentWidgetConfig) {\n this.config = { ...this.config, ...next };\n this.client = new AgentWidgetClient(this.config);\n }\n\n public getMessages() {\n return [...this.messages];\n }\n\n public getStatus() {\n return this.status;\n }\n\n public isStreaming() {\n return this.streaming;\n }\n\n public injectTestEvent(event: AgentWidgetEvent) {\n this.handleEvent(event);\n }\n\n public async sendMessage(rawInput: string, options?: { viaVoice?: boolean }) {\n const input = rawInput.trim();\n if (!input) return;\n\n this.abortController?.abort();\n\n const userMessage: AgentWidgetMessage = {\n id: `user-${Date.now()}`,\n role: \"user\",\n content: input,\n createdAt: new Date().toISOString(),\n sequence: this.nextSequence(),\n viaVoice: options?.viaVoice || false\n };\n\n this.appendMessage(userMessage);\n this.setStreaming(true);\n\n const controller = new AbortController();\n this.abortController = controller;\n\n const snapshot = [...this.messages];\n\n try {\n await this.client.dispatch(\n {\n messages: snapshot,\n signal: controller.signal\n },\n this.handleEvent\n );\n } catch (error) {\n const fallback: AgentWidgetMessage = {\n id: `assistant-${Date.now()}`,\n role: \"assistant\",\n createdAt: new Date().toISOString(),\n content:\n \"It looks like the proxy isn't returning a real response yet. Here's a sample message so you can continue testing locally.\",\n sequence: this.nextSequence()\n };\n\n this.appendMessage(fallback);\n this.setStatus(\"idle\");\n this.setStreaming(false);\n this.abortController = null;\n if (error instanceof Error) {\n this.callbacks.onError?.(error);\n } else {\n this.callbacks.onError?.(new Error(String(error)));\n }\n }\n }\n\n public cancel() {\n this.abortController?.abort();\n this.abortController = null;\n this.setStreaming(false);\n this.setStatus(\"idle\");\n }\n\n public clearMessages() {\n this.abortController?.abort();\n this.abortController = null;\n this.messages = [];\n this.setStreaming(false);\n this.setStatus(\"idle\");\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n public hydrateMessages(messages: AgentWidgetMessage[]) {\n this.abortController?.abort();\n this.abortController = null;\n this.messages = this.sortMessages(\n messages.map((message) => ({\n ...message,\n streaming: false,\n sequence: message.sequence ?? this.nextSequence()\n }))\n );\n this.setStreaming(false);\n this.setStatus(\"idle\");\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n private handleEvent = (event: AgentWidgetEvent) => {\n if (event.type === \"message\") {\n this.upsertMessage(event.message);\n } else if (event.type === \"status\") {\n this.setStatus(event.status);\n if (event.status === \"connecting\") {\n this.setStreaming(true);\n } else if (event.status === \"idle\" || event.status === \"error\") {\n this.setStreaming(false);\n this.abortController = null;\n }\n } else if (event.type === \"error\") {\n this.setStatus(\"error\");\n this.setStreaming(false);\n this.abortController = null;\n this.callbacks.onError?.(event.error);\n }\n };\n\n private setStatus(status: AgentWidgetSessionStatus) {\n if (this.status === status) return;\n this.status = status;\n this.callbacks.onStatusChanged(status);\n }\n\n private setStreaming(streaming: boolean) {\n if (this.streaming === streaming) return;\n this.streaming = streaming;\n this.callbacks.onStreamingChanged(streaming);\n }\n\n private appendMessage(message: AgentWidgetMessage) {\n const withSequence = this.ensureSequence(message);\n this.messages = this.sortMessages([...this.messages, withSequence]);\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n private upsertMessage(message: AgentWidgetMessage) {\n const withSequence = this.ensureSequence(message);\n const index = this.messages.findIndex((m) => m.id === withSequence.id);\n if (index === -1) {\n this.appendMessage(withSequence);\n return;\n }\n\n this.messages = this.messages.map((existing, idx) =>\n idx === index ? { ...existing, ...withSequence } : existing\n );\n this.messages = this.sortMessages(this.messages);\n this.callbacks.onMessagesChanged([...this.messages]);\n }\n\n private ensureSequence(message: AgentWidgetMessage): AgentWidgetMessage {\n if (message.sequence !== undefined) {\n return { ...message };\n }\n return {\n ...message,\n sequence: this.nextSequence()\n };\n }\n\n private nextSequence() {\n return this.sequenceCounter++;\n }\n\n private sortMessages(messages: AgentWidgetMessage[]) {\n return [...messages].sort((a, b) => {\n // Sort by createdAt timestamp first (chronological order)\n const timeA = new Date(a.createdAt).getTime();\n const timeB = new Date(b.createdAt).getTime();\n if (!Number.isNaN(timeA) && !Number.isNaN(timeB) && timeA !== timeB) {\n return timeA - timeB;\n }\n\n // Fall back to sequence if timestamps are equal or invalid\n const seqA = a.sequence ?? 0;\n const seqB = b.sequence ?? 0;\n if (seqA !== seqB) return seqA - seqB;\n\n // Final fallback to ID\n return a.id.localeCompare(b.id);\n });\n }\n}\n","import { AgentWidgetConfig } from \"../types\";\n\nexport const applyThemeVariables = (\n element: HTMLElement,\n config?: AgentWidgetConfig\n) => {\n const theme = config?.theme ?? {};\n Object.entries(theme).forEach(([key, value]) => {\n // Skip undefined or empty values\n if (value === undefined || value === null || value === \"\") {\n return;\n }\n // Convert camelCase to kebab-case (e.g., radiusSm → radius-sm)\n const kebabKey = key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);\n element.style.setProperty(`--cw-${kebabKey}`, String(value));\n });\n};\n\n\n\n\n\n\n\n\n","import * as icons from \"lucide\";\nimport type { IconNode } from \"lucide\";\n\n/**\n * Renders a Lucide icon as an inline SVG element\n * This approach requires no CSS and works on any page\n * \n * @param iconName - The Lucide icon name in kebab-case (e.g., \"arrow-up\")\n * @param size - The size of the icon (default: 24)\n * @param color - The stroke color (default: \"currentColor\")\n * @param strokeWidth - The stroke width (default: 2)\n * @returns SVGElement or null if icon not found\n */\nexport const renderLucideIcon = (\n iconName: string,\n size: number | string = 24,\n color: string = \"currentColor\",\n strokeWidth: number = 2\n): SVGElement | null => {\n try {\n // Convert kebab-case to PascalCase (e.g., \"arrow-up\" -> \"ArrowUp\")\n const pascalName = iconName\n .split(\"-\")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(\"\");\n \n // Lucide's icons object contains IconNode data directly, not functions\n const iconData = (icons as Record<string, IconNode>)[pascalName] as IconNode;\n \n if (!iconData) {\n console.warn(`Lucide icon \"${iconName}\" not found (tried \"${pascalName}\"). Available icons: https://lucide.dev/icons`);\n return null;\n }\n\n return createSvgFromIconData(iconData, size, color, strokeWidth);\n } catch (error) {\n console.warn(`Failed to render Lucide icon \"${iconName}\":`, error);\n return null;\n }\n};\n\n/**\n * Helper function to create SVG from IconNode data\n */\nfunction createSvgFromIconData(\n iconData: IconNode,\n size: number | string,\n color: string,\n strokeWidth: number\n): SVGElement | null {\n if (!iconData || !Array.isArray(iconData)) {\n return null;\n }\n\n // Create SVG element\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"width\", String(size));\n svg.setAttribute(\"height\", String(size));\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", color);\n svg.setAttribute(\"stroke-width\", String(strokeWidth));\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n \n // Render elements from icon data\n // IconNode format: [[\"path\", {\"d\": \"...\"}], [\"rect\", {\"x\": \"...\", \"y\": \"...\"}], ...]\n iconData.forEach((elementData) => {\n if (Array.isArray(elementData) && elementData.length >= 2) {\n const tagName = elementData[0] as string;\n const attrs = elementData[1] as Record<string, string>;\n \n if (attrs) {\n // Create the appropriate SVG element (path, rect, circle, ellipse, line, etc.)\n const element = document.createElementNS(\"http://www.w3.org/2000/svg\", tagName);\n \n // Apply all attributes, but skip 'stroke' (we want to use the parent SVG's stroke for consistent coloring)\n Object.entries(attrs).forEach(([key, value]) => {\n if (key !== \"stroke\") {\n element.setAttribute(key, String(value));\n }\n });\n \n svg.appendChild(element);\n }\n }\n });\n \n return svg;\n}\n\n","/**\n * DOM utility functions\n */\nexport const createElement = <K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className?: string\n): HTMLElementTagNameMap[K] => {\n const element = document.createElement(tag);\n if (className) {\n element.className = className;\n }\n return element;\n};\n\nexport const createFragment = (): DocumentFragment => {\n return document.createDocumentFragment();\n};\n\n\n\n\n\n\n\n\n","import { AgentWidgetSessionStatus } from \"../session\";\n\nexport const statusCopy: Record<AgentWidgetSessionStatus, string> = {\n idle: \"Online\",\n connecting: \"Connecting…\",\n connected: \"Streaming…\",\n error: \"Offline\"\n};\n\n\n\n\n\n\n\n\n","export const positionMap: Record<\n \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\",\n string\n> = {\n \"bottom-right\": \"tvw-bottom-6 tvw-right-6\",\n \"bottom-left\": \"tvw-bottom-6 tvw-left-6\",\n \"top-right\": \"tvw-top-6 tvw-right-6\",\n \"top-left\": \"tvw-top-6 tvw-left-6\"\n};\n\n\n\n\n\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetConfig } from \"../types\";\nimport { positionMap } from \"../utils/positioning\";\nimport { renderLucideIcon } from \"../utils/icons\";\n\nexport interface LauncherButton {\n element: HTMLButtonElement;\n update: (config: AgentWidgetConfig) => void;\n destroy: () => void;\n}\n\nexport const createLauncherButton = (\n config: AgentWidgetConfig | undefined,\n onToggle: () => void\n): LauncherButton => {\n const button = createElement(\"button\") as HTMLButtonElement;\n button.type = \"button\";\n button.innerHTML = `\n <span class=\"tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-bg-cw-primary tvw-text-white\" data-role=\"launcher-icon\">💬</span>\n <img data-role=\"launcher-image\" class=\"tvw-rounded-full tvw-object-cover\" alt=\"\" style=\"display:none\" />\n <span class=\"tvw-flex tvw-flex-col tvw-items-start tvw-text-left\">\n <span class=\"tvw-text-sm tvw-font-semibold tvw-text-cw-primary\" data-role=\"launcher-title\"></span>\n <span class=\"tvw-text-xs tvw-text-cw-muted\" data-role=\"launcher-subtitle\"></span>\n </span>\n <span class=\"tvw-ml-2 tvw-grid tvw-place-items-center tvw-rounded-full tvw-bg-cw-primary tvw-text-cw-call-to-action\" data-role=\"launcher-call-to-action-icon\">↗</span>\n `;\n button.addEventListener(\"click\", onToggle);\n\n const update = (newConfig: AgentWidgetConfig) => {\n const launcher = newConfig.launcher ?? {};\n\n const titleEl = button.querySelector(\"[data-role='launcher-title']\");\n if (titleEl) {\n titleEl.textContent = launcher.title ?? \"Chat Assistant\";\n }\n\n const subtitleEl = button.querySelector(\"[data-role='launcher-subtitle']\");\n if (subtitleEl) {\n subtitleEl.textContent = launcher.subtitle ?? \"Get answers fast\";\n }\n\n // Hide/show text container\n const textContainer = button.querySelector(\".tvw-flex-col\");\n if (textContainer) {\n if (launcher.textHidden) {\n (textContainer as HTMLElement).style.display = \"none\";\n } else {\n (textContainer as HTMLElement).style.display = \"\";\n }\n }\n\n const icon = button.querySelector<HTMLSpanElement>(\"[data-role='launcher-icon']\");\n if (icon) {\n if (launcher.agentIconHidden) {\n icon.style.display = \"none\";\n } else {\n const iconSize = launcher.agentIconSize ?? \"40px\";\n icon.style.height = iconSize;\n icon.style.width = iconSize;\n \n // Clear existing content\n icon.innerHTML = \"\";\n \n // Render icon based on priority: Lucide icon > iconUrl > agentIconText\n if (launcher.agentIconName) {\n // Use Lucide icon\n const iconSizeNum = parseFloat(iconSize) || 24;\n const iconSvg = renderLucideIcon(launcher.agentIconName, iconSizeNum * 0.6, \"#ffffff\", 2);\n if (iconSvg) {\n icon.appendChild(iconSvg);\n icon.style.display = \"\";\n } else {\n // Fallback to agentIconText if Lucide icon fails\n icon.textContent = launcher.agentIconText ?? \"💬\";\n icon.style.display = \"\";\n }\n } else if (launcher.iconUrl) {\n // Use image URL - hide icon span and show img\n icon.style.display = \"none\";\n } else {\n // Use text/emoji\n icon.textContent = launcher.agentIconText ?? \"💬\";\n icon.style.display = \"\";\n }\n }\n }\n\n const img = button.querySelector<HTMLImageElement>(\"[data-role='launcher-image']\");\n if (img) {\n const iconSize = launcher.agentIconSize ?? \"40px\";\n img.style.height = iconSize;\n img.style.width = iconSize;\n if (launcher.iconUrl && !launcher.agentIconName && !launcher.agentIconHidden) {\n // Only show image if not using Lucide icon and not hidden\n img.src = launcher.iconUrl;\n img.style.display = \"block\";\n } else {\n img.style.display = \"none\";\n }\n }\n\n const callToActionIconEl = button.querySelector<HTMLSpanElement>(\"[data-role='launcher-call-to-action-icon']\");\n if (callToActionIconEl) {\n const callToActionIconSize = launcher.callToActionIconSize ?? \"32px\";\n callToActionIconEl.style.height = callToActionIconSize;\n callToActionIconEl.style.width = callToActionIconSize;\n \n // Apply background color if configured\n if (launcher.callToActionIconBackgroundColor) {\n callToActionIconEl.style.backgroundColor = launcher.callToActionIconBackgroundColor;\n callToActionIconEl.classList.remove(\"tvw-bg-cw-primary\");\n } else {\n callToActionIconEl.style.backgroundColor = \"\";\n callToActionIconEl.classList.add(\"tvw-bg-cw-primary\");\n }\n \n // Calculate padding to adjust icon size\n let paddingTotal = 0;\n if (launcher.callToActionIconPadding) {\n callToActionIconEl.style.boxSizing = \"border-box\";\n callToActionIconEl.style.padding = launcher.callToActionIconPadding;\n // Parse padding value to calculate total padding (padding applies to both sides)\n const paddingValue = parseFloat(launcher.callToActionIconPadding) || 0;\n paddingTotal = paddingValue * 2; // padding on both sides\n } else {\n callToActionIconEl.style.boxSizing = \"\";\n callToActionIconEl.style.padding = \"\";\n }\n \n if (launcher.callToActionIconHidden) {\n callToActionIconEl.style.display = \"none\";\n } else {\n callToActionIconEl.style.display = \"\";\n \n // Clear existing content\n callToActionIconEl.innerHTML = \"\";\n \n // Use Lucide icon if provided, otherwise fall back to text\n if (launcher.callToActionIconName) {\n // Calculate actual icon size by subtracting padding\n const containerSize = parseFloat(callToActionIconSize) || 24;\n const iconSize = Math.max(containerSize - paddingTotal, 8); // Ensure minimum size of 8px\n const iconSvg = renderLucideIcon(launcher.callToActionIconName, iconSize, \"currentColor\", 2);\n if (iconSvg) {\n callToActionIconEl.appendChild(iconSvg);\n } else {\n // Fallback to text if icon fails to render\n callToActionIconEl.textContent = launcher.callToActionIconText ?? \"↗\";\n }\n } else {\n callToActionIconEl.textContent = launcher.callToActionIconText ?? \"↗\";\n }\n }\n }\n\n const positionClass =\n launcher.position && positionMap[launcher.position]\n ? positionMap[launcher.position]\n : positionMap[\"bottom-right\"];\n\n const base =\n \"tvw-fixed tvw-flex tvw-items-center tvw-gap-3 tvw-rounded-launcher tvw-bg-cw-surface tvw-py-2.5 tvw-pl-3 tvw-pr-3 tvw-shadow-lg tvw-border tvw-border-gray-200 tvw-transition hover:tvw-translate-y-[-2px] tvw-cursor-pointer tvw-z-50\";\n\n button.className = `${base} ${positionClass}`;\n };\n\n const destroy = () => {\n button.removeEventListener(\"click\", onToggle);\n button.remove();\n };\n\n // Initial update\n if (config) {\n update(config);\n }\n\n return {\n element: button,\n update,\n destroy\n };\n};\n\n\n","import { createElement } from \"../utils/dom\";\nimport { renderLucideIcon } from \"../utils/icons\";\nimport { AgentWidgetConfig } from \"../types\";\nimport { positionMap } from \"../utils/positioning\";\n\nexport interface PanelWrapper {\n wrapper: HTMLElement;\n panel: HTMLElement;\n}\n\nexport const createWrapper = (config?: AgentWidgetConfig): PanelWrapper => {\n const launcherEnabled = config?.launcher?.enabled ?? true;\n\n if (!launcherEnabled) {\n const wrapper = createElement(\n \"div\",\n \"tvw-relative tvw-w-full tvw-h-full\"\n );\n const panel = createElement(\n \"div\",\n \"tvw-relative tvw-w-full tvw-h-full tvw-min-h-[360px]\"\n );\n wrapper.appendChild(panel);\n return { wrapper, panel };\n }\n\n const launcher = config?.launcher ?? {};\n const position =\n launcher.position && positionMap[launcher.position]\n ? positionMap[launcher.position]\n : positionMap[\"bottom-right\"];\n\n const wrapper = createElement(\n \"div\",\n `tvw-fixed ${position} tvw-z-50 tvw-transition`\n );\n\n const panel = createElement(\n \"div\",\n \"tvw-relative tvw-min-h-[320px]\"\n );\n const launcherWidth = config?.launcher?.width ?? config?.launcherWidth;\n const width = launcherWidth ?? \"min(400px, calc(100vw - 24px))\";\n panel.style.width = width;\n panel.style.maxWidth = width;\n\n wrapper.appendChild(panel);\n return { wrapper, panel };\n};\n\nexport interface PanelElements {\n container: HTMLElement;\n body: HTMLElement;\n messagesWrapper: HTMLElement;\n suggestions: HTMLElement;\n textarea: HTMLTextAreaElement;\n sendButton: HTMLButtonElement;\n sendButtonWrapper: HTMLElement;\n micButton: HTMLButtonElement | null;\n micButtonWrapper: HTMLElement | null;\n composerForm: HTMLFormElement;\n statusText: HTMLElement;\n introTitle: HTMLElement;\n introSubtitle: HTMLElement;\n closeButton: HTMLButtonElement;\n closeButtonWrapper: HTMLElement;\n clearChatButton: HTMLButtonElement | null;\n clearChatButtonWrapper: HTMLElement | null;\n iconHolder: HTMLElement;\n headerTitle: HTMLElement;\n headerSubtitle: HTMLElement;\n}\n\nexport const buildPanel = (config?: AgentWidgetConfig, showClose = true): PanelElements => {\n const container = createElement(\n \"div\",\n \"tvw-flex tvw-h-full tvw-w-full tvw-flex-col tvw-bg-cw-surface tvw-text-cw-primary tvw-rounded-2xl tvw-overflow-hidden tvw-shadow-2xl tvw-border tvw-border-cw-border\"\n );\n\n const header = createElement(\n \"div\",\n \"tvw-flex tvw-items-center tvw-gap-3 tvw-bg-cw-surface tvw-px-6 tvw-py-5 tvw-border-b-cw-divider\"\n );\n\n const launcher = config?.launcher ?? {};\n const headerIconSize = launcher.headerIconSize ?? \"48px\";\n const closeButtonSize = launcher.closeButtonSize ?? \"32px\";\n const closeButtonPlacement = launcher.closeButtonPlacement ?? \"inline\";\n const headerIconHidden = launcher.headerIconHidden ?? false;\n const headerIconName = launcher.headerIconName;\n\n const iconHolder = createElement(\n \"div\",\n \"tvw-flex tvw-items-center tvw-justify-center tvw-rounded-xl tvw-bg-cw-primary tvw-text-white tvw-text-xl\"\n );\n iconHolder.style.height = headerIconSize;\n iconHolder.style.width = headerIconSize;\n \n // Render icon based on priority: Lucide icon > iconUrl > agentIconText\n if (!headerIconHidden) {\n if (headerIconName) {\n // Use Lucide icon\n const iconSize = parseFloat(headerIconSize) || 24;\n const iconSvg = renderLucideIcon(headerIconName, iconSize * 0.6, \"#ffffff\", 2);\n if (iconSvg) {\n iconHolder.replaceChildren(iconSvg);\n } else {\n // Fallback to agentIconText if Lucide icon fails\n iconHolder.textContent = config?.launcher?.agentIconText ?? \"💬\";\n }\n } else if (config?.launcher?.iconUrl) {\n // Use image URL\n const img = createElement(\"img\") as HTMLImageElement;\n img.src = config.launcher.iconUrl;\n img.alt = \"\";\n img.className = \"tvw-rounded-xl tvw-object-cover\";\n img.style.height = headerIconSize;\n img.style.width = headerIconSize;\n iconHolder.replaceChildren(img);\n } else {\n // Use text/emoji\n iconHolder.textContent = config?.launcher?.agentIconText ?? \"💬\";\n }\n }\n\n const headerCopy = createElement(\"div\", \"tvw-flex tvw-flex-col\");\n const title = createElement(\n \"span\",\n \"tvw-text-base tvw-font-semibold\"\n );\n title.textContent =\n config?.launcher?.title ?? \"Chat Assistant\";\n const subtitle = createElement(\n \"span\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n subtitle.textContent =\n config?.launcher?.subtitle ?? \"Here to help you get answers fast\";\n\n headerCopy.append(title, subtitle);\n \n // Only append iconHolder if not hidden\n if (!headerIconHidden) {\n header.append(iconHolder, headerCopy);\n } else {\n header.append(headerCopy);\n }\n\n // Create clear chat button if enabled\n const clearChatConfig = launcher.clearChat ?? {};\n const clearChatEnabled = clearChatConfig.enabled ?? true;\n let clearChatButton: HTMLButtonElement | null = null;\n let clearChatButtonWrapper: HTMLElement | null = null;\n\n if (clearChatEnabled) {\n const clearChatSize = clearChatConfig.size ?? \"32px\";\n const clearChatIconName = clearChatConfig.iconName ?? \"refresh-cw\";\n const clearChatIconColor = clearChatConfig.iconColor ?? \"\";\n const clearChatBgColor = clearChatConfig.backgroundColor ?? \"\";\n const clearChatBorderWidth = clearChatConfig.borderWidth ?? \"\";\n const clearChatBorderColor = clearChatConfig.borderColor ?? \"\";\n const clearChatBorderRadius = clearChatConfig.borderRadius ?? \"\";\n const clearChatPaddingX = clearChatConfig.paddingX ?? \"\";\n const clearChatPaddingY = clearChatConfig.paddingY ?? \"\";\n const clearChatTooltipText = clearChatConfig.tooltipText ?? \"Clear chat\";\n const clearChatShowTooltip = clearChatConfig.showTooltip ?? true;\n\n // Create button wrapper for tooltip\n clearChatButtonWrapper = createElement(\n \"div\",\n \"tvw-relative tvw-ml-auto tvw-clear-chat-button-wrapper\"\n );\n\n clearChatButton = createElement(\n \"button\",\n \"tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n\n clearChatButton.style.height = clearChatSize;\n clearChatButton.style.width = clearChatSize;\n clearChatButton.type = \"button\";\n clearChatButton.setAttribute(\"aria-label\", clearChatTooltipText);\n\n // Add icon\n const iconSvg = renderLucideIcon(clearChatIconName, \"20px\", clearChatIconColor || \"\", 2);\n if (iconSvg) {\n clearChatButton.appendChild(iconSvg);\n }\n\n // Apply styling from config\n if (clearChatIconColor) {\n clearChatButton.style.color = clearChatIconColor;\n clearChatButton.classList.remove(\"tvw-text-cw-muted\");\n }\n\n if (clearChatBgColor) {\n clearChatButton.style.backgroundColor = clearChatBgColor;\n clearChatButton.classList.remove(\"hover:tvw-bg-gray-100\");\n }\n\n if (clearChatBorderWidth || clearChatBorderColor) {\n const borderWidth = clearChatBorderWidth || \"0px\";\n const borderColor = clearChatBorderColor || \"transparent\";\n clearChatButton.style.border = `${borderWidth} solid ${borderColor}`;\n clearChatButton.classList.remove(\"tvw-border-none\");\n }\n\n if (clearChatBorderRadius) {\n clearChatButton.style.borderRadius = clearChatBorderRadius;\n clearChatButton.classList.remove(\"tvw-rounded-full\");\n }\n\n // Apply padding styling\n if (clearChatPaddingX) {\n clearChatButton.style.paddingLeft = clearChatPaddingX;\n clearChatButton.style.paddingRight = clearChatPaddingX;\n } else {\n clearChatButton.style.paddingLeft = \"\";\n clearChatButton.style.paddingRight = \"\";\n }\n if (clearChatPaddingY) {\n clearChatButton.style.paddingTop = clearChatPaddingY;\n clearChatButton.style.paddingBottom = clearChatPaddingY;\n } else {\n clearChatButton.style.paddingTop = \"\";\n clearChatButton.style.paddingBottom = \"\";\n }\n\n clearChatButtonWrapper.appendChild(clearChatButton);\n\n // Add tooltip with portaling to document.body to escape overflow clipping\n if (clearChatShowTooltip && clearChatTooltipText && clearChatButton && clearChatButtonWrapper) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip || !clearChatButton) return; // Already showing or button doesn't exist\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = clearChatTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = clearChatButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n clearChatButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n clearChatButton.addEventListener(\"focus\", showTooltip);\n clearChatButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the button for later use\n (clearChatButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n if (clearChatButtonWrapper) {\n clearChatButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n }\n if (clearChatButton) {\n clearChatButton.removeEventListener(\"focus\", showTooltip);\n clearChatButton.removeEventListener(\"blur\", hideTooltip);\n }\n };\n }\n\n header.appendChild(clearChatButtonWrapper);\n }\n\n // Create close button wrapper for tooltip positioning\n const closeButtonWrapper = createElement(\n \"div\",\n closeButtonPlacement === \"top-right\"\n ? \"tvw-absolute tvw-top-4 tvw-right-4 tvw-z-50\"\n : (clearChatEnabled\n ? \"\"\n : \"tvw-ml-auto\")\n );\n\n // Create close button with base classes\n const closeButton = createElement(\n \"button\",\n \"tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n closeButton.style.height = closeButtonSize;\n closeButton.style.width = closeButtonSize;\n closeButton.type = \"button\";\n\n // Get tooltip config\n const closeButtonTooltipText = launcher.closeButtonTooltipText ?? \"Close chat\";\n const closeButtonShowTooltip = launcher.closeButtonShowTooltip ?? true;\n\n closeButton.setAttribute(\"aria-label\", closeButtonTooltipText);\n closeButton.style.display = showClose ? \"\" : \"none\";\n\n // Add icon or fallback text\n const closeButtonIconName = launcher.closeButtonIconName ?? \"x\";\n const closeButtonIconText = launcher.closeButtonIconText ?? \"×\";\n\n // Try to render Lucide icon, fallback to text if not provided or fails\n const iconSvg = renderLucideIcon(closeButtonIconName, \"20px\", launcher.closeButtonColor || \"\", 2);\n if (iconSvg) {\n closeButton.appendChild(iconSvg);\n } else {\n closeButton.textContent = closeButtonIconText;\n }\n \n // Apply close button styling from config\n if (launcher.closeButtonColor) {\n closeButton.style.color = launcher.closeButtonColor;\n closeButton.classList.remove(\"tvw-text-cw-muted\");\n } else {\n closeButton.style.color = \"\";\n closeButton.classList.add(\"tvw-text-cw-muted\");\n }\n \n if (launcher.closeButtonBackgroundColor) {\n closeButton.style.backgroundColor = launcher.closeButtonBackgroundColor;\n closeButton.classList.remove(\"hover:tvw-bg-gray-100\");\n } else {\n closeButton.style.backgroundColor = \"\";\n closeButton.classList.add(\"hover:tvw-bg-gray-100\");\n }\n \n // Apply border if width and/or color are provided\n if (launcher.closeButtonBorderWidth || launcher.closeButtonBorderColor) {\n const borderWidth = launcher.closeButtonBorderWidth || \"0px\";\n const borderColor = launcher.closeButtonBorderColor || \"transparent\";\n closeButton.style.border = `${borderWidth} solid ${borderColor}`;\n closeButton.classList.remove(\"tvw-border-none\");\n } else {\n closeButton.style.border = \"\";\n closeButton.classList.add(\"tvw-border-none\");\n }\n \n if (launcher.closeButtonBorderRadius) {\n closeButton.style.borderRadius = launcher.closeButtonBorderRadius;\n closeButton.classList.remove(\"tvw-rounded-full\");\n } else {\n closeButton.style.borderRadius = \"\";\n closeButton.classList.add(\"tvw-rounded-full\");\n }\n\n // Apply padding styling\n if (launcher.closeButtonPaddingX) {\n closeButton.style.paddingLeft = launcher.closeButtonPaddingX;\n closeButton.style.paddingRight = launcher.closeButtonPaddingX;\n } else {\n closeButton.style.paddingLeft = \"\";\n closeButton.style.paddingRight = \"\";\n }\n if (launcher.closeButtonPaddingY) {\n closeButton.style.paddingTop = launcher.closeButtonPaddingY;\n closeButton.style.paddingBottom = launcher.closeButtonPaddingY;\n } else {\n closeButton.style.paddingTop = \"\";\n closeButton.style.paddingBottom = \"\";\n }\n\n closeButtonWrapper.appendChild(closeButton);\n\n // Add tooltip with portaling to document.body to escape overflow clipping\n if (closeButtonShowTooltip && closeButtonTooltipText) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip) return; // Already showing\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = closeButtonTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = closeButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n closeButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n closeButton.addEventListener(\"focus\", showTooltip);\n closeButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the wrapper for later use\n (closeButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n closeButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n closeButton.removeEventListener(\"focus\", showTooltip);\n closeButton.removeEventListener(\"blur\", hideTooltip);\n };\n }\n\n // Position close button wrapper based on placement\n if (closeButtonPlacement === \"top-right\") {\n // Make container position relative for absolute positioning\n container.style.position = \"relative\";\n container.appendChild(closeButtonWrapper);\n } else {\n // Inline placement: append to header\n header.appendChild(closeButtonWrapper);\n }\n\n const body = createElement(\n \"div\",\n \"tvw-flex tvw-flex-1 tvw-min-h-0 tvw-flex-col tvw-gap-6 tvw-overflow-y-auto tvw-bg-cw-container tvw-px-6 tvw-py-6\"\n );\n body.id = \"vanilla-agent-scroll-container\";\n const introCard = createElement(\n \"div\",\n \"tvw-rounded-2xl tvw-bg-cw-surface tvw-p-6 tvw-shadow-sm\"\n );\n const introTitle = createElement(\n \"h2\",\n \"tvw-text-lg tvw-font-semibold tvw-text-cw-primary\"\n );\n introTitle.textContent = config?.copy?.welcomeTitle ?? \"Hello 👋\";\n const introSubtitle = createElement(\n \"p\",\n \"tvw-mt-2 tvw-text-sm tvw-text-cw-muted\"\n );\n introSubtitle.textContent =\n config?.copy?.welcomeSubtitle ??\n \"Ask anything about your account or products.\";\n introCard.append(introTitle, introSubtitle);\n\n const messagesWrapper = createElement(\n \"div\",\n \"tvw-flex tvw-flex-col tvw-gap-3\"\n );\n\n body.append(introCard, messagesWrapper);\n\n const footer = createElement(\n \"div\",\n \"tvw-border-t-cw-divider tvw-bg-cw-surface tvw-px-6 tvw-py-4\"\n );\n const suggestions = createElement(\n \"div\",\n \"tvw-mb-3 tvw-flex tvw-flex-wrap tvw-gap-2\"\n );\n // Determine gap based on voice recognition\n const voiceRecognitionEnabledForGap = config?.voiceRecognition?.enabled === true;\n const hasSpeechRecognitionForGap = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n const shouldUseSmallGap = voiceRecognitionEnabledForGap && hasSpeechRecognitionForGap;\n const gapClass = shouldUseSmallGap ? \"tvw-gap-1\" : \"tvw-gap-3\";\n \n const composerForm = createElement(\n \"form\",\n `tvw-flex tvw-items-end ${gapClass} tvw-rounded-2xl tvw-border tvw-border-gray-200 tvw-bg-cw-input-background tvw-px-4 tvw-py-3`\n ) as HTMLFormElement;\n // Prevent form from getting focus styles\n composerForm.style.outline = \"none\";\n \n const textarea = createElement(\"textarea\") as HTMLTextAreaElement;\n textarea.placeholder = config?.copy?.inputPlaceholder ?? \"Type your message…\";\n textarea.className =\n \"tvw-min-h-[48px] tvw-flex-1 tvw-resize-none tvw-border-none tvw-bg-transparent tvw-text-sm tvw-text-cw-primary focus:tvw-outline-none focus:tvw-border-none\";\n textarea.rows = 1;\n \n // Apply font family and weight from config\n const fontFamily = config?.theme?.inputFontFamily ?? \"sans-serif\";\n const fontWeight = config?.theme?.inputFontWeight ?? \"400\";\n \n const getFontFamilyValue = (family: \"sans-serif\" | \"serif\" | \"mono\"): string => {\n switch (family) {\n case \"serif\":\n return 'Georgia, \"Times New Roman\", Times, serif';\n case \"mono\":\n return '\"Courier New\", Courier, \"Lucida Console\", Monaco, monospace';\n case \"sans-serif\":\n default:\n return '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif';\n }\n };\n \n textarea.style.fontFamily = getFontFamilyValue(fontFamily);\n textarea.style.fontWeight = fontWeight;\n \n // Explicitly remove border and outline on focus to prevent browser defaults\n textarea.style.border = \"none\";\n textarea.style.outline = \"none\";\n textarea.style.borderWidth = \"0\";\n textarea.style.borderStyle = \"none\";\n textarea.style.borderColor = \"transparent\";\n textarea.addEventListener(\"focus\", () => {\n textarea.style.border = \"none\";\n textarea.style.outline = \"none\";\n textarea.style.borderWidth = \"0\";\n textarea.style.borderStyle = \"none\";\n textarea.style.borderColor = \"transparent\";\n textarea.style.boxShadow = \"none\";\n });\n textarea.addEventListener(\"blur\", () => {\n textarea.style.border = \"none\";\n textarea.style.outline = \"none\";\n });\n // Send button configuration\n const sendButtonConfig = config?.sendButton ?? {};\n const useIcon = sendButtonConfig.useIcon ?? false;\n const iconText = sendButtonConfig.iconText ?? \"↑\";\n const iconName = sendButtonConfig.iconName;\n const tooltipText = sendButtonConfig.tooltipText ?? \"Send message\";\n const showTooltip = sendButtonConfig.showTooltip ?? false;\n const buttonSize = sendButtonConfig.size ?? \"40px\";\n const backgroundColor = sendButtonConfig.backgroundColor;\n const textColor = sendButtonConfig.textColor;\n\n // Create wrapper for tooltip positioning\n const sendButtonWrapper = createElement(\"div\", \"tvw-send-button-wrapper\");\n\n const sendButton = createElement(\n \"button\",\n useIcon \n ? \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\"\n : \"tvw-rounded-button tvw-bg-cw-accent tvw-px-4 tvw-py-2 tvw-text-sm tvw-font-semibold disabled:tvw-opacity-50 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n\n sendButton.type = \"submit\";\n\n if (useIcon) {\n // Icon mode: circular button\n sendButton.style.width = buttonSize;\n sendButton.style.height = buttonSize;\n sendButton.style.minWidth = buttonSize;\n sendButton.style.minHeight = buttonSize;\n sendButton.style.fontSize = \"18px\";\n sendButton.style.lineHeight = \"1\";\n \n // Clear any existing content\n sendButton.innerHTML = \"\";\n \n // Use Lucide icon if iconName is provided, otherwise fall back to iconText\n if (iconName) {\n const iconSize = parseFloat(buttonSize) || 24;\n const iconColor = textColor && typeof textColor === 'string' && textColor.trim() ? textColor.trim() : \"currentColor\";\n const iconSvg = renderLucideIcon(iconName, iconSize, iconColor, 2);\n if (iconSvg) {\n sendButton.appendChild(iconSvg);\n sendButton.style.color = iconColor;\n } else {\n // Fallback to text if icon fails to render\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n } else {\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n \n if (backgroundColor) {\n sendButton.style.backgroundColor = backgroundColor;\n } else {\n sendButton.classList.add(\"tvw-bg-cw-primary\");\n }\n } else {\n // Text mode: existing behavior\n sendButton.textContent = config?.copy?.sendButtonLabel ?? \"Send\";\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n \n // Apply existing styling from config\n if (sendButtonConfig.borderWidth) {\n sendButton.style.borderWidth = sendButtonConfig.borderWidth;\n sendButton.style.borderStyle = \"solid\";\n }\n if (sendButtonConfig.borderColor) {\n sendButton.style.borderColor = sendButtonConfig.borderColor;\n }\n \n // Apply padding styling (works in both icon and text mode)\n if (sendButtonConfig.paddingX) {\n sendButton.style.paddingLeft = sendButtonConfig.paddingX;\n sendButton.style.paddingRight = sendButtonConfig.paddingX;\n } else {\n sendButton.style.paddingLeft = \"\";\n sendButton.style.paddingRight = \"\";\n }\n if (sendButtonConfig.paddingY) {\n sendButton.style.paddingTop = sendButtonConfig.paddingY;\n sendButton.style.paddingBottom = sendButtonConfig.paddingY;\n } else {\n sendButton.style.paddingTop = \"\";\n sendButton.style.paddingBottom = \"\";\n }\n\n // Add tooltip if enabled\n if (showTooltip && tooltipText) {\n const tooltip = createElement(\"div\", \"tvw-send-button-tooltip\");\n tooltip.textContent = tooltipText;\n sendButtonWrapper.appendChild(tooltip);\n }\n\n sendButtonWrapper.appendChild(sendButton);\n \n // Voice recognition mic button\n const voiceRecognitionConfig = config?.voiceRecognition ?? {};\n const voiceRecognitionEnabled = voiceRecognitionConfig.enabled === true;\n let micButton: HTMLButtonElement | null = null;\n let micButtonWrapper: HTMLElement | null = null;\n \n // Check browser support for speech recognition\n const hasSpeechRecognition = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n \n if (voiceRecognitionEnabled && hasSpeechRecognition) {\n micButtonWrapper = createElement(\"div\", \"tvw-send-button-wrapper\");\n micButton = createElement(\n \"button\",\n \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n \n micButton.type = \"button\";\n micButton.setAttribute(\"aria-label\", \"Start voice recognition\");\n \n const micIconName = voiceRecognitionConfig.iconName ?? \"mic\";\n const micIconSize = voiceRecognitionConfig.iconSize ?? buttonSize;\n const micIconSizeNum = parseFloat(micIconSize) || 24;\n \n // Use dedicated colors from voice recognition config, fallback to send button colors\n const micBackgroundColor = voiceRecognitionConfig.backgroundColor ?? backgroundColor;\n const micIconColor = voiceRecognitionConfig.iconColor ?? textColor;\n \n micButton.style.width = micIconSize;\n micButton.style.height = micIconSize;\n micButton.style.minWidth = micIconSize;\n micButton.style.minHeight = micIconSize;\n micButton.style.fontSize = \"18px\";\n micButton.style.lineHeight = \"1\";\n \n // Use Lucide mic icon with configured color (stroke width 1.5 for minimalist outline style)\n const iconColorValue = micIconColor || \"currentColor\";\n const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColorValue, 1.5);\n if (micIconSvg) {\n micButton.appendChild(micIconSvg);\n micButton.style.color = iconColorValue;\n } else {\n // Fallback to text if icon fails\n micButton.textContent = \"🎤\";\n micButton.style.color = iconColorValue;\n }\n \n // Apply background color\n if (micBackgroundColor) {\n micButton.style.backgroundColor = micBackgroundColor;\n } else {\n micButton.classList.add(\"tvw-bg-cw-primary\");\n }\n \n // Apply icon/text color\n if (micIconColor) {\n micButton.style.color = micIconColor;\n } else if (!micIconColor && !textColor) {\n micButton.classList.add(\"tvw-text-white\");\n }\n \n // Apply border styling\n if (voiceRecognitionConfig.borderWidth) {\n micButton.style.borderWidth = voiceRecognitionConfig.borderWidth;\n micButton.style.borderStyle = \"solid\";\n }\n if (voiceRecognitionConfig.borderColor) {\n micButton.style.borderColor = voiceRecognitionConfig.borderColor;\n }\n \n // Apply padding styling\n if (voiceRecognitionConfig.paddingX) {\n micButton.style.paddingLeft = voiceRecognitionConfig.paddingX;\n micButton.style.paddingRight = voiceRecognitionConfig.paddingX;\n }\n if (voiceRecognitionConfig.paddingY) {\n micButton.style.paddingTop = voiceRecognitionConfig.paddingY;\n micButton.style.paddingBottom = voiceRecognitionConfig.paddingY;\n }\n \n micButtonWrapper.appendChild(micButton);\n \n // Add tooltip if enabled\n const tooltipText = voiceRecognitionConfig.tooltipText ?? \"Start voice recognition\";\n const showTooltip = voiceRecognitionConfig.showTooltip ?? false;\n if (showTooltip && tooltipText) {\n const tooltip = createElement(\"div\", \"tvw-send-button-tooltip\");\n tooltip.textContent = tooltipText;\n micButtonWrapper.appendChild(tooltip);\n }\n }\n \n // Focus textarea when composer form container is clicked\n composerForm.addEventListener(\"click\", (e) => {\n // Don't focus if clicking on the send button, mic button, or their wrappers\n if (e.target !== sendButton && e.target !== sendButtonWrapper && \n e.target !== micButton && e.target !== micButtonWrapper) {\n textarea.focus();\n }\n });\n \n // Append elements: textarea, mic button (if exists), send button\n composerForm.append(textarea);\n if (micButtonWrapper) {\n composerForm.append(micButtonWrapper);\n }\n composerForm.append(sendButtonWrapper);\n\n const statusText = createElement(\n \"div\",\n \"tvw-mt-2 tvw-text-right tvw-text-xs tvw-text-cw-muted\"\n );\n \n // Apply status indicator config\n const statusConfig = config?.statusIndicator ?? {};\n const isVisible = statusConfig.visible ?? true;\n statusText.style.display = isVisible ? \"\" : \"none\";\n statusText.textContent = statusConfig.idleText ?? \"Online\";\n\n footer.append(suggestions, composerForm, statusText);\n\n container.append(header, body, footer);\n\n return {\n container,\n body,\n messagesWrapper,\n suggestions,\n textarea,\n sendButton,\n sendButtonWrapper,\n micButton,\n micButtonWrapper,\n composerForm,\n statusText,\n introTitle,\n introSubtitle,\n closeButton,\n closeButtonWrapper,\n clearChatButton,\n clearChatButtonWrapper,\n iconHolder,\n headerTitle: title,\n headerSubtitle: subtitle\n };\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage } from \"../types\";\n\nexport type MessageTransform = (context: {\n text: string;\n message: AgentWidgetMessage;\n streaming: boolean;\n raw?: string;\n}) => string;\n\n// Create typing indicator element\nexport const createTypingIndicator = (): HTMLElement => {\n const container = document.createElement(\"div\");\n container.className = \"tvw-flex tvw-items-center tvw-space-x-1 tvw-h-5 tvw-mt-2\";\n\n const dot1 = document.createElement(\"div\");\n dot1.className = \"tvw-bg-cw-primary tvw-animate-typing tvw-rounded-full tvw-h-1.5 tvw-w-1.5\";\n dot1.style.animationDelay = \"0ms\";\n\n const dot2 = document.createElement(\"div\");\n dot2.className = \"tvw-bg-cw-primary tvw-animate-typing tvw-rounded-full tvw-h-1.5 tvw-w-1.5\";\n dot2.style.animationDelay = \"250ms\";\n\n const dot3 = document.createElement(\"div\");\n dot3.className = \"tvw-bg-cw-primary tvw-animate-typing tvw-rounded-full tvw-h-1.5 tvw-w-1.5\";\n dot3.style.animationDelay = \"500ms\";\n\n const srOnly = document.createElement(\"span\");\n srOnly.className = \"tvw-sr-only\";\n srOnly.textContent = \"Loading\";\n\n container.appendChild(dot1);\n container.appendChild(dot2);\n container.appendChild(dot3);\n container.appendChild(srOnly);\n\n return container;\n};\n\nexport const createStandardBubble = (\n message: AgentWidgetMessage,\n transform: MessageTransform\n): HTMLElement => {\n const classes = [\n \"vanilla-message-bubble\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-text-sm\",\n \"tvw-leading-relaxed\",\n \"tvw-shadow-sm\"\n ];\n\n if (message.role === \"user\") {\n classes.push(\n \"vanilla-message-user-bubble\",\n \"tvw-ml-auto\",\n \"tvw-bg-cw-accent\",\n \"tvw-text-white\",\n \"tvw-px-5\",\n \"tvw-py-3\"\n );\n } else {\n classes.push(\n \"vanilla-message-assistant-bubble\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-px-5\",\n \"tvw-py-3\"\n );\n }\n\n const bubble = createElement(\"div\", classes.join(\" \"));\n\n // Add message content\n const contentDiv = document.createElement(\"div\");\n contentDiv.innerHTML = transform({\n text: message.content,\n message,\n streaming: Boolean(message.streaming),\n raw: message.rawContent\n });\n bubble.appendChild(contentDiv);\n\n // Add typing indicator if this is a streaming assistant message\n // Show it when streaming starts (even if content is empty), hide it once content appears\n if (message.streaming && message.role === \"assistant\") {\n // Only show typing indicator if content is empty or just starting\n // Hide it once we have substantial content\n if (!message.content || !message.content.trim()) {\n const typingIndicator = createTypingIndicator();\n bubble.appendChild(typingIndicator);\n }\n }\n\n return bubble;\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage } from \"../types\";\nimport { describeReasonStatus } from \"../utils/formatting\";\nimport { renderLucideIcon } from \"../utils/icons\";\n\n// Expansion state per widget instance\nconst reasoningExpansionState = new Set<string>();\n\nexport const createReasoningBubble = (message: AgentWidgetMessage): HTMLElement => {\n const reasoning = message.reasoning;\n const bubble = createElement(\n \"div\",\n [\n \"vanilla-message-bubble\",\n \"vanilla-reasoning-bubble\",\n \"tvw-w-full\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-shadow-sm\",\n \"tvw-overflow-hidden\",\n \"tvw-px-0\",\n \"tvw-py-0\"\n ].join(\" \")\n );\n\n if (!reasoning) {\n return bubble;\n }\n\n let expanded = reasoningExpansionState.has(message.id);\n const header = createElement(\n \"button\",\n \"tvw-flex tvw-w-full tvw-items-center tvw-justify-between tvw-gap-3 tvw-bg-transparent tvw-px-4 tvw-py-3 tvw-text-left tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n header.type = \"button\";\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n\n const headerContent = createElement(\"div\", \"tvw-flex tvw-flex-col tvw-text-left\");\n const title = createElement(\"span\", \"tvw-text-xs tvw-text-cw-primary\");\n title.textContent = \"Thinking...\";\n headerContent.appendChild(title);\n\n const status = createElement(\"span\", \"tvw-text-xs tvw-text-cw-primary\");\n status.textContent = describeReasonStatus(reasoning);\n headerContent.appendChild(status);\n\n if (reasoning.status === \"complete\") {\n title.style.display = \"none\";\n } else {\n title.style.display = \"\";\n }\n\n const toggleIcon = createElement(\"div\", \"tvw-flex tvw-items-center\");\n const iconColor = \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n\n const headerMeta = createElement(\"div\", \"tvw-flex tvw-items-center tvw-ml-auto\");\n headerMeta.append(toggleIcon);\n\n header.append(headerContent, headerMeta);\n\n const content = createElement(\n \"div\",\n \"tvw-border-t tvw-border-gray-200 tvw-bg-gray-50 tvw-px-4 tvw-py-3\"\n );\n content.style.display = expanded ? \"\" : \"none\";\n\n const text = reasoning.chunks.join(\"\");\n const body = createElement(\n \"div\",\n \"tvw-whitespace-pre-wrap tvw-text-xs tvw-leading-snug tvw-text-cw-muted\"\n );\n body.textContent =\n text ||\n (reasoning.status === \"complete\"\n ? \"No additional context was shared.\"\n : \"Waiting for details…\");\n content.appendChild(body);\n\n const applyExpansionState = () => {\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n // Update chevron icon\n toggleIcon.innerHTML = \"\";\n const iconColor = \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n content.style.display = expanded ? \"\" : \"none\";\n };\n\n const toggleExpansion = () => {\n expanded = !expanded;\n if (expanded) {\n reasoningExpansionState.add(message.id);\n } else {\n reasoningExpansionState.delete(message.id);\n }\n applyExpansionState();\n };\n\n header.addEventListener(\"pointerdown\", (event) => {\n event.preventDefault();\n toggleExpansion();\n });\n\n header.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n toggleExpansion();\n }\n });\n\n applyExpansionState();\n\n bubble.append(header, content);\n return bubble;\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage, AgentWidgetConfig } from \"../types\";\nimport { formatUnknownValue, describeToolTitle } from \"../utils/formatting\";\nimport { renderLucideIcon } from \"../utils/icons\";\n\n// Expansion state per widget instance\nconst toolExpansionState = new Set<string>();\n\nexport const createToolBubble = (message: AgentWidgetMessage, config?: AgentWidgetConfig): HTMLElement => {\n const tool = message.toolCall;\n const toolCallConfig = config?.toolCall ?? {};\n \n const bubble = createElement(\n \"div\",\n [\n \"vanilla-message-bubble\",\n \"vanilla-tool-bubble\",\n \"tvw-w-full\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-shadow-sm\",\n \"tvw-overflow-hidden\",\n \"tvw-px-0\",\n \"tvw-py-0\"\n ].join(\" \")\n );\n\n // Apply bubble-level styles\n if (toolCallConfig.backgroundColor) {\n bubble.style.backgroundColor = toolCallConfig.backgroundColor;\n }\n if (toolCallConfig.borderColor) {\n bubble.style.borderColor = toolCallConfig.borderColor;\n }\n if (toolCallConfig.borderWidth) {\n bubble.style.borderWidth = toolCallConfig.borderWidth;\n }\n if (toolCallConfig.borderRadius) {\n bubble.style.borderRadius = toolCallConfig.borderRadius;\n }\n\n if (!tool) {\n return bubble;\n }\n\n let expanded = toolExpansionState.has(message.id);\n const header = createElement(\n \"button\",\n \"tvw-flex tvw-w-full tvw-items-center tvw-justify-between tvw-gap-3 tvw-bg-transparent tvw-px-4 tvw-py-3 tvw-text-left tvw-cursor-pointer tvw-border-none\"\n ) as HTMLButtonElement;\n header.type = \"button\";\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n\n // Apply header styles\n if (toolCallConfig.headerBackgroundColor) {\n header.style.backgroundColor = toolCallConfig.headerBackgroundColor;\n }\n if (toolCallConfig.headerPaddingX) {\n header.style.paddingLeft = toolCallConfig.headerPaddingX;\n header.style.paddingRight = toolCallConfig.headerPaddingX;\n }\n if (toolCallConfig.headerPaddingY) {\n header.style.paddingTop = toolCallConfig.headerPaddingY;\n header.style.paddingBottom = toolCallConfig.headerPaddingY;\n }\n\n const headerContent = createElement(\"div\", \"tvw-flex tvw-flex-col tvw-text-left\");\n const title = createElement(\"span\", \"tvw-text-xs tvw-text-cw-primary\");\n if (toolCallConfig.headerTextColor) {\n title.style.color = toolCallConfig.headerTextColor;\n }\n title.textContent = describeToolTitle(tool);\n headerContent.appendChild(title);\n\n const toggleIcon = createElement(\"div\", \"tvw-flex tvw-items-center\");\n const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n\n const headerMeta = createElement(\"div\", \"tvw-flex tvw-items-center tvw-gap-2 tvw-ml-auto\");\n headerMeta.append(toggleIcon);\n\n header.append(headerContent, headerMeta);\n\n const content = createElement(\n \"div\",\n \"tvw-border-t tvw-border-gray-200 tvw-bg-gray-50 tvw-space-y-3 tvw-px-4 tvw-py-3\"\n );\n content.style.display = expanded ? \"\" : \"none\";\n\n // Apply content styles\n if (toolCallConfig.contentBackgroundColor) {\n content.style.backgroundColor = toolCallConfig.contentBackgroundColor;\n }\n if (toolCallConfig.contentTextColor) {\n content.style.color = toolCallConfig.contentTextColor;\n }\n if (toolCallConfig.contentPaddingX) {\n content.style.paddingLeft = toolCallConfig.contentPaddingX;\n content.style.paddingRight = toolCallConfig.contentPaddingX;\n }\n if (toolCallConfig.contentPaddingY) {\n content.style.paddingTop = toolCallConfig.contentPaddingY;\n content.style.paddingBottom = toolCallConfig.contentPaddingY;\n }\n\n // Add tool name at the top of content\n if (tool.name) {\n const toolName = createElement(\"div\", \"tvw-text-xs tvw-text-cw-muted tvw-italic\");\n if (toolCallConfig.contentTextColor) {\n toolName.style.color = toolCallConfig.contentTextColor;\n } else if (toolCallConfig.headerTextColor) {\n toolName.style.color = toolCallConfig.headerTextColor;\n }\n toolName.textContent = tool.name;\n content.appendChild(toolName);\n }\n\n if (tool.args !== undefined) {\n const argsBlock = createElement(\"div\", \"tvw-space-y-1\");\n const argsLabel = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.labelTextColor) {\n argsLabel.style.color = toolCallConfig.labelTextColor;\n }\n argsLabel.textContent = \"Arguments\";\n const argsPre = createElement(\n \"pre\",\n \"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary\"\n );\n // Ensure font size matches header text (0.75rem / 12px)\n argsPre.style.fontSize = \"0.75rem\";\n argsPre.style.lineHeight = \"1rem\";\n if (toolCallConfig.codeBlockBackgroundColor) {\n argsPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;\n }\n if (toolCallConfig.codeBlockBorderColor) {\n argsPre.style.borderColor = toolCallConfig.codeBlockBorderColor;\n }\n if (toolCallConfig.codeBlockTextColor) {\n argsPre.style.color = toolCallConfig.codeBlockTextColor;\n }\n argsPre.textContent = formatUnknownValue(tool.args);\n argsBlock.append(argsLabel, argsPre);\n content.appendChild(argsBlock);\n }\n\n if (tool.chunks && tool.chunks.length) {\n const logsBlock = createElement(\"div\", \"tvw-space-y-1\");\n const logsLabel = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.labelTextColor) {\n logsLabel.style.color = toolCallConfig.labelTextColor;\n }\n logsLabel.textContent = \"Activity\";\n const logsPre = createElement(\n \"pre\",\n \"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary\"\n );\n // Ensure font size matches header text (0.75rem / 12px)\n logsPre.style.fontSize = \"0.75rem\";\n logsPre.style.lineHeight = \"1rem\";\n if (toolCallConfig.codeBlockBackgroundColor) {\n logsPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;\n }\n if (toolCallConfig.codeBlockBorderColor) {\n logsPre.style.borderColor = toolCallConfig.codeBlockBorderColor;\n }\n if (toolCallConfig.codeBlockTextColor) {\n logsPre.style.color = toolCallConfig.codeBlockTextColor;\n }\n logsPre.textContent = tool.chunks.join(\"\\n\");\n logsBlock.append(logsLabel, logsPre);\n content.appendChild(logsBlock);\n }\n\n if (tool.status === \"complete\" && tool.result !== undefined) {\n const resultBlock = createElement(\"div\", \"tvw-space-y-1\");\n const resultLabel = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.labelTextColor) {\n resultLabel.style.color = toolCallConfig.labelTextColor;\n }\n resultLabel.textContent = \"Result\";\n const resultPre = createElement(\n \"pre\",\n \"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary\"\n );\n // Ensure font size matches header text (0.75rem / 12px)\n resultPre.style.fontSize = \"0.75rem\";\n resultPre.style.lineHeight = \"1rem\";\n if (toolCallConfig.codeBlockBackgroundColor) {\n resultPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;\n }\n if (toolCallConfig.codeBlockBorderColor) {\n resultPre.style.borderColor = toolCallConfig.codeBlockBorderColor;\n }\n if (toolCallConfig.codeBlockTextColor) {\n resultPre.style.color = toolCallConfig.codeBlockTextColor;\n }\n resultPre.textContent = formatUnknownValue(tool.result);\n resultBlock.append(resultLabel, resultPre);\n content.appendChild(resultBlock);\n }\n\n if (tool.status === \"complete\" && typeof tool.duration === \"number\") {\n const duration = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted\"\n );\n if (toolCallConfig.contentTextColor) {\n duration.style.color = toolCallConfig.contentTextColor;\n }\n duration.textContent = `Duration: ${tool.duration}ms`;\n content.appendChild(duration);\n }\n\n const applyToolExpansion = () => {\n header.setAttribute(\"aria-expanded\", expanded ? \"true\" : \"false\");\n // Update chevron icon\n toggleIcon.innerHTML = \"\";\n const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || \"currentColor\";\n const chevronIcon = renderLucideIcon(expanded ? \"chevron-up\" : \"chevron-down\", 16, iconColor, 2);\n if (chevronIcon) {\n toggleIcon.appendChild(chevronIcon);\n } else {\n // Fallback to text if icon fails\n toggleIcon.textContent = expanded ? \"Hide\" : \"Show\";\n }\n content.style.display = expanded ? \"\" : \"none\";\n };\n\n const toggleToolExpansion = () => {\n expanded = !expanded;\n if (expanded) {\n toolExpansionState.add(message.id);\n } else {\n toolExpansionState.delete(message.id);\n }\n applyToolExpansion();\n };\n\n header.addEventListener(\"pointerdown\", (event) => {\n event.preventDefault();\n toggleToolExpansion();\n });\n\n header.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n toggleToolExpansion();\n }\n });\n\n applyToolExpansion();\n\n bubble.append(header, content);\n return bubble;\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetSession } from \"../session\";\nimport { AgentWidgetMessage, AgentWidgetSuggestionChipsConfig } from \"../types\";\n\nexport interface SuggestionButtons {\n buttons: HTMLButtonElement[];\n render: (\n chips: string[] | undefined,\n session: AgentWidgetSession,\n textarea: HTMLTextAreaElement,\n messages?: AgentWidgetMessage[],\n config?: AgentWidgetSuggestionChipsConfig\n ) => void;\n}\n\nexport const createSuggestions = (container: HTMLElement): SuggestionButtons => {\n const suggestionButtons: HTMLButtonElement[] = [];\n\n const render = (\n chips: string[] | undefined,\n session: AgentWidgetSession,\n textarea: HTMLTextAreaElement,\n messages?: AgentWidgetMessage[],\n chipsConfig?: AgentWidgetSuggestionChipsConfig\n ) => {\n container.innerHTML = \"\";\n suggestionButtons.length = 0;\n if (!chips || !chips.length) return;\n\n // Hide suggestions after the first user message is sent\n // Use provided messages or get from session\n const messagesToCheck = messages ?? (session ? session.getMessages() : []);\n const hasUserMessage = messagesToCheck.some((msg) => msg.role === \"user\");\n if (hasUserMessage) return;\n\n const fragment = document.createDocumentFragment();\n const streaming = session ? session.isStreaming() : false;\n\n // Get font family mapping function\n const getFontFamilyValue = (family: \"sans-serif\" | \"serif\" | \"mono\"): string => {\n switch (family) {\n case \"serif\":\n return 'Georgia, \"Times New Roman\", Times, serif';\n case \"mono\":\n return '\"Courier New\", Courier, \"Lucida Console\", Monaco, monospace';\n case \"sans-serif\":\n default:\n return '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif';\n }\n };\n\n chips.forEach((chip) => {\n const btn = createElement(\n \"button\",\n \"tvw-rounded-button tvw-bg-cw-surface tvw-px-3 tvw-py-1.5 tvw-text-xs tvw-font-medium tvw-text-cw-muted hover:tvw-opacity-90 tvw-cursor-pointer tvw-border tvw-border-gray-200\"\n ) as HTMLButtonElement;\n btn.type = \"button\";\n btn.textContent = chip;\n btn.disabled = streaming;\n\n // Apply typography settings\n if (chipsConfig?.fontFamily) {\n btn.style.fontFamily = getFontFamilyValue(chipsConfig.fontFamily);\n }\n if (chipsConfig?.fontWeight) {\n btn.style.fontWeight = chipsConfig.fontWeight;\n }\n\n // Apply padding settings\n if (chipsConfig?.paddingX) {\n btn.style.paddingLeft = chipsConfig.paddingX;\n btn.style.paddingRight = chipsConfig.paddingX;\n }\n if (chipsConfig?.paddingY) {\n btn.style.paddingTop = chipsConfig.paddingY;\n btn.style.paddingBottom = chipsConfig.paddingY;\n }\n\n btn.addEventListener(\"click\", () => {\n if (!session || session.isStreaming()) return;\n textarea.value = \"\";\n session.sendMessage(chip);\n });\n fragment.appendChild(btn);\n suggestionButtons.push(btn);\n });\n container.appendChild(fragment);\n };\n\n return {\n buttons: suggestionButtons,\n render\n };\n};\n\n\n\n","import { createElement } from \"../utils/dom\";\nimport { AgentWidgetMessage, AgentWidgetConfig } from \"../types\";\nimport { AgentWidgetSession } from \"../session\";\n\nexport const formDefinitions: Record<\n string,\n {\n title: string;\n description?: string;\n fields: Array<{\n name: string;\n label: string;\n placeholder?: string;\n type?: \"text\" | \"email\" | \"textarea\";\n required?: boolean;\n }>;\n submitLabel?: string;\n }\n> = {\n init: {\n title: \"Schedule a Demo\",\n description: \"Share the basics and we'll follow up with a confirmation.\",\n fields: [\n { name: \"name\", label: \"Full name\", placeholder: \"Jane Doe\", required: true },\n { name: \"email\", label: \"Work email\", placeholder: \"jane@example.com\", type: \"email\", required: true },\n { name: \"notes\", label: \"What would you like to cover?\", type: \"textarea\" }\n ],\n submitLabel: \"Submit details\"\n },\n followup: {\n title: \"Additional Information\",\n description: \"Provide any extra details to tailor the next steps.\",\n fields: [\n { name: \"company\", label: \"Company\", placeholder: \"Acme Inc.\" },\n { name: \"context\", label: \"Context\", type: \"textarea\", placeholder: \"Share more about your use case\" }\n ],\n submitLabel: \"Send\"\n }\n};\n\nexport const enhanceWithForms = (\n bubble: HTMLElement,\n message: AgentWidgetMessage,\n config: AgentWidgetConfig,\n session: AgentWidgetSession\n) => {\n const placeholders = bubble.querySelectorAll<HTMLElement>(\"[data-tv-form]\");\n if (placeholders.length) {\n placeholders.forEach((placeholder) => {\n if (placeholder.dataset.enhanced === \"true\") return;\n const type = placeholder.dataset.tvForm ?? \"init\";\n placeholder.dataset.enhanced = \"true\";\n\n const definition = formDefinitions[type] ?? formDefinitions.init;\n placeholder.classList.add(\"tvw-form-card\", \"tvw-space-y-4\");\n\n const heading = createElement(\"div\", \"tvw-space-y-1\");\n const title = createElement(\n \"h3\",\n \"tvw-text-base tvw-font-semibold tvw-text-cw-primary\"\n );\n title.textContent = definition.title;\n heading.appendChild(title);\n if (definition.description) {\n const desc = createElement(\n \"p\",\n \"tvw-text-sm tvw-text-cw-muted\"\n );\n desc.textContent = definition.description;\n heading.appendChild(desc);\n }\n\n const form = document.createElement(\"form\");\n form.className = \"tvw-form-grid tvw-space-y-3\";\n\n definition.fields.forEach((field) => {\n const group = createElement(\"label\", \"tvw-form-field tvw-flex tvw-flex-col tvw-gap-1\");\n group.htmlFor = `${message.id}-${type}-${field.name}`;\n const label = createElement(\"span\", \"tvw-text-xs tvw-font-medium tvw-text-cw-muted\");\n label.textContent = field.label;\n group.appendChild(label);\n\n const inputType = field.type ?? \"text\";\n let control: HTMLInputElement | HTMLTextAreaElement;\n if (inputType === \"textarea\") {\n control = document.createElement(\"textarea\");\n control.rows = 3;\n } else {\n control = document.createElement(\"input\");\n control.type = inputType;\n }\n control.className =\n \"tvw-rounded-xl tvw-border tvw-border-gray-200 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-sm tvw-text-cw-primary focus:tvw-outline-none focus:tvw-border-cw-primary\";\n control.id = `${message.id}-${type}-${field.name}`;\n control.name = field.name;\n control.placeholder = field.placeholder ?? \"\";\n if (field.required) {\n control.required = true;\n }\n group.appendChild(control);\n form.appendChild(group);\n });\n\n const actions = createElement(\n \"div\",\n \"tvw-flex tvw-items-center tvw-justify-between tvw-gap-2\"\n );\n const status = createElement(\n \"div\",\n \"tvw-text-xs tvw-text-cw-muted tvw-min-h-[1.5rem]\"\n );\n const submit = createElement(\n \"button\",\n \"tvw-inline-flex tvw-items-center tvw-rounded-full tvw-bg-cw-primary tvw-px-4 tvw-py-2 tvw-text-sm tvw-font-semibold tvw-text-white disabled:tvw-opacity-60 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n submit.type = \"submit\";\n submit.textContent = definition.submitLabel ?? \"Submit\";\n actions.appendChild(status);\n actions.appendChild(submit);\n form.appendChild(actions);\n\n placeholder.replaceChildren(heading, form);\n\n form.addEventListener(\"submit\", async (event) => {\n event.preventDefault();\n const formEndpoint = config.formEndpoint ?? \"/form\";\n const formData = new FormData(form as HTMLFormElement);\n const payload: Record<string, unknown> = {};\n formData.forEach((value, key) => {\n payload[key] = value;\n });\n payload[\"type\"] = type;\n\n submit.disabled = true;\n status.textContent = \"Submitting…\";\n\n try {\n const response = await fetch(formEndpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(payload)\n });\n if (!response.ok) {\n throw new Error(`Form submission failed (${response.status})`);\n }\n const data = await response.json();\n status.textContent = data.message ?? \"Thanks! We'll be in touch soon.\";\n if (data.success && data.nextPrompt) {\n await session.sendMessage(String(data.nextPrompt));\n }\n } catch (error) {\n status.textContent =\n error instanceof Error ? error.message : \"Something went wrong. Please try again.\";\n } finally {\n submit.disabled = false;\n }\n });\n });\n }\n};\n\n\n\n\n\n\n\n\n","import { AgentWidgetPlugin } from \"./types\";\n\nclass PluginRegistry {\n private plugins: Map<string, AgentWidgetPlugin> = new Map();\n\n /**\n * Register a plugin\n */\n register(plugin: AgentWidgetPlugin): void {\n if (this.plugins.has(plugin.id)) {\n console.warn(`Plugin \"${plugin.id}\" is already registered. Overwriting.`);\n }\n\n this.plugins.set(plugin.id, plugin);\n plugin.onRegister?.();\n }\n\n /**\n * Unregister a plugin\n */\n unregister(pluginId: string): void {\n const plugin = this.plugins.get(pluginId);\n if (plugin) {\n plugin.onUnregister?.();\n this.plugins.delete(pluginId);\n }\n }\n\n /**\n * Get all plugins sorted by priority\n */\n getAll(): AgentWidgetPlugin[] {\n return Array.from(this.plugins.values()).sort(\n (a, b) => (b.priority ?? 0) - (a.priority ?? 0)\n );\n }\n\n /**\n * Get plugins for a specific instance (from config)\n * Merges instance plugins with globally registered plugins\n */\n getForInstance(instancePlugins?: AgentWidgetPlugin[]): AgentWidgetPlugin[] {\n const allPlugins = this.getAll();\n\n if (!instancePlugins || instancePlugins.length === 0) {\n return allPlugins;\n }\n\n // Merge instance plugins with global plugins\n // Instance plugins override global plugins with the same ID\n const instanceIds = new Set(instancePlugins.map(p => p.id));\n const merged = [\n ...allPlugins.filter(p => !instanceIds.has(p.id)),\n ...instancePlugins\n ];\n\n return merged.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n }\n\n /**\n * Clear all plugins\n */\n clear(): void {\n this.plugins.forEach(plugin => plugin.onUnregister?.());\n this.plugins.clear();\n }\n}\n\nexport const pluginRegistry = new PluginRegistry();\n\n\n\n\n\n\n\n\n","import type { AgentWidgetConfig } from \"./types\";\n\n/**\n * Default widget configuration\n * Single source of truth for all default values\n */\nexport const DEFAULT_WIDGET_CONFIG: Partial<AgentWidgetConfig> = {\n apiUrl: \"http://localhost:43111/api/chat/dispatch\",\n theme: {\n primary: \"#111827\",\n accent: \"#1d4ed8\",\n surface: \"#ffffff\",\n muted: \"#6b7280\",\n container: \"#f8fafc\",\n border: \"#f1f5f9\",\n divider: \"#f1f5f9\",\n messageBorder: \"#f1f5f9\",\n inputBackground: \"#ffffff\",\n callToAction: \"#000000\",\n callToActionBackground: \"#ffffff\",\n sendButtonBackgroundColor: \"#111827\",\n sendButtonTextColor: \"#ffffff\",\n sendButtonBorderColor: \"#60a5fa\",\n closeButtonColor: \"#6b7280\",\n closeButtonBackgroundColor: \"transparent\",\n closeButtonBorderColor: \"\",\n clearChatIconColor: \"#6b7280\",\n clearChatBackgroundColor: \"transparent\",\n clearChatBorderColor: \"transparent\",\n micIconColor: \"#111827\",\n micBackgroundColor: \"transparent\",\n micBorderColor: \"transparent\",\n recordingIconColor: \"#ffffff\",\n recordingBackgroundColor: \"#ef4444\",\n recordingBorderColor: \"transparent\",\n inputFontFamily: \"sans-serif\",\n inputFontWeight: \"400\",\n radiusSm: \"0.75rem\",\n radiusMd: \"1rem\",\n radiusLg: \"1.5rem\",\n launcherRadius: \"9999px\",\n buttonRadius: \"9999px\",\n },\n launcher: {\n enabled: true,\n title: \"Chat Assistant\",\n subtitle: \"Here to help you get answers fast\",\n agentIconText: \"💬\",\n position: \"bottom-right\",\n width: \"min(400px, calc(100vw - 24px))\",\n autoExpand: false,\n callToActionIconHidden: false,\n agentIconSize: \"40px\",\n headerIconSize: \"40px\",\n closeButtonSize: \"32px\",\n callToActionIconName: \"arrow-up-right\",\n callToActionIconText: \"\",\n callToActionIconSize: \"32px\",\n callToActionIconPadding: \"5px\",\n callToActionIconColor: \"#000000\",\n callToActionIconBackgroundColor: \"#ffffff\",\n closeButtonColor: \"#6b7280\",\n closeButtonBackgroundColor: \"transparent\",\n clearChat: {\n iconColor: \"#6b7280\",\n backgroundColor: \"transparent\",\n borderColor: \"transparent\",\n enabled: true,\n iconName: \"refresh-cw\",\n size: \"29px\",\n showTooltip: true,\n tooltipText: \"Clear chat\",\n paddingX: \"0px\",\n paddingY: \"0px\",\n },\n headerIconHidden: false,\n },\n copy: {\n welcomeTitle: \"Hello 👋\",\n welcomeSubtitle: \"Ask anything about your account or products.\",\n inputPlaceholder: \"How can I help...\",\n sendButtonLabel: \"Send\",\n },\n sendButton: {\n borderWidth: \"0px\",\n paddingX: \"12px\",\n paddingY: \"10px\",\n backgroundColor: \"#111827\",\n textColor: \"#ffffff\",\n borderColor: \"#60a5fa\",\n useIcon: true,\n iconText: \"↑\",\n size: \"40px\",\n showTooltip: true,\n tooltipText: \"Send message\",\n iconName: \"send\",\n },\n statusIndicator: {\n visible: true,\n idleText: \"Online\",\n connectingText: \"Connecting…\",\n connectedText: \"Streaming…\",\n errorText: \"Offline\",\n },\n voiceRecognition: {\n enabled: true,\n pauseDuration: 2000,\n iconName: \"mic\",\n iconSize: \"39px\",\n borderWidth: \"0px\",\n paddingX: \"9px\",\n paddingY: \"14px\",\n iconColor: \"#111827\",\n backgroundColor: \"transparent\",\n borderColor: \"transparent\",\n recordingIconColor: \"#ffffff\",\n recordingBackgroundColor: \"#ef4444\",\n recordingBorderColor: \"transparent\",\n showTooltip: true,\n tooltipText: \"Start voice recognition\",\n },\n features: {\n showReasoning: true,\n showToolCalls: true,\n },\n suggestionChips: [\n \"What can you help me with?\",\n \"Tell me about your features\",\n \"How does this work?\",\n ],\n suggestionChipsConfig: {\n fontFamily: \"sans-serif\",\n fontWeight: \"500\",\n paddingX: \"12px\",\n paddingY: \"6px\",\n },\n debug: false,\n};\n\n/**\n * Helper to deep merge user config with defaults\n * This ensures all default values are present while allowing selective overrides\n */\nexport function mergeWithDefaults(\n config?: Partial<AgentWidgetConfig>\n): Partial<AgentWidgetConfig> {\n if (!config) return DEFAULT_WIDGET_CONFIG;\n\n return {\n ...DEFAULT_WIDGET_CONFIG,\n ...config,\n theme: {\n ...DEFAULT_WIDGET_CONFIG.theme,\n ...config.theme,\n },\n launcher: {\n ...DEFAULT_WIDGET_CONFIG.launcher,\n ...config.launcher,\n clearChat: {\n ...DEFAULT_WIDGET_CONFIG.launcher?.clearChat,\n ...config.launcher?.clearChat,\n },\n },\n copy: {\n ...DEFAULT_WIDGET_CONFIG.copy,\n ...config.copy,\n },\n sendButton: {\n ...DEFAULT_WIDGET_CONFIG.sendButton,\n ...config.sendButton,\n },\n statusIndicator: {\n ...DEFAULT_WIDGET_CONFIG.statusIndicator,\n ...config.statusIndicator,\n },\n voiceRecognition: {\n ...DEFAULT_WIDGET_CONFIG.voiceRecognition,\n ...config.voiceRecognition,\n },\n features: {\n ...DEFAULT_WIDGET_CONFIG.features,\n ...config.features,\n },\n suggestionChips: config.suggestionChips ?? DEFAULT_WIDGET_CONFIG.suggestionChips,\n suggestionChipsConfig: {\n ...DEFAULT_WIDGET_CONFIG.suggestionChipsConfig,\n ...config.suggestionChipsConfig,\n },\n };\n}\n","type Handler<T> = (payload: T) => void;\n\nexport type EventUnsubscribe = () => void;\n\nexport const createEventBus = <EventMap extends Record<string, any>>() => {\n const listeners = new Map<keyof EventMap, Set<Handler<any>>>();\n\n const on = <K extends keyof EventMap>(\n event: K,\n handler: Handler<EventMap[K]>\n ): EventUnsubscribe => {\n if (!listeners.has(event)) {\n listeners.set(event, new Set());\n }\n listeners.get(event)!.add(handler as Handler<any>);\n return () => off(event, handler);\n };\n\n const off = <K extends keyof EventMap>(\n event: K,\n handler: Handler<EventMap[K]>\n ) => {\n listeners.get(event)?.delete(handler as Handler<any>);\n };\n\n const emit = <K extends keyof EventMap>(event: K, payload: EventMap[K]) => {\n listeners.get(event)?.forEach((handler) => {\n try {\n handler(payload);\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Event handler error:\", error);\n }\n }\n });\n };\n\n return { on, off, emit };\n};\n\n","import type {\n AgentWidgetActionContext,\n AgentWidgetActionEventPayload,\n AgentWidgetActionHandler,\n AgentWidgetActionHandlerResult,\n AgentWidgetActionParser,\n AgentWidgetParsedAction,\n AgentWidgetControllerEventMap,\n AgentWidgetMessage\n} from \"../types\";\n\ntype ActionManagerProcessContext = {\n text: string;\n message: AgentWidgetMessage;\n streaming: boolean;\n raw?: string;\n};\n\ntype ActionManagerOptions = {\n parsers: AgentWidgetActionParser[];\n handlers: AgentWidgetActionHandler[];\n getMetadata: () => Record<string, unknown>;\n updateMetadata: (\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) => void;\n emit: <K extends keyof AgentWidgetControllerEventMap>(\n event: K,\n payload: AgentWidgetControllerEventMap[K]\n ) => void;\n documentRef: Document | null;\n};\n\nconst stripCodeFence = (value: string) => {\n const match = value.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n return match ? match[1] : value;\n};\n\nconst extractJsonObject = (value: string) => {\n const trimmed = value.trim();\n const start = trimmed.indexOf(\"{\");\n if (start === -1) return null;\n\n let depth = 0;\n for (let i = start; i < trimmed.length; i += 1) {\n const char = trimmed[i];\n if (char === \"{\") depth += 1;\n if (char === \"}\") {\n depth -= 1;\n if (depth === 0) {\n return trimmed.slice(start, i + 1);\n }\n }\n }\n return null;\n};\n\nexport const defaultJsonActionParser: AgentWidgetActionParser = ({ text }) => {\n if (!text) return null;\n if (!text.includes(\"{\")) return null;\n\n try {\n const withoutFence = stripCodeFence(text);\n const jsonBody = extractJsonObject(withoutFence);\n if (!jsonBody) return null;\n const parsed = JSON.parse(jsonBody);\n if (!parsed || typeof parsed !== \"object\" || !parsed.action) {\n return null;\n }\n const { action, ...payload } = parsed;\n return {\n type: String(action),\n payload,\n raw: parsed\n };\n } catch {\n return null;\n }\n};\n\nconst asString = (value: unknown) =>\n typeof value === \"string\" ? value : value == null ? \"\" : String(value);\n\nexport const defaultActionHandlers: Record<\n string,\n AgentWidgetActionHandler\n> = {\n message: (action) => {\n if (action.type !== \"message\") return;\n const text = asString((action.payload as Record<string, unknown>).text);\n return {\n handled: true,\n displayText: text\n };\n },\n messageAndClick: (action, context) => {\n if (action.type !== \"message_and_click\") return;\n const payload = action.payload as Record<string, unknown>;\n const selector = asString(payload.element);\n if (selector && context.document?.querySelector) {\n const element = context.document.querySelector<HTMLElement>(selector);\n if (element) {\n setTimeout(() => {\n element.click();\n }, 400);\n } else if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.warn(\"[AgentWidget] Element not found for selector:\", selector);\n }\n }\n return {\n handled: true,\n displayText: asString(payload.text)\n };\n }\n};\n\nconst ensureArrayOfStrings = (value: unknown): string[] => {\n if (Array.isArray(value)) {\n return value.map((entry) => String(entry));\n }\n return [];\n};\n\nexport const createActionManager = (options: ActionManagerOptions) => {\n let processedIds = new Set(\n ensureArrayOfStrings(options.getMetadata().processedActionMessageIds)\n );\n\n const syncFromMetadata = () => {\n processedIds = new Set(\n ensureArrayOfStrings(options.getMetadata().processedActionMessageIds)\n );\n };\n\n const persistProcessedIds = () => {\n const latestIds = Array.from(processedIds);\n options.updateMetadata((prev) => ({\n ...prev,\n processedActionMessageIds: latestIds\n }));\n };\n\n const process = (context: ActionManagerProcessContext): { text: string; persist: boolean } | null => {\n if (\n context.streaming ||\n context.message.role !== \"assistant\" ||\n !context.text ||\n processedIds.has(context.message.id)\n ) {\n return null;\n }\n\n const parseSource =\n (typeof context.raw === \"string\" && context.raw) ||\n (typeof context.message.rawContent === \"string\" &&\n context.message.rawContent) ||\n (typeof context.text === \"string\" && context.text) ||\n null;\n\n if (\n !parseSource &&\n typeof context.text === \"string\" &&\n context.text.trim().startsWith(\"{\") &&\n typeof console !== \"undefined\"\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n \"[AgentWidget] Structured response detected but no raw payload was provided. Ensure your stream parser returns { text, raw }.\"\n );\n }\n\n const action = parseSource\n ? options.parsers.reduce<AgentWidgetParsedAction | null>(\n (acc, parser) =>\n acc || parser?.({ text: parseSource, message: context.message }) || null,\n null\n )\n : null;\n\n if (!action) {\n return null;\n }\n\n processedIds.add(context.message.id);\n persistProcessedIds();\n\n const eventPayload: AgentWidgetActionEventPayload = {\n action,\n message: context.message\n };\n options.emit(\"action:detected\", eventPayload);\n\n for (const handler of options.handlers) {\n if (!handler) continue;\n try {\n const handlerResult = handler(action, {\n message: context.message,\n metadata: options.getMetadata(),\n updateMetadata: options.updateMetadata,\n document: options.documentRef\n } as AgentWidgetActionContext) as AgentWidgetActionHandlerResult | void;\n\n if (!handlerResult) continue;\n\n if (handlerResult.handled) {\n // persistMessage defaults to true if not specified\n const persist = handlerResult.persistMessage !== false;\n const displayText = handlerResult.displayText !== undefined ? handlerResult.displayText : \"\";\n return { text: displayText, persist };\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Action handler error:\", error);\n }\n }\n }\n\n return { text: \"\", persist: true };\n };\n\n return {\n process,\n syncFromMetadata\n };\n};\n\n","import type {\n AgentWidgetMessage,\n AgentWidgetStorageAdapter,\n AgentWidgetStoredState\n} from \"../types\";\n\nconst safeJsonParse = (value: string | null) => {\n if (!value) return null;\n try {\n return JSON.parse(value);\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to parse stored state:\", error);\n }\n return null;\n }\n};\n\nconst sanitizeMessages = (messages: AgentWidgetMessage[]) =>\n messages.map((message) => ({\n ...message,\n streaming: false\n }));\n\nexport const createLocalStorageAdapter = (\n key = \"vanilla-agent-state\"\n): AgentWidgetStorageAdapter => {\n const getStorage = () => {\n if (typeof window === \"undefined\" || !window.localStorage) {\n return null;\n }\n return window.localStorage;\n };\n\n return {\n load: () => {\n const storage = getStorage();\n if (!storage) return null;\n return safeJsonParse(storage.getItem(key));\n },\n save: (state: AgentWidgetStoredState) => {\n const storage = getStorage();\n if (!storage) return;\n try {\n const payload: AgentWidgetStoredState = {\n ...state,\n messages: state.messages ? sanitizeMessages(state.messages) : undefined\n };\n storage.setItem(key, JSON.stringify(payload));\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to persist state:\", error);\n }\n }\n },\n clear: () => {\n const storage = getStorage();\n if (!storage) return;\n try {\n storage.removeItem(key);\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear stored state:\", error);\n }\n }\n }\n };\n};\n\n","import { AgentWidgetConfig, AgentWidgetMessage } from \"../types\";\n\n/**\n * Context provided to component renderers\n */\nexport interface ComponentContext {\n message: AgentWidgetMessage;\n config: AgentWidgetConfig;\n /**\n * Update component props during streaming\n */\n updateProps: (newProps: Record<string, unknown>) => void;\n}\n\n/**\n * Component renderer function signature\n */\nexport type ComponentRenderer = (\n props: Record<string, unknown>,\n context: ComponentContext\n) => HTMLElement;\n\n/**\n * Component registry for managing custom components\n */\nclass ComponentRegistry {\n private components: Map<string, ComponentRenderer> = new Map();\n\n /**\n * Register a custom component\n */\n register(name: string, renderer: ComponentRenderer): void {\n if (this.components.has(name)) {\n console.warn(`[ComponentRegistry] Component \"${name}\" is already registered. Overwriting.`);\n }\n this.components.set(name, renderer);\n }\n\n /**\n * Unregister a component\n */\n unregister(name: string): void {\n this.components.delete(name);\n }\n\n /**\n * Get a component renderer by name\n */\n get(name: string): ComponentRenderer | undefined {\n return this.components.get(name);\n }\n\n /**\n * Check if a component is registered\n */\n has(name: string): boolean {\n return this.components.has(name);\n }\n\n /**\n * Get all registered component names\n */\n getAllNames(): string[] {\n return Array.from(this.components.keys());\n }\n\n /**\n * Clear all registered components\n */\n clear(): void {\n this.components.clear();\n }\n\n /**\n * Register multiple components at once\n */\n registerAll(components: Record<string, ComponentRenderer>): void {\n Object.entries(components).forEach(([name, renderer]) => {\n this.register(name, renderer);\n });\n }\n}\n\n/**\n * Global component registry instance\n */\nexport const componentRegistry = new ComponentRegistry();\n","import { parse as parsePartialJson, STR, OBJ } from \"partial-json\";\n\n/**\n * Represents a component directive extracted from JSON\n */\nexport interface ComponentDirective {\n component: string;\n props: Record<string, unknown>;\n raw: string;\n}\n\n/**\n * Checks if a parsed object is a component directive\n */\nfunction isComponentDirective(obj: unknown): obj is { component: string; props?: unknown } {\n if (!obj || typeof obj !== \"object\") return false;\n if (!(\"component\" in obj)) return false;\n const component = (obj as { component: unknown }).component;\n return typeof component === \"string\" && component.length > 0;\n}\n\n/**\n * Extracts component directive from parsed JSON object\n */\nfunction extractComponentDirective(\n parsed: unknown,\n rawJson: string\n): ComponentDirective | null {\n if (!isComponentDirective(parsed)) {\n return null;\n }\n\n const props = parsed.props && typeof parsed.props === \"object\" && parsed.props !== null\n ? (parsed.props as Record<string, unknown>)\n : {};\n\n return {\n component: parsed.component,\n props,\n raw: rawJson\n };\n}\n\n/**\n * Creates a parser that extracts component directives from JSON streams\n * This parser looks for objects with a \"component\" field and extracts\n * the component name and props incrementally as they stream in.\n */\nexport function createComponentStreamParser() {\n let extractedDirective: ComponentDirective | null = null;\n let processedLength = 0;\n\n return {\n /**\n * Get the currently extracted component directive\n */\n getExtractedDirective: (): ComponentDirective | null => {\n return extractedDirective;\n },\n\n /**\n * Process a chunk of JSON and extract component directive if present\n */\n processChunk: (accumulatedContent: string): ComponentDirective | null => {\n // Validate that the accumulated content looks like JSON\n const trimmed = accumulatedContent.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) {\n return null;\n }\n\n // Skip if no new content\n if (accumulatedContent.length <= processedLength) {\n return extractedDirective;\n }\n\n try {\n // Parse partial JSON - allow partial strings and objects during streaming\n // STR | OBJ allows incomplete strings and objects during streaming\n const parsed = parsePartialJson(accumulatedContent, STR | OBJ);\n\n // Try to extract component directive\n const directive = extractComponentDirective(parsed, accumulatedContent);\n if (directive) {\n extractedDirective = directive;\n }\n } catch (error) {\n // If parsing fails completely, keep the last extracted directive\n // This can happen with very malformed JSON during streaming\n }\n\n // Update processed length\n processedLength = accumulatedContent.length;\n\n return extractedDirective;\n },\n\n /**\n * Reset the parser state\n */\n reset: () => {\n extractedDirective = null;\n processedLength = 0;\n }\n };\n}\n\n/**\n * Type guard to check if an object is a component directive\n */\nexport function isComponentDirectiveType(obj: unknown): obj is ComponentDirective {\n return (\n typeof obj === \"object\" &&\n obj !== null &&\n \"component\" in obj &&\n typeof (obj as { component: unknown }).component === \"string\" &&\n \"props\" in obj &&\n typeof (obj as { props: unknown }).props === \"object\"\n );\n}\n","import { AgentWidgetMessage, AgentWidgetConfig } from \"../types\";\nimport { componentRegistry, ComponentContext } from \"../components/registry\";\nimport { ComponentDirective, createComponentStreamParser } from \"./component-parser\";\nimport { createStandardBubble, MessageTransform } from \"../components/message-bubble\";\n\n/**\n * Options for component middleware\n */\nexport interface ComponentMiddlewareOptions {\n config: AgentWidgetConfig;\n message: AgentWidgetMessage;\n transform: MessageTransform;\n onPropsUpdate?: (props: Record<string, unknown>) => void;\n}\n\n/**\n * Renders a component directive into an HTMLElement\n */\nexport function renderComponentDirective(\n directive: ComponentDirective,\n options: ComponentMiddlewareOptions\n): HTMLElement | null {\n const { config, message, onPropsUpdate } = options;\n\n // Get component renderer from registry\n const renderer = componentRegistry.get(directive.component);\n if (!renderer) {\n // Component not found, fall back to default rendering\n console.warn(\n `[ComponentMiddleware] Component \"${directive.component}\" not found in registry. Falling back to default rendering.`\n );\n return null;\n }\n\n // Create component context\n const context: ComponentContext = {\n message,\n config,\n updateProps: (newProps: Record<string, unknown>) => {\n if (onPropsUpdate) {\n onPropsUpdate(newProps);\n }\n }\n };\n\n try {\n // Render the component\n const element = renderer(directive.props, context);\n return element;\n } catch (error) {\n console.error(\n `[ComponentMiddleware] Error rendering component \"${directive.component}\":`,\n error\n );\n return null;\n }\n}\n\n/**\n * Creates middleware that processes component directives from streamed JSON\n */\nexport function createComponentMiddleware() {\n const parser = createComponentStreamParser();\n\n return {\n /**\n * Process accumulated content and extract component directive\n */\n processChunk: (accumulatedContent: string): ComponentDirective | null => {\n return parser.processChunk(accumulatedContent);\n },\n\n /**\n * Get the currently extracted directive\n */\n getDirective: (): ComponentDirective | null => {\n return parser.getExtractedDirective();\n },\n\n /**\n * Reset the parser state\n */\n reset: () => {\n parser.reset();\n }\n };\n}\n\n/**\n * Checks if a message contains a component directive in its raw content\n */\nexport function hasComponentDirective(message: AgentWidgetMessage): boolean {\n if (!message.rawContent) return false;\n \n try {\n const parsed = JSON.parse(message.rawContent);\n return (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"component\" in parsed &&\n typeof parsed.component === \"string\"\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts component directive from a complete message\n */\nexport function extractComponentDirectiveFromMessage(\n message: AgentWidgetMessage\n): ComponentDirective | null {\n if (!message.rawContent) return null;\n\n try {\n const parsed = JSON.parse(message.rawContent);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n \"component\" in parsed &&\n typeof parsed.component === \"string\"\n ) {\n return {\n component: parsed.component,\n props: (parsed.props && typeof parsed.props === \"object\" && parsed.props !== null\n ? parsed.props\n : {}) as Record<string, unknown>,\n raw: message.rawContent\n };\n }\n } catch {\n // Not valid JSON or not a component directive\n }\n\n return null;\n}\n","import { escapeHtml } from \"./postprocessors\";\nimport { AgentWidgetSession, AgentWidgetSessionStatus } from \"./session\";\nimport {\n AgentWidgetConfig,\n AgentWidgetMessage,\n AgentWidgetEvent,\n AgentWidgetStorageAdapter,\n AgentWidgetStoredState,\n AgentWidgetControllerEventMap,\n AgentWidgetVoiceStateEvent,\n AgentWidgetStateEvent,\n AgentWidgetStateSnapshot\n} from \"./types\";\nimport { applyThemeVariables } from \"./utils/theme\";\nimport { renderLucideIcon } from \"./utils/icons\";\nimport { createElement } from \"./utils/dom\";\nimport { statusCopy } from \"./utils/constants\";\nimport { createLauncherButton } from \"./components/launcher\";\nimport { createWrapper, buildPanel } from \"./components/panel\";\nimport { MessageTransform } from \"./components/message-bubble\";\nimport { createStandardBubble, createTypingIndicator } from \"./components/message-bubble\";\nimport { createReasoningBubble } from \"./components/reasoning-bubble\";\nimport { createToolBubble } from \"./components/tool-bubble\";\nimport { createSuggestions } from \"./components/suggestions\";\nimport { enhanceWithForms } from \"./components/forms\";\nimport { pluginRegistry } from \"./plugins/registry\";\nimport { mergeWithDefaults } from \"./defaults\";\nimport { createEventBus } from \"./utils/events\";\nimport {\n createActionManager,\n defaultActionHandlers,\n defaultJsonActionParser\n} from \"./utils/actions\";\nimport { createLocalStorageAdapter } from \"./utils/storage\";\nimport { componentRegistry } from \"./components/registry\";\nimport {\n renderComponentDirective,\n extractComponentDirectiveFromMessage,\n hasComponentDirective\n} from \"./utils/component-middleware\";\n\n// Default localStorage key for chat history (automatically cleared on clear chat)\nconst DEFAULT_CHAT_HISTORY_STORAGE_KEY = \"vanilla-agent-chat-history\";\nconst VOICE_STATE_RESTORE_WINDOW = 30 * 1000;\n\nconst ensureRecord = (value: unknown): Record<string, unknown> => {\n if (!value || typeof value !== \"object\") {\n return {};\n }\n return { ...(value as Record<string, unknown>) };\n};\n\nconst stripStreamingFromMessages = (messages: AgentWidgetMessage[]) =>\n messages.map((message) => ({\n ...message,\n streaming: false\n }));\n\ntype Controller = {\n update: (config: AgentWidgetConfig) => void;\n destroy: () => void;\n open: () => void;\n close: () => void;\n toggle: () => void;\n clearChat: () => void;\n setMessage: (message: string) => boolean;\n submitMessage: (message?: string) => boolean;\n startVoiceRecognition: () => boolean;\n stopVoiceRecognition: () => boolean;\n injectTestMessage: (event: AgentWidgetEvent) => void;\n getMessages: () => AgentWidgetMessage[];\n getStatus: () => AgentWidgetSessionStatus;\n getPersistentMetadata: () => Record<string, unknown>;\n updatePersistentMetadata: (\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) => void;\n on: <K extends keyof AgentWidgetControllerEventMap>(\n event: K,\n handler: (payload: AgentWidgetControllerEventMap[K]) => void\n ) => () => void;\n off: <K extends keyof AgentWidgetControllerEventMap>(\n event: K,\n handler: (payload: AgentWidgetControllerEventMap[K]) => void\n ) => void;\n // State query methods\n isOpen: () => boolean;\n isVoiceActive: () => boolean;\n getState: () => AgentWidgetStateSnapshot;\n};\n\nconst buildPostprocessor = (\n cfg: AgentWidgetConfig | undefined,\n actionManager?: ReturnType<typeof createActionManager>\n): MessageTransform => {\n return (context) => {\n let nextText = context.text ?? \"\";\n const rawPayload = context.message.rawContent ?? null;\n\n if (actionManager) {\n const actionResult = actionManager.process({\n text: nextText,\n raw: rawPayload ?? nextText,\n message: context.message,\n streaming: context.streaming\n });\n if (actionResult !== null) {\n nextText = actionResult.text;\n // Mark message as non-persistable if persist is false\n if (!actionResult.persist) {\n (context.message as any).__skipPersist = true;\n }\n }\n }\n\n if (cfg?.postprocessMessage) {\n return cfg.postprocessMessage({\n ...context,\n text: nextText,\n raw: rawPayload ?? context.text ?? \"\"\n });\n }\n\n return escapeHtml(nextText);\n };\n};\n\nexport const createAgentExperience = (\n mount: HTMLElement,\n initialConfig?: AgentWidgetConfig,\n runtimeOptions?: { debugTools?: boolean }\n): Controller => {\n // Tailwind config uses important: \"#vanilla-agent-root\", so ensure mount has this ID\n if (!mount.id || mount.id !== \"vanilla-agent-root\") {\n mount.id = \"vanilla-agent-root\";\n }\n\n let config = mergeWithDefaults(initialConfig) as AgentWidgetConfig;\n applyThemeVariables(mount, config);\n\n // Get plugins for this instance\n const plugins = pluginRegistry.getForInstance(config.plugins);\n \n // Register components from config\n if (config.components) {\n componentRegistry.registerAll(config.components);\n }\n const eventBus = createEventBus<AgentWidgetControllerEventMap>();\n\n const storageAdapter: AgentWidgetStorageAdapter =\n config.storageAdapter ?? createLocalStorageAdapter();\n let persistentMetadata: Record<string, unknown> = {};\n let pendingStoredState: Promise<AgentWidgetStoredState | null> | null = null;\n\n if (storageAdapter?.load) {\n try {\n const storedState = storageAdapter.load();\n if (storedState && typeof (storedState as Promise<any>).then === \"function\") {\n pendingStoredState = storedState as Promise<AgentWidgetStoredState | null>;\n } else if (storedState) {\n const immediateState = storedState as AgentWidgetStoredState;\n if (immediateState.metadata) {\n persistentMetadata = ensureRecord(immediateState.metadata);\n }\n if (immediateState.messages?.length) {\n config = { ...config, initialMessages: immediateState.messages };\n }\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to load stored state:\", error);\n }\n }\n }\n\n const getMetadata = () => persistentMetadata;\n const updateMetadata = (\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) => {\n const next = updater({ ...persistentMetadata }) ?? {};\n persistentMetadata = next;\n persistState();\n };\n\n const resolvedActionParsers =\n config.actionParsers && config.actionParsers.length\n ? config.actionParsers\n : [defaultJsonActionParser];\n\n const resolvedActionHandlers =\n config.actionHandlers && config.actionHandlers.length\n ? config.actionHandlers\n : [defaultActionHandlers.message, defaultActionHandlers.messageAndClick];\n\n let actionManager = createActionManager({\n parsers: resolvedActionParsers,\n handlers: resolvedActionHandlers,\n getMetadata,\n updateMetadata,\n emit: eventBus.emit,\n documentRef: typeof document !== \"undefined\" ? document : null\n });\n actionManager.syncFromMetadata();\n\n let launcherEnabled = config.launcher?.enabled ?? true;\n let autoExpand = config.launcher?.autoExpand ?? false;\n let prevAutoExpand = autoExpand;\n let prevLauncherEnabled = launcherEnabled;\n let open = launcherEnabled ? autoExpand : true;\n let postprocess = buildPostprocessor(config, actionManager);\n let showReasoning = config.features?.showReasoning ?? true;\n let showToolCalls = config.features?.showToolCalls ?? true;\n \n // Get status indicator config\n const statusConfig = config.statusIndicator ?? {};\n const getStatusText = (status: AgentWidgetSessionStatus): string => {\n if (status === \"idle\") return statusConfig.idleText ?? statusCopy.idle;\n if (status === \"connecting\") return statusConfig.connectingText ?? statusCopy.connecting;\n if (status === \"connected\") return statusConfig.connectedText ?? statusCopy.connected;\n if (status === \"error\") return statusConfig.errorText ?? statusCopy.error;\n return statusCopy[status];\n };\n\n const { wrapper, panel } = createWrapper(config);\n const panelElements = buildPanel(config, launcherEnabled);\n const {\n container,\n body,\n messagesWrapper,\n suggestions,\n textarea,\n sendButton,\n sendButtonWrapper,\n composerForm,\n statusText,\n introTitle,\n introSubtitle,\n closeButton,\n iconHolder,\n headerTitle,\n headerSubtitle\n } = panelElements;\n \n // Use mutable references for mic button so we can update them dynamically\n let micButton: HTMLButtonElement | null = panelElements.micButton;\n let micButtonWrapper: HTMLElement | null = panelElements.micButtonWrapper;\n\n panel.appendChild(container);\n mount.appendChild(wrapper);\n\n const destroyCallbacks: Array<() => void> = [];\n const suggestionsManager = createSuggestions(suggestions);\n let closeHandler: (() => void) | null = null;\n let session: AgentWidgetSession;\n let isStreaming = false;\n let shouldAutoScroll = true;\n let lastScrollTop = 0;\n let lastAutoScrollTime = 0;\n let scrollRAF: number | null = null;\n let isAutoScrollBlocked = false;\n let blockUntilTime = 0;\n let isAutoScrolling = false;\n\n const AUTO_SCROLL_THROTTLE = 125;\n const AUTO_SCROLL_BLOCK_TIME = 2000;\n const USER_SCROLL_THRESHOLD = 5;\n const BOTTOM_THRESHOLD = 50;\n const messageState = new Map<\n string,\n { streaming?: boolean; role: AgentWidgetMessage[\"role\"] }\n >();\n const voiceState = {\n active: false,\n manuallyDeactivated: false,\n lastUserMessageWasVoice: false\n };\n const voiceAutoResumeMode = config.voiceRecognition?.autoResume ?? false;\n const emitVoiceState = (source: AgentWidgetVoiceStateEvent[\"source\"]) => {\n eventBus.emit(\"voice:state\", {\n active: voiceState.active,\n source,\n timestamp: Date.now()\n });\n };\n const persistVoiceMetadata = () => {\n updateMetadata((prev) => ({\n ...prev,\n voiceState: {\n active: voiceState.active,\n timestamp: Date.now(),\n manuallyDeactivated: voiceState.manuallyDeactivated\n }\n }));\n };\n const maybeRestoreVoiceFromMetadata = () => {\n if (config.voiceRecognition?.enabled === false) return;\n const rawVoiceState = ensureRecord((persistentMetadata as any).voiceState);\n const wasActive = Boolean(rawVoiceState.active);\n const timestamp = Number(rawVoiceState.timestamp ?? 0);\n voiceState.manuallyDeactivated = Boolean(rawVoiceState.manuallyDeactivated);\n if (wasActive && Date.now() - timestamp < VOICE_STATE_RESTORE_WINDOW) {\n setTimeout(() => {\n if (!voiceState.active) {\n voiceState.manuallyDeactivated = false;\n startVoiceRecognition(\"restore\");\n }\n }, 1000);\n }\n };\n\n const getMessagesForPersistence = () =>\n session \n ? stripStreamingFromMessages(session.getMessages()).filter(msg => !(msg as any).__skipPersist)\n : [];\n\n function persistState(messagesOverride?: AgentWidgetMessage[]) {\n if (!storageAdapter?.save) return;\n\n // Allow saving even if session doesn't exist yet (for metadata during init)\n const messages = messagesOverride\n ? stripStreamingFromMessages(messagesOverride)\n : session\n ? getMessagesForPersistence()\n : [];\n\n const payload = {\n messages,\n metadata: persistentMetadata\n };\n try {\n const result = storageAdapter.save(payload);\n if (result instanceof Promise) {\n result.catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to persist state:\", error);\n }\n });\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to persist state:\", error);\n }\n }\n }\n\n const scheduleAutoScroll = (force = false) => {\n if (!shouldAutoScroll) return;\n\n const now = Date.now();\n\n if (isAutoScrollBlocked && now < blockUntilTime) {\n if (!force) return;\n }\n\n if (isAutoScrollBlocked && now >= blockUntilTime) {\n isAutoScrollBlocked = false;\n }\n\n if (!force && !isStreaming) return;\n\n if (now - lastAutoScrollTime < AUTO_SCROLL_THROTTLE) return;\n lastAutoScrollTime = now;\n\n if (scrollRAF) {\n cancelAnimationFrame(scrollRAF);\n }\n\n scrollRAF = requestAnimationFrame(() => {\n if (isAutoScrollBlocked || !shouldAutoScroll) return;\n isAutoScrolling = true;\n body.scrollTop = body.scrollHeight;\n lastScrollTop = body.scrollTop;\n requestAnimationFrame(() => {\n isAutoScrolling = false;\n });\n scrollRAF = null;\n });\n };\n\n // Track ongoing smooth scroll animation\n let smoothScrollRAF: number | null = null;\n\n // Get the scrollable container using its unique ID\n const getScrollableContainer = (): HTMLElement => {\n // Use the unique ID for reliable selection\n const scrollable = wrapper.querySelector('#vanilla-agent-scroll-container') as HTMLElement;\n // Fallback to body if ID not found (shouldn't happen, but safe fallback)\n return scrollable || body;\n };\n\n // Custom smooth scroll animation with easing\n const smoothScrollToBottom = (element: HTMLElement, duration = 500) => {\n const start = element.scrollTop;\n const clientHeight = element.clientHeight;\n // Recalculate target dynamically to handle layout changes\n let target = element.scrollHeight;\n let distance = target - start;\n\n // Check if already at bottom: scrollTop + clientHeight should be >= scrollHeight\n // Add a small threshold (2px) to account for rounding/subpixel differences\n const isAtBottom = start + clientHeight >= target - 2;\n \n // If already at bottom or very close, skip animation to prevent glitch\n if (isAtBottom || Math.abs(distance) < 5) {\n return;\n }\n\n // Cancel any ongoing smooth scroll animation\n if (smoothScrollRAF !== null) {\n cancelAnimationFrame(smoothScrollRAF);\n smoothScrollRAF = null;\n }\n\n const startTime = performance.now();\n\n // Easing function: ease-out cubic for smooth deceleration\n const easeOutCubic = (t: number): number => {\n return 1 - Math.pow(1 - t, 3);\n };\n\n const animate = (currentTime: number) => {\n // Recalculate target each frame in case scrollHeight changed\n const currentTarget = element.scrollHeight;\n if (currentTarget !== target) {\n target = currentTarget;\n distance = target - start;\n }\n\n const elapsed = currentTime - startTime;\n const progress = Math.min(elapsed / duration, 1);\n const eased = easeOutCubic(progress);\n \n const currentScroll = start + distance * eased;\n element.scrollTop = currentScroll;\n\n if (progress < 1) {\n smoothScrollRAF = requestAnimationFrame(animate);\n } else {\n // Ensure we end exactly at the target\n element.scrollTop = element.scrollHeight;\n smoothScrollRAF = null;\n }\n };\n\n smoothScrollRAF = requestAnimationFrame(animate);\n };\n\n const trackMessages = (messages: AgentWidgetMessage[]) => {\n const nextState = new Map<\n string,\n { streaming?: boolean; role: AgentWidgetMessage[\"role\"] }\n >();\n\n messages.forEach((message) => {\n const previous = messageState.get(message.id);\n nextState.set(message.id, {\n streaming: message.streaming,\n role: message.role\n });\n\n if (!previous && message.role === \"assistant\") {\n eventBus.emit(\"assistant:message\", message);\n }\n\n if (\n message.role === \"assistant\" &&\n previous?.streaming &&\n message.streaming === false\n ) {\n eventBus.emit(\"assistant:complete\", message);\n }\n });\n\n messageState.clear();\n nextState.forEach((value, key) => {\n messageState.set(key, value);\n });\n };\n\n\n // Message rendering with plugin support\n const renderMessagesWithPlugins = (\n container: HTMLElement,\n messages: AgentWidgetMessage[],\n transform: MessageTransform\n ) => {\n container.innerHTML = \"\";\n const fragment = document.createDocumentFragment();\n\n messages.forEach((message) => {\n let bubble: HTMLElement | null = null;\n\n // Try plugins first\n const matchingPlugin = plugins.find((p) => {\n if (message.variant === \"reasoning\" && p.renderReasoning) {\n return true;\n }\n if (message.variant === \"tool\" && p.renderToolCall) {\n return true;\n }\n if (!message.variant && p.renderMessage) {\n return true;\n }\n return false;\n });\n\n if (matchingPlugin) {\n if (message.variant === \"reasoning\" && message.reasoning && matchingPlugin.renderReasoning) {\n if (!showReasoning) return;\n bubble = matchingPlugin.renderReasoning({\n message,\n defaultRenderer: () => createReasoningBubble(message),\n config\n });\n } else if (message.variant === \"tool\" && message.toolCall && matchingPlugin.renderToolCall) {\n if (!showToolCalls) return;\n bubble = matchingPlugin.renderToolCall({\n message,\n defaultRenderer: () => createToolBubble(message, config),\n config\n });\n } else if (matchingPlugin.renderMessage) {\n bubble = matchingPlugin.renderMessage({\n message,\n defaultRenderer: () => {\n const b = createStandardBubble(message, transform);\n if (message.role !== \"user\") {\n enhanceWithForms(b, message, config, session);\n }\n return b;\n },\n config\n });\n }\n }\n\n // Check for component directive if no plugin handled it\n if (!bubble && message.role === \"assistant\" && !message.variant) {\n const enableComponentStreaming = config.enableComponentStreaming !== false; // Default to true\n if (enableComponentStreaming && hasComponentDirective(message)) {\n const directive = extractComponentDirectiveFromMessage(message);\n if (directive) {\n const componentBubble = renderComponentDirective(directive, {\n config,\n message,\n transform\n });\n if (componentBubble) {\n // Wrap component in standard bubble styling\n const wrapper = document.createElement(\"div\");\n wrapper.className = [\n \"vanilla-message-bubble\",\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-p-4\"\n ].join(\" \");\n wrapper.setAttribute(\"data-message-id\", message.id);\n\n // Add text content above component if present (combined text+component response)\n if (message.content && message.content.trim()) {\n const textDiv = document.createElement(\"div\");\n textDiv.className = \"tvw-mb-3 tvw-text-sm tvw-leading-relaxed\";\n textDiv.innerHTML = transform({\n text: message.content,\n message,\n streaming: Boolean(message.streaming),\n raw: message.rawContent\n });\n wrapper.appendChild(textDiv);\n }\n\n wrapper.appendChild(componentBubble);\n bubble = wrapper;\n }\n }\n }\n }\n\n // Fallback to default rendering if plugin returned null or no plugin matched\n if (!bubble) {\n if (message.variant === \"reasoning\" && message.reasoning) {\n if (!showReasoning) return;\n bubble = createReasoningBubble(message);\n } else if (message.variant === \"tool\" && message.toolCall) {\n if (!showToolCalls) return;\n bubble = createToolBubble(message, config);\n } else {\n bubble = createStandardBubble(message, transform);\n if (message.role !== \"user\") {\n enhanceWithForms(bubble, message, config, session);\n }\n }\n }\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = \"tvw-flex\";\n if (message.role === \"user\") {\n wrapper.classList.add(\"tvw-justify-end\");\n }\n wrapper.appendChild(bubble);\n fragment.appendChild(wrapper);\n });\n\n // Add standalone typing indicator only if streaming but no assistant message is streaming yet\n // (This shows while waiting for the stream to start)\n // Check for ANY streaming assistant message, even if empty (to avoid duplicate bubbles)\n const hasStreamingAssistantMessage = messages.some(\n (msg) => msg.role === \"assistant\" && msg.streaming\n );\n\n if (isStreaming && messages.some((msg) => msg.role === \"user\") && !hasStreamingAssistantMessage) {\n const typingIndicator = createTypingIndicator();\n\n // Create a bubble wrapper for the typing indicator (similar to assistant messages)\n const typingBubble = document.createElement(\"div\");\n typingBubble.className = [\n \"tvw-max-w-[85%]\",\n \"tvw-rounded-2xl\",\n \"tvw-text-sm\",\n \"tvw-leading-relaxed\",\n \"tvw-shadow-sm\",\n \"tvw-bg-cw-surface\",\n \"tvw-border\",\n \"tvw-border-cw-message-border\",\n \"tvw-text-cw-primary\",\n \"tvw-px-5\",\n \"tvw-py-3\"\n ].join(\" \");\n\n typingBubble.appendChild(typingIndicator);\n\n const typingWrapper = document.createElement(\"div\");\n typingWrapper.className = \"tvw-flex\";\n typingWrapper.appendChild(typingBubble);\n fragment.appendChild(typingWrapper);\n }\n\n container.appendChild(fragment);\n // Defer scroll to next frame for smoother animation and to prevent jolt\n // This allows the browser to update layout (e.g., typing indicator removal) before scrolling\n // Use double RAF to ensure layout has fully settled before starting scroll animation\n // Get the scrollable container using its unique ID (#vanilla-agent-scroll-container)\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n const scrollableContainer = getScrollableContainer();\n smoothScrollToBottom(scrollableContainer);\n });\n });\n };\n\n const updateOpenState = () => {\n if (!launcherEnabled) return;\n if (open) {\n wrapper.classList.remove(\"tvw-pointer-events-none\", \"tvw-opacity-0\");\n panel.classList.remove(\"tvw-scale-95\", \"tvw-opacity-0\");\n panel.classList.add(\"tvw-scale-100\", \"tvw-opacity-100\");\n // Hide launcher button when widget is open\n if (launcherButtonInstance) {\n launcherButtonInstance.element.style.display = \"none\";\n }\n } else {\n wrapper.classList.add(\"tvw-pointer-events-none\", \"tvw-opacity-0\");\n panel.classList.remove(\"tvw-scale-100\", \"tvw-opacity-100\");\n panel.classList.add(\"tvw-scale-95\", \"tvw-opacity-0\");\n // Show launcher button when widget is closed\n if (launcherButtonInstance) {\n launcherButtonInstance.element.style.display = \"\";\n }\n }\n };\n\n const setOpenState = (nextOpen: boolean, source: \"user\" | \"auto\" | \"api\" | \"system\" = \"user\") => {\n if (!launcherEnabled) return;\n if (open === nextOpen) return;\n \n const prevOpen = open;\n open = nextOpen;\n updateOpenState();\n \n if (open) {\n recalcPanelHeight();\n scheduleAutoScroll(true);\n }\n \n // Emit widget state events\n const stateEvent: AgentWidgetStateEvent = {\n open,\n source,\n timestamp: Date.now()\n };\n \n if (open && !prevOpen) {\n eventBus.emit(\"widget:opened\", stateEvent);\n } else if (!open && prevOpen) {\n eventBus.emit(\"widget:closed\", stateEvent);\n }\n \n // Emit general state snapshot\n eventBus.emit(\"widget:state\", {\n open,\n launcherEnabled,\n voiceActive: voiceState.active,\n streaming: session.isStreaming()\n });\n };\n\n const setComposerDisabled = (disabled: boolean) => {\n textarea.disabled = disabled;\n sendButton.disabled = disabled;\n if (micButton) {\n micButton.disabled = disabled;\n }\n suggestionsManager.buttons.forEach((btn) => {\n btn.disabled = disabled;\n });\n };\n\n const updateCopy = () => {\n introTitle.textContent = config.copy?.welcomeTitle ?? \"Hello 👋\";\n introSubtitle.textContent =\n config.copy?.welcomeSubtitle ??\n \"Ask anything about your account or products.\";\n textarea.placeholder = config.copy?.inputPlaceholder ?? \"How can I help...\";\n\n // Only update send button text if NOT using icon mode\n const useIcon = config.sendButton?.useIcon ?? false;\n if (!useIcon) {\n sendButton.textContent = config.copy?.sendButtonLabel ?? \"Send\";\n }\n\n // Update textarea font family and weight\n const fontFamily = config.theme?.inputFontFamily ?? \"sans-serif\";\n const fontWeight = config.theme?.inputFontWeight ?? \"400\";\n \n const getFontFamilyValue = (family: \"sans-serif\" | \"serif\" | \"mono\"): string => {\n switch (family) {\n case \"serif\":\n return 'Georgia, \"Times New Roman\", Times, serif';\n case \"mono\":\n return '\"Courier New\", Courier, \"Lucida Console\", Monaco, monospace';\n case \"sans-serif\":\n default:\n return '-apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif';\n }\n };\n \n textarea.style.fontFamily = getFontFamilyValue(fontFamily);\n textarea.style.fontWeight = fontWeight;\n };\n\n session = new AgentWidgetSession(config, {\n onMessagesChanged(messages) {\n renderMessagesWithPlugins(messagesWrapper, messages, postprocess);\n // Re-render suggestions to hide them after first user message\n // Pass messages directly to avoid calling session.getMessages() during construction\n if (session) {\n const hasUserMessage = messages.some((msg) => msg.role === \"user\");\n if (hasUserMessage) {\n // Hide suggestions if user message exists\n suggestionsManager.render([], session, textarea, messages);\n } else {\n // Show suggestions if no user message yet\n suggestionsManager.render(config.suggestionChips, session, textarea, messages, config.suggestionChipsConfig);\n }\n }\n scheduleAutoScroll(!isStreaming);\n trackMessages(messages);\n\n const lastUserMessage = [...messages]\n .reverse()\n .find((msg) => msg.role === \"user\");\n voiceState.lastUserMessageWasVoice = Boolean(lastUserMessage?.viaVoice);\n persistState(messages);\n },\n onStatusChanged(status) {\n const currentStatusConfig = config.statusIndicator ?? {};\n const getCurrentStatusText = (status: AgentWidgetSessionStatus): string => {\n if (status === \"idle\") return currentStatusConfig.idleText ?? statusCopy.idle;\n if (status === \"connecting\") return currentStatusConfig.connectingText ?? statusCopy.connecting;\n if (status === \"connected\") return currentStatusConfig.connectedText ?? statusCopy.connected;\n if (status === \"error\") return currentStatusConfig.errorText ?? statusCopy.error;\n return statusCopy[status];\n };\n statusText.textContent = getCurrentStatusText(status);\n },\n onStreamingChanged(streaming) {\n isStreaming = streaming;\n setComposerDisabled(streaming);\n // Re-render messages to show/hide typing indicator\n if (session) {\n renderMessagesWithPlugins(messagesWrapper, session.getMessages(), postprocess);\n }\n if (!streaming) {\n scheduleAutoScroll(true);\n }\n }\n });\n\n if (pendingStoredState) {\n pendingStoredState\n .then((state) => {\n if (!state) return;\n if (state.metadata) {\n persistentMetadata = ensureRecord(state.metadata);\n actionManager.syncFromMetadata();\n }\n if (state.messages?.length) {\n session.hydrateMessages(state.messages);\n }\n })\n .catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to hydrate stored state:\", error);\n }\n });\n }\n\n const handleSubmit = (event: Event) => {\n event.preventDefault();\n const value = textarea.value.trim();\n if (!value) return;\n textarea.value = \"\";\n session.sendMessage(value);\n };\n\n const handleInputEnter = (event: KeyboardEvent) => {\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n sendButton.click();\n }\n };\n\n // Voice recognition state and logic\n let speechRecognition: any = null;\n let isRecording = false;\n let pauseTimer: number | null = null;\n let originalMicStyles: {\n backgroundColor: string;\n color: string;\n borderColor: string;\n } | null = null;\n\n const getSpeechRecognitionClass = (): any => {\n if (typeof window === 'undefined') return null;\n return (window as any).webkitSpeechRecognition || (window as any).SpeechRecognition || null;\n };\n\n const startVoiceRecognition = (\n source: AgentWidgetVoiceStateEvent[\"source\"] = \"user\"\n ) => {\n if (isRecording || session.isStreaming()) return;\n\n const SpeechRecognitionClass = getSpeechRecognitionClass();\n if (!SpeechRecognitionClass) return;\n\n speechRecognition = new SpeechRecognitionClass();\n const voiceConfig = config.voiceRecognition ?? {};\n const pauseDuration = voiceConfig.pauseDuration ?? 2000;\n\n speechRecognition.continuous = true;\n speechRecognition.interimResults = true;\n speechRecognition.lang = 'en-US';\n\n // Store the initial text that was in the textarea\n const initialText = textarea.value;\n\n speechRecognition.onresult = (event: any) => {\n // Build the complete transcript from all results\n let fullTranscript = \"\";\n let interimTranscript = \"\";\n \n // Process all results from the beginning\n for (let i = 0; i < event.results.length; i++) {\n const result = event.results[i];\n const transcript = result[0].transcript;\n \n if (result.isFinal) {\n fullTranscript += transcript + \" \";\n } else {\n // Only take the last interim result\n interimTranscript = transcript;\n }\n }\n \n // Update textarea with initial text + full transcript + interim\n const newValue = initialText + fullTranscript + interimTranscript;\n textarea.value = newValue;\n\n // Reset pause timer on each result\n if (pauseTimer) {\n clearTimeout(pauseTimer);\n }\n\n // Set timer to auto-submit after pause when we have any speech\n if (fullTranscript || interimTranscript) {\n pauseTimer = window.setTimeout(() => {\n const finalValue = textarea.value.trim();\n if (finalValue && speechRecognition && isRecording) {\n stopVoiceRecognition();\n textarea.value = \"\";\n session.sendMessage(finalValue, { viaVoice: true });\n }\n }, pauseDuration);\n }\n };\n\n speechRecognition.onerror = (event: any) => {\n // Don't stop on \"no-speech\" error, just ignore it\n if (event.error !== 'no-speech') {\n stopVoiceRecognition();\n }\n };\n\n speechRecognition.onend = () => {\n // If recognition ended naturally (not manually stopped), submit if there's text\n if (isRecording) {\n const finalValue = textarea.value.trim();\n if (finalValue && finalValue !== initialText.trim()) {\n textarea.value = \"\";\n session.sendMessage(finalValue, { viaVoice: true });\n }\n stopVoiceRecognition();\n }\n };\n\n try {\n speechRecognition.start();\n isRecording = true;\n voiceState.active = true;\n if (source !== \"system\") {\n voiceState.manuallyDeactivated = false;\n }\n emitVoiceState(source);\n persistVoiceMetadata();\n if (micButton) {\n // Store original styles\n originalMicStyles = {\n backgroundColor: micButton.style.backgroundColor,\n color: micButton.style.color,\n borderColor: micButton.style.borderColor\n };\n \n // Apply recording state styles from config\n const voiceConfig = config.voiceRecognition ?? {};\n const recordingBackgroundColor = voiceConfig.recordingBackgroundColor ?? \"#ef4444\";\n const recordingIconColor = voiceConfig.recordingIconColor;\n const recordingBorderColor = voiceConfig.recordingBorderColor;\n \n micButton.classList.add(\"tvw-voice-recording\");\n micButton.style.backgroundColor = recordingBackgroundColor;\n \n if (recordingIconColor) {\n micButton.style.color = recordingIconColor;\n // Update SVG stroke color if present\n const svg = micButton.querySelector(\"svg\");\n if (svg) {\n svg.setAttribute(\"stroke\", recordingIconColor);\n }\n }\n \n if (recordingBorderColor) {\n micButton.style.borderColor = recordingBorderColor;\n }\n \n micButton.setAttribute(\"aria-label\", \"Stop voice recognition\");\n }\n } catch (error) {\n stopVoiceRecognition(\"system\");\n }\n };\n\n const stopVoiceRecognition = (\n source: AgentWidgetVoiceStateEvent[\"source\"] = \"user\"\n ) => {\n if (!isRecording) return;\n\n isRecording = false;\n if (pauseTimer) {\n clearTimeout(pauseTimer);\n pauseTimer = null;\n }\n\n if (speechRecognition) {\n try {\n speechRecognition.stop();\n } catch (error) {\n // Ignore errors when stopping\n }\n speechRecognition = null;\n }\n\n voiceState.active = false;\n emitVoiceState(source);\n persistVoiceMetadata();\n\n if (micButton) {\n micButton.classList.remove(\"tvw-voice-recording\");\n \n // Restore original styles\n if (originalMicStyles) {\n micButton.style.backgroundColor = originalMicStyles.backgroundColor;\n micButton.style.color = originalMicStyles.color;\n micButton.style.borderColor = originalMicStyles.borderColor;\n \n // Restore SVG stroke color if present\n const svg = micButton.querySelector(\"svg\");\n if (svg) {\n svg.setAttribute(\"stroke\", originalMicStyles.color || \"currentColor\");\n }\n \n originalMicStyles = null;\n }\n \n micButton.setAttribute(\"aria-label\", \"Start voice recognition\");\n }\n };\n\n // Function to create mic button dynamically\n const createMicButton = (voiceConfig: AgentWidgetConfig['voiceRecognition'], sendButtonConfig: AgentWidgetConfig['sendButton']): { micButton: HTMLButtonElement; micButtonWrapper: HTMLElement } | null => {\n const hasSpeechRecognition = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n \n if (!hasSpeechRecognition) return null;\n\n const micButtonWrapper = createElement(\"div\", \"tvw-send-button-wrapper\");\n const micButton = createElement(\n \"button\",\n \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\"\n ) as HTMLButtonElement;\n \n micButton.type = \"button\";\n micButton.setAttribute(\"aria-label\", \"Start voice recognition\");\n \n const micIconName = voiceConfig?.iconName ?? \"mic\";\n const buttonSize = sendButtonConfig?.size ?? \"40px\";\n const micIconSize = voiceConfig?.iconSize ?? buttonSize;\n const micIconSizeNum = parseFloat(micIconSize) || 24;\n \n // Use dedicated colors from voice recognition config, fallback to send button colors\n const backgroundColor = voiceConfig?.backgroundColor ?? sendButtonConfig?.backgroundColor;\n const iconColor = voiceConfig?.iconColor ?? sendButtonConfig?.textColor;\n \n micButton.style.width = micIconSize;\n micButton.style.height = micIconSize;\n micButton.style.minWidth = micIconSize;\n micButton.style.minHeight = micIconSize;\n micButton.style.fontSize = \"18px\";\n micButton.style.lineHeight = \"1\";\n \n // Use Lucide mic icon with configured color (stroke width 1.5 for minimalist outline style)\n const iconColorValue = iconColor || \"currentColor\";\n const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColorValue, 1.5);\n if (micIconSvg) {\n micButton.appendChild(micIconSvg);\n micButton.style.color = iconColorValue;\n } else {\n // Fallback to text if icon fails\n micButton.textContent = \"🎤\";\n micButton.style.color = iconColorValue;\n }\n \n // Apply background color\n if (backgroundColor) {\n micButton.style.backgroundColor = backgroundColor;\n } else {\n micButton.classList.add(\"tvw-bg-cw-primary\");\n }\n \n // Apply icon/text color\n if (iconColor) {\n micButton.style.color = iconColor;\n } else if (!iconColor && !sendButtonConfig?.textColor) {\n micButton.classList.add(\"tvw-text-white\");\n }\n \n // Apply border styling\n if (voiceConfig?.borderWidth) {\n micButton.style.borderWidth = voiceConfig.borderWidth;\n micButton.style.borderStyle = \"solid\";\n }\n if (voiceConfig?.borderColor) {\n micButton.style.borderColor = voiceConfig.borderColor;\n }\n \n // Apply padding styling\n if (voiceConfig?.paddingX) {\n micButton.style.paddingLeft = voiceConfig.paddingX;\n micButton.style.paddingRight = voiceConfig.paddingX;\n }\n if (voiceConfig?.paddingY) {\n micButton.style.paddingTop = voiceConfig.paddingY;\n micButton.style.paddingBottom = voiceConfig.paddingY;\n }\n \n micButtonWrapper.appendChild(micButton);\n \n // Add tooltip if enabled\n const tooltipText = voiceConfig?.tooltipText ?? \"Start voice recognition\";\n const showTooltip = voiceConfig?.showTooltip ?? false;\n if (showTooltip && tooltipText) {\n const tooltip = createElement(\"div\", \"tvw-send-button-tooltip\");\n tooltip.textContent = tooltipText;\n micButtonWrapper.appendChild(tooltip);\n }\n \n return { micButton, micButtonWrapper };\n };\n\n // Wire up mic button click handler\n const handleMicButtonClick = () => {\n if (isRecording) {\n // Stop recording and submit\n const finalValue = textarea.value.trim();\n voiceState.manuallyDeactivated = true;\n persistVoiceMetadata();\n stopVoiceRecognition(\"user\");\n if (finalValue) {\n textarea.value = \"\";\n session.sendMessage(finalValue);\n }\n } else {\n // Start recording\n voiceState.manuallyDeactivated = false;\n persistVoiceMetadata();\n startVoiceRecognition(\"user\");\n }\n };\n\n if (micButton) {\n micButton.addEventListener(\"click\", handleMicButtonClick);\n\n destroyCallbacks.push(() => {\n stopVoiceRecognition(\"system\");\n if (micButton) {\n micButton.removeEventListener(\"click\", handleMicButtonClick);\n }\n });\n }\n\n const autoResumeUnsub = eventBus.on(\"assistant:complete\", () => {\n if (!voiceAutoResumeMode) return;\n if (voiceState.active || voiceState.manuallyDeactivated) return;\n if (voiceAutoResumeMode === \"assistant\" && !voiceState.lastUserMessageWasVoice) {\n return;\n }\n setTimeout(() => {\n if (!voiceState.active && !voiceState.manuallyDeactivated) {\n startVoiceRecognition(\"auto\");\n }\n }, 600);\n });\n destroyCallbacks.push(autoResumeUnsub);\n\n const toggleOpen = () => {\n setOpenState(!open, \"user\");\n };\n\n let launcherButtonInstance = launcherEnabled\n ? createLauncherButton(config, toggleOpen)\n : null;\n\n if (launcherButtonInstance) {\n mount.appendChild(launcherButtonInstance.element);\n }\n updateOpenState();\n suggestionsManager.render(config.suggestionChips, session, textarea, undefined, config.suggestionChipsConfig);\n updateCopy();\n setComposerDisabled(session.isStreaming());\n scheduleAutoScroll(true);\n maybeRestoreVoiceFromMetadata();\n\n const recalcPanelHeight = () => {\n if (!launcherEnabled) {\n panel.style.height = \"\";\n panel.style.width = \"\";\n return;\n }\n const launcherWidth = config?.launcher?.width ?? config?.launcherWidth;\n const width = launcherWidth ?? \"min(400px, calc(100vw - 24px))\";\n panel.style.width = width;\n panel.style.maxWidth = width;\n const viewportHeight = window.innerHeight;\n const verticalMargin = 64; // leave space for launcher's offset\n const available = Math.max(200, viewportHeight - verticalMargin);\n const clamped = Math.min(640, available);\n panel.style.height = `${clamped}px`;\n };\n\n recalcPanelHeight();\n window.addEventListener(\"resize\", recalcPanelHeight);\n destroyCallbacks.push(() => window.removeEventListener(\"resize\", recalcPanelHeight));\n\n lastScrollTop = body.scrollTop;\n\n const handleScroll = () => {\n const scrollTop = body.scrollTop;\n const scrollHeight = body.scrollHeight;\n const clientHeight = body.clientHeight;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n const delta = Math.abs(scrollTop - lastScrollTop);\n lastScrollTop = scrollTop;\n\n if (isAutoScrolling) return;\n if (delta <= USER_SCROLL_THRESHOLD) return;\n\n if (!shouldAutoScroll && distanceFromBottom < BOTTOM_THRESHOLD) {\n isAutoScrollBlocked = false;\n shouldAutoScroll = true;\n return;\n }\n\n if (shouldAutoScroll && distanceFromBottom > BOTTOM_THRESHOLD) {\n isAutoScrollBlocked = true;\n blockUntilTime = Date.now() + AUTO_SCROLL_BLOCK_TIME;\n shouldAutoScroll = false;\n }\n };\n\n body.addEventListener(\"scroll\", handleScroll, { passive: true });\n destroyCallbacks.push(() => body.removeEventListener(\"scroll\", handleScroll));\n destroyCallbacks.push(() => {\n if (scrollRAF) cancelAnimationFrame(scrollRAF);\n });\n\n const refreshCloseButton = () => {\n if (!closeButton) return;\n if (closeHandler) {\n closeButton.removeEventListener(\"click\", closeHandler);\n closeHandler = null;\n }\n if (launcherEnabled) {\n closeButton.style.display = \"\";\n closeHandler = () => {\n open = false;\n updateOpenState();\n };\n closeButton.addEventListener(\"click\", closeHandler);\n } else {\n closeButton.style.display = \"none\";\n }\n };\n\n refreshCloseButton();\n\n // Setup clear chat button click handler\n const setupClearChatButton = () => {\n const { clearChatButton } = panelElements;\n if (!clearChatButton) return;\n\n clearChatButton.addEventListener(\"click\", () => {\n // Clear messages in session (this will trigger onMessagesChanged which re-renders)\n session.clearMessages();\n\n // Always clear the default localStorage key\n try {\n localStorage.removeItem(DEFAULT_CHAT_HISTORY_STORAGE_KEY);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared default localStorage key: ${DEFAULT_CHAT_HISTORY_STORAGE_KEY}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear default localStorage:\", error);\n }\n\n // Also clear custom localStorage key if configured\n if (config.clearChatHistoryStorageKey && config.clearChatHistoryStorageKey !== DEFAULT_CHAT_HISTORY_STORAGE_KEY) {\n try {\n localStorage.removeItem(config.clearChatHistoryStorageKey);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared custom localStorage key: ${config.clearChatHistoryStorageKey}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear custom localStorage:\", error);\n }\n }\n\n // Dispatch custom event for external handlers (e.g., localStorage clearing in examples)\n const clearEvent = new CustomEvent(\"vanilla-agent:clear-chat\", {\n detail: { timestamp: new Date().toISOString() }\n });\n window.dispatchEvent(clearEvent);\n\n if (storageAdapter?.clear) {\n try {\n const result = storageAdapter.clear();\n if (result instanceof Promise) {\n result.catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n });\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n }\n }\n persistentMetadata = {};\n actionManager.syncFromMetadata();\n });\n };\n\n setupClearChatButton();\n\n composerForm.addEventListener(\"submit\", handleSubmit);\n textarea.addEventListener(\"keydown\", handleInputEnter);\n\n destroyCallbacks.push(() => {\n composerForm.removeEventListener(\"submit\", handleSubmit);\n textarea.removeEventListener(\"keydown\", handleInputEnter);\n });\n\n destroyCallbacks.push(() => {\n session.cancel();\n });\n\n if (launcherButtonInstance) {\n destroyCallbacks.push(() => {\n launcherButtonInstance?.destroy();\n });\n }\n\n const controller: Controller = {\n update(nextConfig: AgentWidgetConfig) {\n const previousToolCallConfig = config.toolCall;\n config = { ...config, ...nextConfig };\n applyThemeVariables(mount, config);\n\n // Update plugins\n const newPlugins = pluginRegistry.getForInstance(config.plugins);\n plugins.length = 0;\n plugins.push(...newPlugins);\n\n launcherEnabled = config.launcher?.enabled ?? true;\n autoExpand = config.launcher?.autoExpand ?? false;\n showReasoning = config.features?.showReasoning ?? true;\n showToolCalls = config.features?.showToolCalls ?? true;\n\n if (config.launcher?.enabled === false && launcherButtonInstance) {\n launcherButtonInstance.destroy();\n launcherButtonInstance = null;\n }\n\n if (config.launcher?.enabled !== false && !launcherButtonInstance) {\n launcherButtonInstance = createLauncherButton(config, toggleOpen);\n mount.appendChild(launcherButtonInstance.element);\n }\n\n if (launcherButtonInstance) {\n launcherButtonInstance.update(config);\n }\n\n // Update panel header title and subtitle\n if (headerTitle && config.launcher?.title !== undefined) {\n headerTitle.textContent = config.launcher.title;\n }\n if (headerSubtitle && config.launcher?.subtitle !== undefined) {\n headerSubtitle.textContent = config.launcher.subtitle;\n }\n\n // Only update open state if launcher enabled state changed or autoExpand value changed\n const launcherEnabledChanged = launcherEnabled !== prevLauncherEnabled;\n const autoExpandChanged = autoExpand !== prevAutoExpand;\n\n if (launcherEnabledChanged) {\n // Launcher was enabled/disabled - update state accordingly\n if (!launcherEnabled) {\n // When launcher is disabled, always keep panel open\n open = true;\n updateOpenState();\n } else {\n // Launcher was just enabled - respect autoExpand setting\n setOpenState(autoExpand, \"auto\");\n }\n } else if (autoExpandChanged) {\n // autoExpand value changed - update state to match\n setOpenState(autoExpand, \"auto\");\n }\n // Otherwise, preserve current open state (user may have manually opened/closed)\n\n // Update previous values for next comparison\n prevAutoExpand = autoExpand;\n prevLauncherEnabled = launcherEnabled;\n recalcPanelHeight();\n refreshCloseButton();\n\n // Re-render messages if toolCall config changed (to apply new styles)\n const toolCallConfigChanged = JSON.stringify(nextConfig.toolCall) !== JSON.stringify(previousToolCallConfig);\n if (toolCallConfigChanged && session) {\n renderMessagesWithPlugins(messagesWrapper, session.getMessages(), postprocess);\n }\n\n // Update panel icon sizes\n const launcher = config.launcher ?? {};\n const headerIconHidden = launcher.headerIconHidden ?? false;\n const headerIconName = launcher.headerIconName;\n const headerIconSize = launcher.headerIconSize ?? \"48px\";\n \n if (iconHolder) {\n const header = container.querySelector(\".tvw-border-b-cw-divider\");\n const headerCopy = header?.querySelector(\".tvw-flex-col\");\n \n // Handle hide/show\n if (headerIconHidden) {\n // Hide iconHolder\n iconHolder.style.display = \"none\";\n // Ensure headerCopy is still in header\n if (header && headerCopy && !header.contains(headerCopy)) {\n header.insertBefore(headerCopy, header.firstChild);\n }\n } else {\n // Show iconHolder\n iconHolder.style.display = \"\";\n iconHolder.style.height = headerIconSize;\n iconHolder.style.width = headerIconSize;\n \n // Ensure iconHolder is before headerCopy in header\n if (header && headerCopy) {\n if (!header.contains(iconHolder)) {\n header.insertBefore(iconHolder, headerCopy);\n } else if (iconHolder.nextSibling !== headerCopy) {\n // Reorder if needed\n iconHolder.remove();\n header.insertBefore(iconHolder, headerCopy);\n }\n }\n \n // Update icon content based on priority: Lucide icon > iconUrl > agentIconText\n if (headerIconName) {\n // Use Lucide icon\n const iconSize = parseFloat(headerIconSize) || 24;\n const iconSvg = renderLucideIcon(headerIconName, iconSize * 0.6, \"#ffffff\", 2);\n if (iconSvg) {\n iconHolder.replaceChildren(iconSvg);\n } else {\n // Fallback to agentIconText if Lucide icon fails\n iconHolder.textContent = launcher.agentIconText ?? \"💬\";\n }\n } else if (launcher.iconUrl) {\n // Use image URL\n const img = iconHolder.querySelector(\"img\");\n if (img) {\n img.src = launcher.iconUrl;\n img.style.height = headerIconSize;\n img.style.width = headerIconSize;\n } else {\n // Create new img if it doesn't exist\n const newImg = document.createElement(\"img\");\n newImg.src = launcher.iconUrl;\n newImg.alt = \"\";\n newImg.className = \"tvw-rounded-xl tvw-object-cover\";\n newImg.style.height = headerIconSize;\n newImg.style.width = headerIconSize;\n iconHolder.replaceChildren(newImg);\n }\n } else {\n // Use text/emoji - clear any SVG or img first\n const existingSvg = iconHolder.querySelector(\"svg\");\n const existingImg = iconHolder.querySelector(\"img\");\n if (existingSvg || existingImg) {\n iconHolder.replaceChildren();\n }\n iconHolder.textContent = launcher.agentIconText ?? \"💬\";\n }\n \n // Update image size if present\n const img = iconHolder.querySelector(\"img\");\n if (img) {\n img.style.height = headerIconSize;\n img.style.width = headerIconSize;\n }\n }\n }\n if (closeButton) {\n const closeButtonSize = launcher.closeButtonSize ?? \"32px\";\n const closeButtonPlacement = launcher.closeButtonPlacement ?? \"inline\";\n closeButton.style.height = closeButtonSize;\n closeButton.style.width = closeButtonSize;\n \n // Update placement if changed\n const isTopRight = closeButtonPlacement === \"top-right\";\n const hasTopRightClasses = closeButton.classList.contains(\"tvw-absolute\");\n \n if (isTopRight !== hasTopRightClasses) {\n // Placement changed - need to move button and update classes\n closeButton.remove();\n \n // Update classes\n if (isTopRight) {\n closeButton.className = \"tvw-absolute tvw-top-4 tvw-right-4 tvw-z-50 tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\";\n container.style.position = \"relative\";\n container.appendChild(closeButton);\n } else {\n closeButton.className = \"tvw-ml-auto tvw-inline-flex tvw-items-center tvw-justify-center tvw-rounded-full tvw-text-cw-muted hover:tvw-bg-gray-100 tvw-cursor-pointer tvw-border-none\";\n // Find header element (first child of container)\n const header = container.querySelector(\".tvw-border-b-cw-divider\");\n if (header) {\n header.appendChild(closeButton);\n }\n }\n }\n \n // Apply close button styling from config\n if (launcher.closeButtonColor) {\n closeButton.style.color = launcher.closeButtonColor;\n closeButton.classList.remove(\"tvw-text-cw-muted\");\n } else {\n closeButton.style.color = \"\";\n closeButton.classList.add(\"tvw-text-cw-muted\");\n }\n \n if (launcher.closeButtonBackgroundColor) {\n closeButton.style.backgroundColor = launcher.closeButtonBackgroundColor;\n closeButton.classList.remove(\"hover:tvw-bg-gray-100\");\n } else {\n closeButton.style.backgroundColor = \"\";\n closeButton.classList.add(\"hover:tvw-bg-gray-100\");\n }\n \n // Apply border if width and/or color are provided\n if (launcher.closeButtonBorderWidth || launcher.closeButtonBorderColor) {\n const borderWidth = launcher.closeButtonBorderWidth || \"0px\";\n const borderColor = launcher.closeButtonBorderColor || \"transparent\";\n closeButton.style.border = `${borderWidth} solid ${borderColor}`;\n closeButton.classList.remove(\"tvw-border-none\");\n } else {\n closeButton.style.border = \"\";\n closeButton.classList.add(\"tvw-border-none\");\n }\n \n if (launcher.closeButtonBorderRadius) {\n closeButton.style.borderRadius = launcher.closeButtonBorderRadius;\n closeButton.classList.remove(\"tvw-rounded-full\");\n } else {\n closeButton.style.borderRadius = \"\";\n closeButton.classList.add(\"tvw-rounded-full\");\n }\n\n // Update padding\n if (launcher.closeButtonPaddingX) {\n closeButton.style.paddingLeft = launcher.closeButtonPaddingX;\n closeButton.style.paddingRight = launcher.closeButtonPaddingX;\n } else {\n closeButton.style.paddingLeft = \"\";\n closeButton.style.paddingRight = \"\";\n }\n if (launcher.closeButtonPaddingY) {\n closeButton.style.paddingTop = launcher.closeButtonPaddingY;\n closeButton.style.paddingBottom = launcher.closeButtonPaddingY;\n } else {\n closeButton.style.paddingTop = \"\";\n closeButton.style.paddingBottom = \"\";\n }\n\n // Update icon\n const closeButtonIconName = launcher.closeButtonIconName ?? \"x\";\n const closeButtonIconText = launcher.closeButtonIconText ?? \"×\";\n\n // Clear existing content and render new icon\n closeButton.innerHTML = \"\";\n const iconSvg = renderLucideIcon(closeButtonIconName, \"20px\", launcher.closeButtonColor || \"\", 2);\n if (iconSvg) {\n closeButton.appendChild(iconSvg);\n } else {\n closeButton.textContent = closeButtonIconText;\n }\n\n // Update tooltip\n const { closeButtonWrapper } = panelElements;\n const closeButtonTooltipText = launcher.closeButtonTooltipText ?? \"Close chat\";\n const closeButtonShowTooltip = launcher.closeButtonShowTooltip ?? true;\n\n closeButton.setAttribute(\"aria-label\", closeButtonTooltipText);\n\n if (closeButtonWrapper) {\n // Clean up old tooltip event listeners if they exist\n if ((closeButtonWrapper as any)._cleanupTooltip) {\n (closeButtonWrapper as any)._cleanupTooltip();\n delete (closeButtonWrapper as any)._cleanupTooltip;\n }\n\n // Set up new portaled tooltip with event listeners\n if (closeButtonShowTooltip && closeButtonTooltipText) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip || !closeButton) return; // Already showing or button doesn't exist\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = closeButtonTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = closeButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n closeButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n closeButton.addEventListener(\"focus\", showTooltip);\n closeButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the wrapper for later use\n (closeButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n if (closeButtonWrapper) {\n closeButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n closeButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n }\n if (closeButton) {\n closeButton.removeEventListener(\"focus\", showTooltip);\n closeButton.removeEventListener(\"blur\", hideTooltip);\n }\n };\n }\n }\n }\n\n // Update clear chat button styling from config\n const { clearChatButton, clearChatButtonWrapper } = panelElements;\n if (clearChatButton) {\n const clearChatConfig = launcher.clearChat ?? {};\n const clearChatEnabled = clearChatConfig.enabled ?? true;\n\n // Show/hide button based on enabled state\n if (clearChatButtonWrapper) {\n clearChatButtonWrapper.style.display = clearChatEnabled ? \"\" : \"none\";\n }\n\n if (clearChatEnabled) {\n // Update size\n const clearChatSize = clearChatConfig.size ?? \"32px\";\n clearChatButton.style.height = clearChatSize;\n clearChatButton.style.width = clearChatSize;\n\n // Update icon\n const clearChatIconName = clearChatConfig.iconName ?? \"refresh-cw\";\n const clearChatIconColor = clearChatConfig.iconColor ?? \"\";\n\n // Clear existing icon and render new one\n clearChatButton.innerHTML = \"\";\n const iconSvg = renderLucideIcon(clearChatIconName, \"20px\", clearChatIconColor || \"\", 2);\n if (iconSvg) {\n clearChatButton.appendChild(iconSvg);\n }\n\n // Update icon color\n if (clearChatIconColor) {\n clearChatButton.style.color = clearChatIconColor;\n clearChatButton.classList.remove(\"tvw-text-cw-muted\");\n } else {\n clearChatButton.style.color = \"\";\n clearChatButton.classList.add(\"tvw-text-cw-muted\");\n }\n\n // Update background color\n if (clearChatConfig.backgroundColor) {\n clearChatButton.style.backgroundColor = clearChatConfig.backgroundColor;\n clearChatButton.classList.remove(\"hover:tvw-bg-gray-100\");\n } else {\n clearChatButton.style.backgroundColor = \"\";\n clearChatButton.classList.add(\"hover:tvw-bg-gray-100\");\n }\n\n // Update border\n if (clearChatConfig.borderWidth || clearChatConfig.borderColor) {\n const borderWidth = clearChatConfig.borderWidth || \"0px\";\n const borderColor = clearChatConfig.borderColor || \"transparent\";\n clearChatButton.style.border = `${borderWidth} solid ${borderColor}`;\n clearChatButton.classList.remove(\"tvw-border-none\");\n } else {\n clearChatButton.style.border = \"\";\n clearChatButton.classList.add(\"tvw-border-none\");\n }\n\n // Update border radius\n if (clearChatConfig.borderRadius) {\n clearChatButton.style.borderRadius = clearChatConfig.borderRadius;\n clearChatButton.classList.remove(\"tvw-rounded-full\");\n } else {\n clearChatButton.style.borderRadius = \"\";\n clearChatButton.classList.add(\"tvw-rounded-full\");\n }\n\n // Update padding\n if (clearChatConfig.paddingX) {\n clearChatButton.style.paddingLeft = clearChatConfig.paddingX;\n clearChatButton.style.paddingRight = clearChatConfig.paddingX;\n } else {\n clearChatButton.style.paddingLeft = \"\";\n clearChatButton.style.paddingRight = \"\";\n }\n if (clearChatConfig.paddingY) {\n clearChatButton.style.paddingTop = clearChatConfig.paddingY;\n clearChatButton.style.paddingBottom = clearChatConfig.paddingY;\n } else {\n clearChatButton.style.paddingTop = \"\";\n clearChatButton.style.paddingBottom = \"\";\n }\n\n const clearChatTooltipText = clearChatConfig.tooltipText ?? \"Clear chat\";\n const clearChatShowTooltip = clearChatConfig.showTooltip ?? true;\n\n clearChatButton.setAttribute(\"aria-label\", clearChatTooltipText);\n\n if (clearChatButtonWrapper) {\n // Clean up old tooltip event listeners if they exist\n if ((clearChatButtonWrapper as any)._cleanupTooltip) {\n (clearChatButtonWrapper as any)._cleanupTooltip();\n delete (clearChatButtonWrapper as any)._cleanupTooltip;\n }\n\n // Set up new portaled tooltip with event listeners\n if (clearChatShowTooltip && clearChatTooltipText) {\n let portaledTooltip: HTMLElement | null = null;\n\n const showTooltip = () => {\n if (portaledTooltip || !clearChatButton) return; // Already showing or button doesn't exist\n\n // Create tooltip element\n portaledTooltip = createElement(\"div\", \"tvw-clear-chat-tooltip\");\n portaledTooltip.textContent = clearChatTooltipText;\n\n // Add arrow\n const arrow = createElement(\"div\");\n arrow.className = \"tvw-clear-chat-tooltip-arrow\";\n portaledTooltip.appendChild(arrow);\n\n // Get button position\n const buttonRect = clearChatButton.getBoundingClientRect();\n\n // Position tooltip above button\n portaledTooltip.style.position = \"fixed\";\n portaledTooltip.style.left = `${buttonRect.left + buttonRect.width / 2}px`;\n portaledTooltip.style.top = `${buttonRect.top - 8}px`;\n portaledTooltip.style.transform = \"translate(-50%, -100%)\";\n\n // Append to body\n document.body.appendChild(portaledTooltip);\n };\n\n const hideTooltip = () => {\n if (portaledTooltip && portaledTooltip.parentNode) {\n portaledTooltip.parentNode.removeChild(portaledTooltip);\n portaledTooltip = null;\n }\n };\n\n // Add event listeners\n clearChatButtonWrapper.addEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.addEventListener(\"mouseleave\", hideTooltip);\n clearChatButton.addEventListener(\"focus\", showTooltip);\n clearChatButton.addEventListener(\"blur\", hideTooltip);\n\n // Store cleanup function on the button for later use\n (clearChatButtonWrapper as any)._cleanupTooltip = () => {\n hideTooltip();\n if (clearChatButtonWrapper) {\n clearChatButtonWrapper.removeEventListener(\"mouseenter\", showTooltip);\n clearChatButtonWrapper.removeEventListener(\"mouseleave\", hideTooltip);\n }\n if (clearChatButton) {\n clearChatButton.removeEventListener(\"focus\", showTooltip);\n clearChatButton.removeEventListener(\"blur\", hideTooltip);\n }\n };\n }\n }\n }\n }\n\n const nextParsers =\n config.actionParsers && config.actionParsers.length\n ? config.actionParsers\n : [defaultJsonActionParser];\n const nextHandlers =\n config.actionHandlers && config.actionHandlers.length\n ? config.actionHandlers\n : [defaultActionHandlers.message, defaultActionHandlers.messageAndClick];\n\n actionManager = createActionManager({\n parsers: nextParsers,\n handlers: nextHandlers,\n getMetadata,\n updateMetadata,\n emit: eventBus.emit,\n documentRef: typeof document !== \"undefined\" ? document : null\n });\n\n postprocess = buildPostprocessor(config, actionManager);\n session.updateConfig(config);\n renderMessagesWithPlugins(\n messagesWrapper,\n session.getMessages(),\n postprocess\n );\n suggestionsManager.render(config.suggestionChips, session, textarea, undefined, config.suggestionChipsConfig);\n updateCopy();\n setComposerDisabled(session.isStreaming());\n \n // Update voice recognition mic button visibility\n const voiceRecognitionEnabled = config.voiceRecognition?.enabled === true;\n const hasSpeechRecognition = \n typeof window !== 'undefined' && \n (typeof (window as any).webkitSpeechRecognition !== 'undefined' || \n typeof (window as any).SpeechRecognition !== 'undefined');\n \n // Update composer form gap based on voice recognition\n const shouldUseSmallGap = voiceRecognitionEnabled && hasSpeechRecognition;\n composerForm.classList.remove(\"tvw-gap-1\", \"tvw-gap-3\");\n composerForm.classList.add(shouldUseSmallGap ? \"tvw-gap-1\" : \"tvw-gap-3\");\n \n if (voiceRecognitionEnabled && hasSpeechRecognition) {\n // Create or update mic button\n if (!micButton || !micButtonWrapper) {\n // Create new mic button\n const micButtonResult = createMicButton(config.voiceRecognition, config.sendButton);\n if (micButtonResult) {\n // Update the mutable references\n micButton = micButtonResult.micButton;\n micButtonWrapper = micButtonResult.micButtonWrapper;\n \n // Insert before send button wrapper\n composerForm.insertBefore(micButtonWrapper, sendButtonWrapper);\n \n // Wire up click handler\n micButton.addEventListener(\"click\", handleMicButtonClick);\n \n // Set disabled state\n micButton.disabled = session.isStreaming();\n }\n } else {\n // Update existing mic button with new config\n const voiceConfig = config.voiceRecognition ?? {};\n const sendButtonConfig = config.sendButton ?? {};\n \n // Update icon name and size\n const micIconName = voiceConfig.iconName ?? \"mic\";\n const buttonSize = sendButtonConfig.size ?? \"40px\";\n const micIconSize = voiceConfig.iconSize ?? buttonSize;\n const micIconSizeNum = parseFloat(micIconSize) || 24;\n \n micButton.style.width = micIconSize;\n micButton.style.height = micIconSize;\n micButton.style.minWidth = micIconSize;\n micButton.style.minHeight = micIconSize;\n \n // Update icon\n const iconColor = voiceConfig.iconColor ?? sendButtonConfig.textColor ?? \"currentColor\";\n micButton.innerHTML = \"\";\n const micIconSvg = renderLucideIcon(micIconName, micIconSizeNum, iconColor, 2);\n if (micIconSvg) {\n micButton.appendChild(micIconSvg);\n } else {\n micButton.textContent = \"🎤\";\n }\n \n // Update colors\n const backgroundColor = voiceConfig.backgroundColor ?? sendButtonConfig.backgroundColor;\n if (backgroundColor) {\n micButton.style.backgroundColor = backgroundColor;\n micButton.classList.remove(\"tvw-bg-cw-primary\");\n } else {\n micButton.style.backgroundColor = \"\";\n micButton.classList.add(\"tvw-bg-cw-primary\");\n }\n \n if (iconColor) {\n micButton.style.color = iconColor;\n micButton.classList.remove(\"tvw-text-white\");\n } else if (!iconColor && !sendButtonConfig.textColor) {\n micButton.style.color = \"\";\n micButton.classList.add(\"tvw-text-white\");\n }\n \n // Update border styling\n if (voiceConfig.borderWidth) {\n micButton.style.borderWidth = voiceConfig.borderWidth;\n micButton.style.borderStyle = \"solid\";\n } else {\n micButton.style.borderWidth = \"\";\n micButton.style.borderStyle = \"\";\n }\n if (voiceConfig.borderColor) {\n micButton.style.borderColor = voiceConfig.borderColor;\n } else {\n micButton.style.borderColor = \"\";\n }\n \n // Update padding styling\n if (voiceConfig.paddingX) {\n micButton.style.paddingLeft = voiceConfig.paddingX;\n micButton.style.paddingRight = voiceConfig.paddingX;\n } else {\n micButton.style.paddingLeft = \"\";\n micButton.style.paddingRight = \"\";\n }\n if (voiceConfig.paddingY) {\n micButton.style.paddingTop = voiceConfig.paddingY;\n micButton.style.paddingBottom = voiceConfig.paddingY;\n } else {\n micButton.style.paddingTop = \"\";\n micButton.style.paddingBottom = \"\";\n }\n \n // Update tooltip\n const tooltip = micButtonWrapper?.querySelector(\".tvw-send-button-tooltip\") as HTMLElement | null;\n const tooltipText = voiceConfig.tooltipText ?? \"Start voice recognition\";\n const showTooltip = voiceConfig.showTooltip ?? false;\n if (showTooltip && tooltipText) {\n if (!tooltip) {\n // Create tooltip if it doesn't exist\n const newTooltip = document.createElement(\"div\");\n newTooltip.className = \"tvw-send-button-tooltip\";\n newTooltip.textContent = tooltipText;\n micButtonWrapper?.insertBefore(newTooltip, micButton);\n } else {\n tooltip.textContent = tooltipText;\n tooltip.style.display = \"\";\n }\n } else if (tooltip) {\n // Hide tooltip if disabled\n tooltip.style.display = \"none\";\n }\n \n // Show and update disabled state\n micButtonWrapper.style.display = \"\";\n micButton.disabled = session.isStreaming();\n }\n } else {\n // Hide mic button\n if (micButton && micButtonWrapper) {\n micButtonWrapper.style.display = \"none\";\n // Stop any active recording if disabling\n if (isRecording) {\n stopVoiceRecognition();\n }\n }\n }\n \n // Update send button styling\n const sendButtonConfig = config.sendButton ?? {};\n const useIcon = sendButtonConfig.useIcon ?? false;\n const iconText = sendButtonConfig.iconText ?? \"↑\";\n const iconName = sendButtonConfig.iconName;\n const tooltipText = sendButtonConfig.tooltipText ?? \"Send message\";\n const showTooltip = sendButtonConfig.showTooltip ?? false;\n const buttonSize = sendButtonConfig.size ?? \"40px\";\n const backgroundColor = sendButtonConfig.backgroundColor;\n const textColor = sendButtonConfig.textColor;\n\n // Update button content and styling based on mode\n if (useIcon) {\n // Icon mode: circular button\n sendButton.style.width = buttonSize;\n sendButton.style.height = buttonSize;\n sendButton.style.minWidth = buttonSize;\n sendButton.style.minHeight = buttonSize;\n sendButton.style.fontSize = \"18px\";\n sendButton.style.lineHeight = \"1\";\n \n // Clear existing content\n sendButton.innerHTML = \"\";\n \n // Use Lucide icon if iconName is provided, otherwise fall back to iconText\n if (iconName) {\n const iconSize = parseFloat(buttonSize) || 24;\n const iconColor = textColor && typeof textColor === 'string' && textColor.trim() ? textColor.trim() : \"currentColor\";\n const iconSvg = renderLucideIcon(iconName, iconSize, iconColor, 2);\n if (iconSvg) {\n sendButton.appendChild(iconSvg);\n sendButton.style.color = iconColor;\n } else {\n // Fallback to text if icon fails to render\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n } else {\n sendButton.textContent = iconText;\n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n \n // Update classes\n sendButton.className = \"tvw-rounded-button tvw-flex tvw-items-center tvw-justify-center disabled:tvw-opacity-50 tvw-cursor-pointer\";\n \n if (backgroundColor) {\n sendButton.style.backgroundColor = backgroundColor;\n sendButton.classList.remove(\"tvw-bg-cw-primary\");\n } else {\n sendButton.classList.add(\"tvw-bg-cw-primary\");\n }\n } else {\n // Text mode: existing behavior\n sendButton.textContent = config.copy?.sendButtonLabel ?? \"Send\";\n sendButton.style.width = \"\";\n sendButton.style.height = \"\";\n sendButton.style.minWidth = \"\";\n sendButton.style.minHeight = \"\";\n sendButton.style.fontSize = \"\";\n sendButton.style.lineHeight = \"\";\n \n // Update classes\n sendButton.className = \"tvw-rounded-button tvw-bg-cw-accent tvw-px-4 tvw-py-2 tvw-text-sm tvw-font-semibold tvw-text-white disabled:tvw-opacity-50 tvw-cursor-pointer\";\n \n if (backgroundColor) {\n sendButton.style.backgroundColor = backgroundColor;\n sendButton.classList.remove(\"tvw-bg-cw-accent\");\n } else {\n sendButton.classList.add(\"tvw-bg-cw-accent\");\n }\n \n if (textColor) {\n sendButton.style.color = textColor;\n } else {\n sendButton.classList.add(\"tvw-text-white\");\n }\n }\n\n // Apply border styling\n if (sendButtonConfig.borderWidth) {\n sendButton.style.borderWidth = sendButtonConfig.borderWidth;\n sendButton.style.borderStyle = \"solid\";\n } else {\n sendButton.style.borderWidth = \"\";\n sendButton.style.borderStyle = \"\";\n }\n if (sendButtonConfig.borderColor) {\n sendButton.style.borderColor = sendButtonConfig.borderColor;\n } else {\n sendButton.style.borderColor = \"\";\n }\n\n // Apply padding styling (works in both icon and text mode)\n if (sendButtonConfig.paddingX) {\n sendButton.style.paddingLeft = sendButtonConfig.paddingX;\n sendButton.style.paddingRight = sendButtonConfig.paddingX;\n } else {\n sendButton.style.paddingLeft = \"\";\n sendButton.style.paddingRight = \"\";\n }\n if (sendButtonConfig.paddingY) {\n sendButton.style.paddingTop = sendButtonConfig.paddingY;\n sendButton.style.paddingBottom = sendButtonConfig.paddingY;\n } else {\n sendButton.style.paddingTop = \"\";\n sendButton.style.paddingBottom = \"\";\n }\n\n // Update tooltip\n const tooltip = sendButtonWrapper?.querySelector(\".tvw-send-button-tooltip\") as HTMLElement | null;\n if (showTooltip && tooltipText) {\n if (!tooltip) {\n // Create tooltip if it doesn't exist\n const newTooltip = document.createElement(\"div\");\n newTooltip.className = \"tvw-send-button-tooltip\";\n newTooltip.textContent = tooltipText;\n sendButtonWrapper?.insertBefore(newTooltip, sendButton);\n } else {\n tooltip.textContent = tooltipText;\n tooltip.style.display = \"\";\n }\n } else if (tooltip) {\n tooltip.style.display = \"none\";\n }\n \n // Update status indicator visibility and text\n const statusIndicatorConfig = config.statusIndicator ?? {};\n const isVisible = statusIndicatorConfig.visible ?? true;\n statusText.style.display = isVisible ? \"\" : \"none\";\n \n // Update status text if status is currently set\n if (session) {\n const currentStatus = session.getStatus();\n const getCurrentStatusText = (status: AgentWidgetSessionStatus): string => {\n if (status === \"idle\") return statusIndicatorConfig.idleText ?? statusCopy.idle;\n if (status === \"connecting\") return statusIndicatorConfig.connectingText ?? statusCopy.connecting;\n if (status === \"connected\") return statusIndicatorConfig.connectedText ?? statusCopy.connected;\n if (status === \"error\") return statusIndicatorConfig.errorText ?? statusCopy.error;\n return statusCopy[status];\n };\n statusText.textContent = getCurrentStatusText(currentStatus);\n }\n },\n open() {\n if (!launcherEnabled) return;\n setOpenState(true, \"api\");\n },\n close() {\n if (!launcherEnabled) return;\n setOpenState(false, \"api\");\n },\n toggle() {\n if (!launcherEnabled) return;\n setOpenState(!open, \"api\");\n },\n clearChat() {\n // Clear messages in session (this will trigger onMessagesChanged which re-renders)\n session.clearMessages();\n\n // Always clear the default localStorage key\n try {\n localStorage.removeItem(DEFAULT_CHAT_HISTORY_STORAGE_KEY);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared default localStorage key: ${DEFAULT_CHAT_HISTORY_STORAGE_KEY}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear default localStorage:\", error);\n }\n\n // Also clear custom localStorage key if configured\n if (config.clearChatHistoryStorageKey && config.clearChatHistoryStorageKey !== DEFAULT_CHAT_HISTORY_STORAGE_KEY) {\n try {\n localStorage.removeItem(config.clearChatHistoryStorageKey);\n if (config.debug) {\n console.log(`[AgentWidget] Cleared custom localStorage key: ${config.clearChatHistoryStorageKey}`);\n }\n } catch (error) {\n console.error(\"[AgentWidget] Failed to clear custom localStorage:\", error);\n }\n }\n\n // Dispatch custom event for external handlers (e.g., localStorage clearing in examples)\n const clearEvent = new CustomEvent(\"vanilla-agent:clear-chat\", {\n detail: { timestamp: new Date().toISOString() }\n });\n window.dispatchEvent(clearEvent);\n\n if (storageAdapter?.clear) {\n try {\n const result = storageAdapter.clear();\n if (result instanceof Promise) {\n result.catch((error) => {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n });\n }\n } catch (error) {\n if (typeof console !== \"undefined\") {\n // eslint-disable-next-line no-console\n console.error(\"[AgentWidget] Failed to clear storage adapter:\", error);\n }\n }\n }\n persistentMetadata = {};\n actionManager.syncFromMetadata();\n },\n setMessage(message: string): boolean {\n if (!textarea) return false;\n if (session.isStreaming()) return false;\n \n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n \n textarea.value = message;\n // Trigger input event for any listeners\n textarea.dispatchEvent(new Event('input', { bubbles: true }));\n return true;\n },\n submitMessage(message?: string): boolean {\n if (session.isStreaming()) return false;\n \n const valueToSubmit = message?.trim() || textarea.value.trim();\n if (!valueToSubmit) return false;\n \n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n \n textarea.value = \"\";\n session.sendMessage(valueToSubmit);\n return true;\n },\n startVoiceRecognition(): boolean {\n if (isRecording || session.isStreaming()) return false;\n \n const SpeechRecognitionClass = getSpeechRecognitionClass();\n if (!SpeechRecognitionClass) return false;\n \n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n \n voiceState.manuallyDeactivated = false;\n persistVoiceMetadata();\n startVoiceRecognition(\"user\");\n return true;\n },\n stopVoiceRecognition(): boolean {\n if (!isRecording) return false;\n \n voiceState.manuallyDeactivated = true;\n persistVoiceMetadata();\n stopVoiceRecognition(\"user\");\n return true;\n },\n injectTestMessage(event: AgentWidgetEvent) {\n // Auto-open widget if closed and launcher is enabled\n if (!open && launcherEnabled) {\n setOpenState(true, \"system\");\n }\n session.injectTestEvent(event);\n },\n getMessages() {\n return session.getMessages();\n },\n getStatus() {\n return session.getStatus();\n },\n getPersistentMetadata() {\n return { ...persistentMetadata };\n },\n updatePersistentMetadata(\n updater: (prev: Record<string, unknown>) => Record<string, unknown>\n ) {\n updateMetadata(updater);\n },\n on(event, handler) {\n return eventBus.on(event, handler);\n },\n off(event, handler) {\n eventBus.off(event, handler);\n },\n // State query methods\n isOpen(): boolean {\n return launcherEnabled && open;\n },\n isVoiceActive(): boolean {\n return voiceState.active;\n },\n getState(): AgentWidgetStateSnapshot {\n return {\n open: launcherEnabled && open,\n launcherEnabled,\n voiceActive: voiceState.active,\n streaming: session.isStreaming()\n };\n },\n destroy() {\n destroyCallbacks.forEach((cb) => cb());\n wrapper.remove();\n launcherButtonInstance?.destroy();\n if (closeHandler) {\n closeButton.removeEventListener(\"click\", closeHandler);\n }\n }\n };\n\n const shouldExposeDebugApi =\n (runtimeOptions?.debugTools ?? false) || Boolean(config.debug);\n\n if (shouldExposeDebugApi && typeof window !== \"undefined\") {\n const previousDebug = (window as any).AgentWidgetBrowser;\n const debugApi = {\n controller,\n getMessages: controller.getMessages,\n getStatus: controller.getStatus,\n getMetadata: controller.getPersistentMetadata,\n updateMetadata: controller.updatePersistentMetadata,\n clearHistory: () => controller.clearChat(),\n setVoiceActive: (active: boolean) =>\n active\n ? controller.startVoiceRecognition()\n : controller.stopVoiceRecognition()\n };\n (window as any).AgentWidgetBrowser = debugApi;\n destroyCallbacks.push(() => {\n if ((window as any).AgentWidgetBrowser === debugApi) {\n (window as any).AgentWidgetBrowser = previousDebug;\n }\n });\n }\n\n return controller;\n};\n\nexport type AgentWidgetController = Controller;\n","import { createAgentExperience, AgentWidgetController } from \"../ui\";\nimport { AgentWidgetConfig, AgentWidgetInitOptions, AgentWidgetEvent } from \"../types\";\n\nconst ensureTarget = (target: string | HTMLElement): HTMLElement => {\n if (typeof window === \"undefined\" || typeof document === \"undefined\") {\n throw new Error(\"Chat widget can only be mounted in a browser environment\");\n }\n\n if (typeof target === \"string\") {\n const element = document.querySelector<HTMLElement>(target);\n if (!element) {\n throw new Error(`Chat widget target \"${target}\" was not found`);\n }\n return element;\n }\n\n return target;\n};\n\nconst widgetCssHref = (): string | null => {\n try {\n // This works in ESM builds but not in IIFE builds\n if (typeof import.meta !== \"undefined\" && import.meta.url) {\n return new URL(\"../widget.css\", import.meta.url).href;\n }\n } catch {\n // Fallback for IIFE builds where CSS should be loaded separately\n }\n return null;\n};\n\nconst mountStyles = (root: ShadowRoot | HTMLElement) => {\n const href = widgetCssHref();\n\n const adoptExistingStylesheet = () => {\n if (!(root instanceof ShadowRoot)) {\n return;\n }\n\n if (root.querySelector('link[data-vanilla-agent]')) {\n return;\n }\n\n const globalLink = document.head.querySelector<HTMLLinkElement>(\n 'link[data-vanilla-agent]'\n );\n if (!globalLink) {\n return;\n }\n\n const clonedLink = globalLink.cloneNode(true) as HTMLLinkElement;\n root.insertBefore(clonedLink, root.firstChild);\n };\n\n if (root instanceof ShadowRoot) {\n // For shadow DOM, we need to load CSS into the shadow root\n if (href) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.setAttribute(\"data-vanilla-agent\", \"true\");\n root.insertBefore(link, root.firstChild);\n } else {\n adoptExistingStylesheet();\n }\n // If href is null (IIFE build), CSS should already be loaded globally\n } else {\n // For non-shadow DOM, check if CSS is already loaded\n const existing = document.head.querySelector<HTMLLinkElement>(\n \"link[data-vanilla-agent]\"\n );\n if (!existing) {\n if (href) {\n // ESM build - load CSS dynamically\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = href;\n link.setAttribute(\"data-vanilla-agent\", \"true\");\n document.head.appendChild(link);\n }\n // IIFE build - CSS should be loaded via <link> tag before script\n // If not found, we'll assume it's loaded globally or warn in dev\n }\n }\n};\n\nexport type AgentWidgetInitHandle = AgentWidgetController & { host: HTMLElement };\n\nexport const initAgentWidget = (\n options: AgentWidgetInitOptions\n): AgentWidgetInitHandle => {\n const target = ensureTarget(options.target);\n const host = document.createElement(\"div\");\n host.className = \"vanilla-agent-host\";\n target.appendChild(host);\n\n const useShadow = options.useShadowDom !== false;\n let mount: HTMLElement;\n let root: ShadowRoot | HTMLElement;\n\n if (useShadow) {\n const shadowRoot = host.attachShadow({ mode: \"open\" });\n root = shadowRoot;\n mount = document.createElement(\"div\");\n mount.id = \"vanilla-agent-root\";\n shadowRoot.appendChild(mount);\n mountStyles(shadowRoot);\n } else {\n root = host;\n mount = document.createElement(\"div\");\n mount.id = \"vanilla-agent-root\";\n host.appendChild(mount);\n mountStyles(host);\n }\n\n let controller = createAgentExperience(mount, options.config, {\n debugTools: options.debugTools\n });\n options.onReady?.();\n\n const handle: AgentWidgetInitHandle = {\n ...controller,\n host,\n destroy() {\n controller.destroy();\n host.remove();\n if (options.windowKey && typeof window !== \"undefined\") {\n delete (window as any)[options.windowKey];\n }\n }\n };\n\n // Store on window if windowKey is provided\n if (options.windowKey && typeof window !== 'undefined') {\n (window as any)[options.windowKey] = handle;\n }\n\n return handle;\n};\n","import {\n initAgentWidget as initAgentWidgetFn,\n type AgentWidgetInitHandle\n} from \"./runtime/init\";\n\nexport type {\n AgentWidgetConfig,\n AgentWidgetTheme,\n AgentWidgetFeatureFlags,\n AgentWidgetInitOptions,\n AgentWidgetMessage,\n AgentWidgetLauncherConfig,\n AgentWidgetEvent,\n AgentWidgetStreamParser,\n AgentWidgetStreamParserResult,\n AgentWidgetRequestPayload,\n AgentWidgetCustomFetch,\n AgentWidgetSSEEventParser,\n AgentWidgetSSEEventResult,\n AgentWidgetHeadersFunction\n} from \"./types\";\n\nexport { initAgentWidgetFn as initAgentWidget };\nexport {\n createAgentExperience,\n type AgentWidgetController\n} from \"./ui\";\nexport {\n AgentWidgetSession,\n type AgentWidgetSessionStatus\n} from \"./session\";\nexport { AgentWidgetClient } from \"./client\";\nexport { createLocalStorageAdapter } from \"./utils/storage\";\nexport {\n createActionManager,\n defaultActionHandlers,\n defaultJsonActionParser\n} from \"./utils/actions\";\nexport {\n markdownPostprocessor,\n escapeHtml,\n directivePostprocessor\n} from \"./postprocessors\";\nexport {\n createPlainTextParser,\n createJsonStreamParser,\n createFlexibleJsonStreamParser,\n createRegexJsonParser,\n createXmlParser\n} from \"./utils/formatting\";\nexport type { AgentWidgetInitHandle };\n\n// Plugin system exports\nexport type { AgentWidgetPlugin } from \"./plugins/types\";\nexport { pluginRegistry } from \"./plugins/registry\";\n\n// Component system exports\nexport { componentRegistry } from \"./components/registry\";\nexport type { ComponentRenderer, ComponentContext } from \"./components/registry\";\nexport {\n createComponentStreamParser,\n isComponentDirectiveType\n} from \"./utils/component-parser\";\nexport type { ComponentDirective } from \"./utils/component-parser\";\nexport {\n renderComponentDirective,\n createComponentMiddleware,\n hasComponentDirective,\n extractComponentDirectiveFromMessage\n} from \"./utils/component-middleware\";\n\n// Default configuration exports\nexport { DEFAULT_WIDGET_CONFIG, mergeWithDefaults } from \"./defaults\";\n\nexport default initAgentWidgetFn;\n"],"mappings":"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","names":["marked","markdownPostprocessor","text","escapeHtml","escapeAttribute","value","makeToken","idx","directiveReplacer","source","placeholders","working","match","jsonText","parsed","token","_","type","directivePostprocessor","withTokens","html","tokenRegex","replacement","parsePartialJson","STR","OBJ","formatUnknownValue","value","formatReasoningDuration","reasoning","_a","_b","end","start","seconds","describeReasonStatus","formatToolDuration","tool","_c","describeToolTitle","tool","formatToolDuration","createRegexJsonParserInternal","extractedText","processedLength","extractTextFromIncompleteJson","jsonString","textFieldRegex","match","incompleteTextFieldRegex","incompleteMatch","accumulatedContent","trimmed","extracted","extractTextFromJson","parsed","createPlainTextParser","parser","createRegexJsonParser","_a","regexParser","createJsonStreamParser","parsePartialJson","STR","OBJ","createFlexibleJsonStreamParser","textExtractor","extractText","newText","createXmlParser","DEFAULT_ENDPOINT","getParserFromType","parserType","createJsonStreamParser","createRegexJsonParser","createXmlParser","createPlainTextParser","AgentWidgetClient","config","_a","_b","_c","options","onEvent","controller","payload","headers","dynamicHeaders","error","response","err","messages","a","b","timeA","timeB","message","contextAggregate","provider","result","assistantMessageRef","emitMessage","nextSequence","ensureAssistant","msg","assistant","body","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","_V","_W","_X","_Y","_Z","__","_$","_aa","_ba","reader","decoder","buffer","baseSequence","sequenceCounter","cloneMessage","reasoning","toolCall","tools","tool","assistantMessage","reasoningMessages","toolMessages","reasoningContext","toolContext","normalizeKey","value","getStepKey","getToolCallKey","ensureAssistantMessage","trackReasoningId","stepKey","id","resolveReasoningId","allowCreate","rawId","resolved","existing","generated","ensureReasoningMessage","reasoningId","trackToolId","callKey","resolveToolId","ensureToolMessage","toolId","resolveTimestamp","parsed","dateParsed","ensureStringContent","streamParsers","rawContentBuffers","done","events","event","lines","eventType","data","line","payloadType","handled","reasoningMessage","chunk","start","toolMessage","chunkText","stepType","executionType","accumulatedRaw","parser","looksLikeJson","parsedResult","text","currentAssistant","finalContent","rawBuffer","contentToProcess","extractedText","extractTextFromJson","parserToClose","closeResult","hasExtractedText","currentExtractedText","finalExtractedText","stringContent","displayContent","currentText","AgentWidgetSession","config","callbacks","event","_a","_b","message","AgentWidgetClient","next","rawInput","options","_c","_d","_e","input","userMessage","controller","snapshot","error","fallback","messages","status","streaming","withSequence","index","m","existing","idx","a","b","timeA","timeB","seqA","seqB","applyThemeVariables","element","config","_a","theme","key","value","kebabKey","letter","icons","renderLucideIcon","iconName","size","color","strokeWidth","pascalName","word","iconData","createSvgFromIconData","error","svg","elementData","tagName","attrs","element","key","value","createElement","tag","className","element","statusCopy","positionMap","createLauncherButton","config","onToggle","button","createElement","update","newConfig","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","launcher","titleEl","subtitleEl","textContainer","icon","iconSize","iconSizeNum","iconSvg","renderLucideIcon","img","callToActionIconEl","callToActionIconSize","paddingTotal","containerSize","positionClass","positionMap","base","destroy","createWrapper","config","_a","_b","_c","_d","_e","wrapper","createElement","panel","launcher","position","positionMap","launcherWidth","width","buildPanel","showClose","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","_V","_W","_X","_Y","_Z","__","_$","_aa","_ba","_ca","_da","_ea","_fa","container","header","headerIconSize","closeButtonSize","closeButtonPlacement","headerIconHidden","headerIconName","iconHolder","iconSize","iconSvg","renderLucideIcon","img","headerCopy","title","subtitle","clearChatConfig","clearChatEnabled","clearChatButton","clearChatButtonWrapper","clearChatSize","clearChatIconName","clearChatIconColor","clearChatBgColor","clearChatBorderWidth","clearChatBorderColor","clearChatBorderRadius","clearChatPaddingX","clearChatPaddingY","clearChatTooltipText","clearChatShowTooltip","borderWidth","borderColor","portaledTooltip","showTooltip","arrow","buttonRect","hideTooltip","closeButtonWrapper","closeButton","closeButtonTooltipText","closeButtonShowTooltip","closeButtonIconName","closeButtonIconText","body","introCard","introTitle","introSubtitle","messagesWrapper","footer","suggestions","voiceRecognitionEnabledForGap","hasSpeechRecognitionForGap","composerForm","textarea","fontFamily","fontWeight","getFontFamilyValue","family","sendButtonConfig","useIcon","iconText","iconName","tooltipText","buttonSize","backgroundColor","textColor","sendButtonWrapper","sendButton","iconColor","tooltip","voiceRecognitionConfig","voiceRecognitionEnabled","micButton","micButtonWrapper","hasSpeechRecognition","micIconName","micIconSize","micIconSizeNum","micBackgroundColor","micIconColor","iconColorValue","micIconSvg","e","statusText","statusConfig","isVisible","createTypingIndicator","container","dot1","dot2","dot3","srOnly","createStandardBubble","message","transform","classes","bubble","createElement","contentDiv","typingIndicator","reasoningExpansionState","createReasoningBubble","message","reasoning","bubble","createElement","expanded","header","headerContent","title","status","describeReasonStatus","toggleIcon","chevronIcon","renderLucideIcon","headerMeta","content","text","body","applyExpansionState","toggleExpansion","event","toolExpansionState","createToolBubble","message","config","_a","tool","toolCallConfig","bubble","createElement","expanded","header","headerContent","title","describeToolTitle","toggleIcon","iconColor","chevronIcon","renderLucideIcon","headerMeta","content","toolName","argsBlock","argsLabel","argsPre","formatUnknownValue","logsBlock","logsLabel","logsPre","resultBlock","resultLabel","resultPre","duration","applyToolExpansion","toggleToolExpansion","event","createSuggestions","container","suggestionButtons","chips","session","textarea","messages","chipsConfig","msg","fragment","streaming","getFontFamilyValue","family","chip","btn","createElement","formDefinitions","enhanceWithForms","bubble","message","config","session","placeholders","placeholder","_a","_b","_c","type","definition","heading","createElement","title","desc","form","field","group","label","inputType","control","actions","status","submit","event","formEndpoint","formData","payload","value","key","response","data","error","PluginRegistry","plugin","_a","pluginId","a","b","_b","instancePlugins","allPlugins","instanceIds","p","pluginRegistry","DEFAULT_WIDGET_CONFIG","mergeWithDefaults","config","_a","_b","_c","createEventBus","listeners","on","event","handler","off","_a","payload","error","stripCodeFence","value","match","extractJsonObject","trimmed","start","depth","i","char","defaultJsonActionParser","text","withoutFence","jsonBody","parsed","action","payload","asString","defaultActionHandlers","context","_a","selector","element","ensureArrayOfStrings","entry","createActionManager","options","processedIds","syncFromMetadata","persistProcessedIds","latestIds","prev","parseSource","acc","parser","eventPayload","handler","handlerResult","persist","error","safeJsonParse","value","error","sanitizeMessages","messages","message","createLocalStorageAdapter","key","getStorage","storage","state","payload","ComponentRegistry","name","renderer","components","componentRegistry","parsePartialJson","STR","OBJ","isComponentDirective","obj","component","extractComponentDirective","parsed","rawJson","props","createComponentStreamParser","extractedDirective","processedLength","accumulatedContent","trimmed","directive","isComponentDirectiveType","renderComponentDirective","directive","options","config","message","onPropsUpdate","renderer","componentRegistry","context","newProps","error","createComponentMiddleware","parser","createComponentStreamParser","accumulatedContent","hasComponentDirective","parsed","extractComponentDirectiveFromMessage","DEFAULT_CHAT_HISTORY_STORAGE_KEY","VOICE_STATE_RESTORE_WINDOW","ensureRecord","value","stripStreamingFromMessages","messages","message","buildPostprocessor","cfg","actionManager","context","_a","_b","_c","nextText","rawPayload","actionResult","escapeHtml","createAgentExperience","mount","initialConfig","runtimeOptions","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","config","mergeWithDefaults","applyThemeVariables","plugins","pluginRegistry","componentRegistry","eventBus","createEventBus","storageAdapter","createLocalStorageAdapter","persistentMetadata","pendingStoredState","storedState","immediateState","error","getMetadata","updateMetadata","updater","persistState","resolvedActionParsers","defaultJsonActionParser","resolvedActionHandlers","defaultActionHandlers","createActionManager","launcherEnabled","autoExpand","prevAutoExpand","prevLauncherEnabled","open","postprocess","showReasoning","showToolCalls","statusConfig","getStatusText","status","statusCopy","wrapper","panel","createWrapper","panelElements","buildPanel","container","body","messagesWrapper","suggestions","textarea","sendButton","sendButtonWrapper","composerForm","statusText","introTitle","introSubtitle","closeButton","iconHolder","headerTitle","headerSubtitle","micButton","micButtonWrapper","destroyCallbacks","suggestionsManager","createSuggestions","closeHandler","session","isStreaming","shouldAutoScroll","lastScrollTop","lastAutoScrollTime","scrollRAF","isAutoScrollBlocked","blockUntilTime","isAutoScrolling","AUTO_SCROLL_THROTTLE","AUTO_SCROLL_BLOCK_TIME","USER_SCROLL_THRESHOLD","BOTTOM_THRESHOLD","messageState","voiceState","voiceAutoResumeMode","emitVoiceState","source","persistVoiceMetadata","prev","maybeRestoreVoiceFromMetadata","rawVoiceState","wasActive","timestamp","startVoiceRecognition","getMessagesForPersistence","msg","messagesOverride","payload","result","scheduleAutoScroll","force","now","smoothScrollRAF","getScrollableContainer","smoothScrollToBottom","element","duration","start","clientHeight","target","distance","startTime","easeOutCubic","t","animate","currentTime","currentTarget","elapsed","progress","eased","currentScroll","trackMessages","nextState","previous","key","renderMessagesWithPlugins","transform","fragment","bubble","matchingPlugin","p","createReasoningBubble","createToolBubble","b","createStandardBubble","enhanceWithForms","hasComponentDirective","directive","extractComponentDirectiveFromMessage","componentBubble","renderComponentDirective","textDiv","hasStreamingAssistantMessage","typingIndicator","createTypingIndicator","typingBubble","typingWrapper","scrollableContainer","updateOpenState","launcherButtonInstance","setOpenState","nextOpen","prevOpen","recalcPanelHeight","stateEvent","setComposerDisabled","disabled","btn","updateCopy","fontFamily","fontWeight","getFontFamilyValue","family","AgentWidgetSession","lastUserMessage","currentStatusConfig","getCurrentStatusText","streaming","state","handleSubmit","event","handleInputEnter","speechRecognition","isRecording","pauseTimer","originalMicStyles","getSpeechRecognitionClass","SpeechRecognitionClass","pauseDuration","initialText","fullTranscript","interimTranscript","i","transcript","newValue","finalValue","stopVoiceRecognition","voiceConfig","recordingBackgroundColor","recordingIconColor","recordingBorderColor","svg","createMicButton","sendButtonConfig","createElement","micIconName","buttonSize","micIconSize","micIconSizeNum","backgroundColor","iconColor","iconColorValue","micIconSvg","renderLucideIcon","tooltipText","tooltip","handleMicButtonClick","autoResumeUnsub","toggleOpen","createLauncherButton","launcherWidth","width","viewportHeight","available","clamped","handleScroll","scrollTop","scrollHeight","distanceFromBottom","delta","refreshCloseButton","clearChatButton","clearEvent","controller","nextConfig","_o","_p","_q","_r","_s","_t","_u","_v","_w","_x","_y","_z","_A","_B","_C","_D","_E","_F","_G","_H","_I","_J","_K","_L","_M","_N","_O","_P","_Q","_R","_S","_T","_U","_V","_W","_X","_Y","previousToolCallConfig","newPlugins","launcher","headerIconHidden","headerIconName","headerIconSize","header","headerCopy","iconSize","iconSvg","img","newImg","existingSvg","existingImg","closeButtonSize","closeButtonPlacement","isTopRight","hasTopRightClasses","borderWidth","borderColor","closeButtonIconName","closeButtonIconText","closeButtonWrapper","closeButtonTooltipText","closeButtonShowTooltip","portaledTooltip","showTooltip","arrow","buttonRect","hideTooltip","clearChatButtonWrapper","clearChatConfig","clearChatEnabled","clearChatSize","clearChatIconName","clearChatIconColor","clearChatTooltipText","clearChatShowTooltip","nextParsers","nextHandlers","voiceRecognitionEnabled","hasSpeechRecognition","shouldUseSmallGap","micButtonResult","newTooltip","useIcon","iconText","iconName","textColor","statusIndicatorConfig","isVisible","currentStatus","valueToSubmit","handler","cb","previousDebug","debugApi","active","import_meta","ensureTarget","target","element","widgetCssHref","mountStyles","root","href","adoptExistingStylesheet","globalLink","clonedLink","link","initAgentWidget","options","_a","host","useShadow","mount","shadowRoot","controller","createAgentExperience","handle","index_default","initAgentWidget"]}
|