@docgenlab.com/chat-widget 0.1.3 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/api.d.ts +51 -1
- package/dist/index.js +902 -256
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +6 -6
- package/dist/index.umd.cjs.map +1 -1
- package/dist/types.d.ts +132 -0
- package/dist/widget.css +1 -1
- package/package.json +1 -1
package/dist/index.umd.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.cjs","sources":["../src/api.ts","../src/widget.tsx","../src/index.ts"],"sourcesContent":["/**\n * Thin client for the /api/v1/public/kb/* surface. No axios — uses native\n * fetch + a manual SSE reader so the bundle stays small.\n *\n * All requests carry two headers:\n * X-DocGenLab-Key — the publishable key (server resolves to agent)\n * X-DocGenLab-Visitor-Id — a stable UUID minted in localStorage\n */\n\nimport type { AgentInfo, StreamEvent } from './types';\n\nconst PUBLIC_BASE = '/api/v1/public/kb';\nconst VISITOR_KEY = 'dgl-visitor-id';\n\n/** Generate a UUID v4. Avoids the `crypto.randomUUID` dependency for older\n * browsers; falls back to a Math.random-based variant. */\nfunction uuid(): string {\n const c = (globalThis as any).crypto;\n if (c && typeof c.randomUUID === 'function') return c.randomUUID();\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n const r = (Math.random() * 16) | 0;\n const v = ch === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nfunction getVisitorId(): string {\n try {\n let id = localStorage.getItem(VISITOR_KEY);\n if (!id) {\n id = uuid();\n localStorage.setItem(VISITOR_KEY, id);\n }\n return id;\n } catch {\n // Storage unavailable (private mode, blocked) — use a session-scoped id.\n return uuid();\n }\n}\n\nexport interface ClientOptions {\n agentKey: string;\n apiBaseUrl: string;\n}\n\nexport class WidgetClient {\n private readonly agentKey: string;\n private readonly baseUrl: string;\n private readonly visitorId: string;\n\n constructor(opts: ClientOptions) {\n this.agentKey = opts.agentKey;\n this.baseUrl = opts.apiBaseUrl.replace(/\\/+$/, '');\n this.visitorId = getVisitorId();\n }\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n return {\n 'X-DocGenLab-Key': this.agentKey,\n 'X-DocGenLab-Visitor-Id': this.visitorId,\n ...(extra || {}),\n };\n }\n\n async getAgent(): Promise<AgentInfo> {\n const resp = await fetch(`${this.baseUrl}${PUBLIC_BASE}/agent`, {\n method: 'GET',\n headers: this.headers(),\n });\n if (!resp.ok) throw new Error(`getAgent failed: ${resp.status}`);\n return resp.json();\n }\n\n async uploadImage(file: File): Promise<string> {\n const fd = new FormData();\n fd.append('file', file);\n const resp = await fetch(`${this.baseUrl}${PUBLIC_BASE}/chat-image`, {\n method: 'POST',\n headers: this.headers(), // browser sets Content-Type for FormData\n body: fd,\n });\n if (!resp.ok) {\n let detail = `${resp.status} ${resp.statusText}`;\n try {\n const j = await resp.json();\n detail = j?.detail || detail;\n } catch { /* keep status */ }\n throw new Error(detail);\n }\n const j = await resp.json();\n return j.image_path as string;\n }\n\n /** Fetch a previously-uploaded image as a blob URL. Caller must\n * URL.revokeObjectURL() when done to avoid memory leaks. */\n async fetchImage(imagePath: string): Promise<string> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/chat-image?path=${encodeURIComponent(imagePath)}&key=${encodeURIComponent(this.agentKey)}`;\n const resp = await fetch(url, {\n method: 'GET',\n headers: { 'X-DocGenLab-Visitor-Id': this.visitorId },\n });\n if (!resp.ok) throw new Error(`fetchImage failed: ${resp.status}`);\n const blob = await resp.blob();\n return URL.createObjectURL(blob);\n }\n\n /** Stream a chat response via SSE. Returns an abort fn the caller invokes\n * to cancel the stream. */\n streamChat(\n body: { message: string; conversation_id?: string; image_path?: string },\n onEvent: (event: StreamEvent) => void,\n ): () => void {\n const ctrl = new AbortController();\n (async () => {\n try {\n const resp = await fetch(`${this.baseUrl}${PUBLIC_BASE}/chat`, {\n method: 'POST',\n signal: ctrl.signal,\n headers: this.headers({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }),\n body: JSON.stringify(body),\n });\n if (!resp.ok || !resp.body) {\n let detail = `${resp.status} ${resp.statusText}`;\n try { const j = await resp.json(); detail = j?.detail || detail; } catch {}\n onEvent({ type: 'error', error: detail });\n return;\n }\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n let nl;\n while ((nl = buf.indexOf('\\n\\n')) !== -1) {\n const raw = buf.slice(0, nl);\n buf = buf.slice(nl + 2);\n const line = raw.trim();\n if (!line.startsWith('data:')) continue;\n try {\n const evt = JSON.parse(line.slice(5).trim()) as StreamEvent;\n onEvent(evt);\n } catch {\n // Ignore malformed SSE frames\n }\n }\n }\n } catch (e: any) {\n if (e?.name !== 'AbortError') {\n onEvent({ type: 'error', error: e?.message || String(e) });\n }\n }\n })();\n return () => ctrl.abort();\n }\n}\n","import * as React from 'react';\nimport { useCallback, useEffect, useRef, useState, type CSSProperties, type FormEvent } from 'react';\nimport type { ChatMessage, ChatWidgetConfig, AgentInfo, Citation } from './types';\nimport { WidgetClient } from './api';\nimport './styles.css';\n\nconst DEFAULTS = {\n apiBaseUrl: 'https://api.docgenlab.com',\n position: 'bottom-right' as const,\n primary: '#4F46E5',\n primaryText: '#FFFFFF',\n radius: '14px',\n fontFamily: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n greeting: 'Hi — how can I help?',\n enableImageUpload: true,\n};\n\nexport interface DocGenLabChatProps extends ChatWidgetConfig {\n /** Called when the widget mounts and successfully resolves the agent. */\n onReady?: (agent: AgentInfo) => void;\n /** Called for unrecoverable errors so the customer can log them. */\n onError?: (err: string) => void;\n}\n\n/**\n * Floating-bubble chat widget. Renders a launcher button bottom-right\n * (or -left) that expands to a chat panel.\n */\nexport function DocGenLabChat(props: DocGenLabChatProps) {\n const baseUrl = props.apiBaseUrl || DEFAULTS.apiBaseUrl;\n const position = props.position || DEFAULTS.position;\n const enableImageUpload = props.enableImageUpload !== false;\n\n const themeVars: CSSProperties & Record<string, string> = {\n ['--dgl-primary' as any]: props.theme?.primary || DEFAULTS.primary,\n ['--dgl-primary-text' as any]: props.theme?.primaryText || DEFAULTS.primaryText,\n ['--dgl-radius' as any]: props.theme?.radius || DEFAULTS.radius,\n ['--dgl-font' as any]: props.theme?.fontFamily || DEFAULTS.fontFamily,\n };\n\n const clientRef = useRef<WidgetClient | null>(null);\n if (!clientRef.current) {\n clientRef.current = new WidgetClient({ agentKey: props.agentKey, apiBaseUrl: baseUrl });\n }\n const client = clientRef.current;\n\n const [open, setOpen] = useState(!!props.openOnLoad);\n // Expanded: roughly 1.6x the default, capped to viewport on small screens.\n // Toggled by the icon next to close in the header.\n const [expanded, setExpanded] = useState(false);\n const [agent, setAgent] = useState<AgentInfo | null>(null);\n const [agentError, setAgentError] = useState<string | null>(null);\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [input, setInput] = useState('');\n const [streaming, setStreaming] = useState(false);\n const [conversationId, setConversationId] = useState<string | null>(null);\n const [attachedFile, setAttachedFile] = useState<File | null>(null);\n const [attachedPreview, setAttachedPreview] = useState<string | null>(null);\n const [uploadingImage, setUploadingImage] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const abortRef = useRef<(() => void) | null>(null);\n const contentRef = useRef('');\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resolve agent on first open\n useEffect(() => {\n if (!open || agent) return;\n client.getAgent()\n .then((info) => {\n setAgent(info);\n props.onReady?.(info);\n })\n .catch((e: Error) => {\n setAgentError(e.message);\n props.onError?.(e.message);\n });\n }, [open, agent, client, props]);\n\n // Restore conversation_id if we have one in localStorage\n useEffect(() => {\n const k = `dgl-chat:${props.agentKey}`;\n const stored = localStorage.getItem(k);\n if (stored) setConversationId(stored);\n }, [props.agentKey]);\n\n // Persist conversation id whenever it changes\n useEffect(() => {\n if (conversationId) {\n localStorage.setItem(`dgl-chat:${props.agentKey}`, conversationId);\n }\n }, [conversationId, props.agentKey]);\n\n // Auto-scroll on new messages\n useEffect(() => {\n if (scrollRef.current) {\n scrollRef.current.scrollTop = scrollRef.current.scrollHeight;\n }\n }, [messages]);\n\n const clearAttachment = useCallback(() => {\n if (attachedPreview) URL.revokeObjectURL(attachedPreview);\n setAttachedFile(null);\n setAttachedPreview(null);\n }, [attachedPreview]);\n\n const stageImage = useCallback((file: File) => {\n if (!file.type.startsWith('image/')) return;\n const MAX = 10 * 1024 * 1024;\n if (file.size > MAX) return;\n if (attachedPreview) URL.revokeObjectURL(attachedPreview);\n setAttachedFile(file);\n setAttachedPreview(URL.createObjectURL(file));\n }, [attachedPreview]);\n\n const onSubmit = async (e: FormEvent) => {\n e.preventDefault();\n if (!input.trim() || streaming || uploadingImage) return;\n const userText = input.trim();\n\n // Upload image (if any) first\n let imagePath: string | undefined;\n let previewForTurn: string | undefined;\n if (attachedFile) {\n try {\n setUploadingImage(true);\n imagePath = await client.uploadImage(attachedFile);\n } catch (e: any) {\n props.onError?.(e?.message || 'Image upload failed');\n setUploadingImage(false);\n return;\n }\n setUploadingImage(false);\n previewForTurn = attachedPreview || undefined;\n }\n\n setInput('');\n contentRef.current = '';\n setMessages((prev) => [\n ...prev,\n { role: 'user', content: userText, imagePath, imagePreviewUrl: previewForTurn },\n { role: 'assistant', content: '', streaming: true },\n ]);\n setStreaming(true);\n // Clear the staged attachment; the turn owns the preview URL now\n setAttachedFile(null);\n setAttachedPreview(null);\n\n abortRef.current = client.streamChat(\n { message: userText, conversation_id: conversationId || undefined, image_path: imagePath },\n (evt) => {\n if (evt.type === 'conversation') {\n setConversationId(evt.conversation_id);\n } else if (evt.type === 'token') {\n contentRef.current += evt.content;\n const snap = contentRef.current;\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant' ? { ...m, content: snap } : m\n ));\n } else if (evt.type === 'citations') {\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant' ? { ...m, citations: evt.citations } : m\n ));\n } else if (evt.type === 'refused') {\n contentRef.current = evt.content;\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? { ...m, content: evt.content, refused: true }\n : m\n ));\n } else if (evt.type === 'done') {\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? { ...m, streaming: false, id: evt.message_id, cacheHit: evt.cache_hit }\n : m\n ));\n setStreaming(false);\n } else if (evt.type === 'error') {\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? { ...m, content: `Error: ${evt.error}`, streaming: false, refused: true }\n : m\n ));\n setStreaming(false);\n props.onError?.(evt.error);\n }\n },\n );\n };\n\n const newChat = () => {\n if (abortRef.current) abortRef.current();\n setMessages([]);\n setConversationId(null);\n setStreaming(false);\n localStorage.removeItem(`dgl-chat:${props.agentKey}`);\n clearAttachment();\n };\n\n const displayName = props.agentName || agent?.name || 'Assistant';\n\n return (\n <div className={`dgl-root dgl-pos-${position}`} style={themeVars}>\n {open && (\n <div className={`dgl-panel ${expanded ? 'dgl-panel-expanded' : ''}`}>\n <div className=\"dgl-header\">\n <div className=\"dgl-header-info\">\n {props.agentAvatarUrl && (\n <img src={props.agentAvatarUrl} alt=\"\" className=\"dgl-avatar\" />\n )}\n <div className=\"dgl-header-text\">\n <div className=\"dgl-title\">{displayName}</div>\n {agent?.org_name && (\n <div className=\"dgl-subtitle\">{agent.org_name}</div>\n )}\n </div>\n </div>\n <div className=\"dgl-header-actions\">\n <button\n type=\"button\"\n onClick={newChat}\n className=\"dgl-icon-btn\"\n title=\"New chat\"\n aria-label=\"New chat\"\n >\n {svgPlus()}\n </button>\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"dgl-icon-btn dgl-hide-on-mobile\"\n title={expanded ? 'Restore size' : 'Expand view'}\n aria-label={expanded ? 'Restore size' : 'Expand view'}\n >\n {expanded ? svgShrink() : svgExpand()}\n </button>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"dgl-icon-btn\"\n title=\"Close\"\n aria-label=\"Close\"\n >\n {svgX()}\n </button>\n </div>\n </div>\n\n <div className=\"dgl-messages\" ref={scrollRef}>\n {messages.length === 0 && !agentError && (\n <div className=\"dgl-empty\">\n <div className=\"dgl-empty-text\">\n {props.greeting || DEFAULTS.greeting}\n </div>\n {agent?.description && (\n <div className=\"dgl-empty-sub\">{agent.description}</div>\n )}\n </div>\n )}\n {agentError && (\n <div className=\"dgl-error\">\n Couldn't load the assistant: {agentError}\n </div>\n )}\n {messages.map((m, idx) => (\n <MessageBubble\n key={idx}\n message={m}\n client={client}\n isLast={idx === messages.length - 1}\n agentAvatarUrl={props.agentAvatarUrl}\n onPickFollowup={(q) => {\n setInput(q);\n // Don't auto-send; user reviews + presses send.\n // Same UX as the dashboard.\n }}\n />\n ))}\n </div>\n\n <form className=\"dgl-composer\" onSubmit={onSubmit}>\n {attachedPreview && (\n <div className=\"dgl-staged-image\">\n <img src={attachedPreview} alt=\"attachment\" />\n <button\n type=\"button\"\n onClick={clearAttachment}\n className=\"dgl-staged-remove\"\n aria-label=\"Remove image\"\n >\n {svgX()}\n </button>\n </div>\n )}\n <div className=\"dgl-composer-row\">\n {enableImageUpload && (\n <>\n <button\n type=\"button\"\n className=\"dgl-icon-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={streaming || uploadingImage}\n title=\"Attach image\"\n aria-label=\"Attach image\"\n >\n {svgImage()}\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n style={{ display: 'none' }}\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) stageImage(f);\n if (e.target) e.target.value = '';\n }}\n />\n </>\n )}\n <input\n className=\"dgl-input\"\n value={input}\n onChange={(e) => setInput(e.target.value)}\n placeholder={\n streaming\n ? 'Thinking…'\n : attachedPreview\n ? 'Describe what to know about this image…'\n : 'Type your question…'\n }\n disabled={streaming}\n onPaste={(e) => {\n if (!enableImageUpload) return;\n const item = Array.from(e.clipboardData?.items || []).find(\n (it) => it.kind === 'file' && it.type.startsWith('image/')\n );\n if (item) {\n const f = item.getAsFile();\n if (f) { e.preventDefault(); stageImage(f); }\n }\n }}\n />\n <button\n type=\"submit\"\n className=\"dgl-send-btn\"\n disabled={!input.trim() || streaming || uploadingImage}\n aria-label=\"Send\"\n >\n {streaming || uploadingImage ? svgSpinner() : svgSend()}\n </button>\n </div>\n {!props.hideBranding && (\n <div className=\"dgl-branding\">\n Powered by <a href=\"https://docgenlab.com\" target=\"_blank\" rel=\"noopener noreferrer\">DocGenLab</a>\n </div>\n )}\n </form>\n </div>\n )}\n\n <button\n type=\"button\"\n className=\"dgl-launcher\"\n onClick={() => setOpen((v) => !v)}\n aria-label={open ? 'Close chat' : 'Open chat'}\n >\n {open ? svgChevronDown() : svgChat()}\n </button>\n </div>\n );\n}\n\n// ─── Message bubble ─────────────────────────────────────────────────────\n\nfunction MessageBubble({\n message,\n client,\n isLast,\n agentAvatarUrl,\n onPickFollowup,\n}: {\n message: ChatMessage;\n client: WidgetClient;\n isLast: boolean;\n agentAvatarUrl?: string;\n onPickFollowup: (q: string) => void;\n}) {\n if (message.role === 'user') {\n return (\n <div className=\"dgl-msg dgl-msg-user\">\n <div className=\"dgl-bubble dgl-bubble-user\">\n {(message.imagePath || message.imagePreviewUrl) && (\n <UserImage client={client} imagePath={message.imagePath} previewUrl={message.imagePreviewUrl} />\n )}\n {message.content}\n </div>\n </div>\n );\n }\n const cleaned = cleanForDisplay(message.content);\n const followups = !message.streaming ? extractFollowups(message.content) : [];\n return (\n <div className=\"dgl-msg dgl-msg-assistant\">\n {agentAvatarUrl ? (\n <img src={agentAvatarUrl} className=\"dgl-avatar\" alt=\"\" />\n ) : (\n <div className=\"dgl-avatar dgl-avatar-fallback\">{svgSparkles()}</div>\n )}\n <div className=\"dgl-msg-body\">\n {message.refused ? (\n <div className=\"dgl-refused\">{cleaned}</div>\n ) : (\n <div className=\"dgl-assistant-text\">\n {/* Tokens haven't started arriving yet — show thinking dots\n instead of an empty bubble. */}\n {message.streaming && !cleaned ? (\n <ThinkingDots />\n ) : (\n <>\n {renderMarkdown(cleaned)}\n {message.streaming && <span className=\"dgl-typing-cursor\">▍</span>}\n </>\n )}\n </div>\n )}\n {!message.streaming && !!message.citations?.length && (\n <CitationChips citations={message.citations} />\n )}\n {followups.length > 0 && (\n <FollowupChips suggestions={followups} onPick={onPickFollowup} />\n )}\n </div>\n </div>\n );\n}\n\n/** Clickable chips below an assistant answer suggesting next questions.\n * Clicking pre-fills the input — the user reviews + presses send. */\nfunction FollowupChips({\n suggestions,\n onPick,\n}: {\n suggestions: string[];\n onPick: (q: string) => void;\n}) {\n return (\n <div className=\"dgl-followups\">\n <div className=\"dgl-followups-label\">Continue exploring</div>\n <div className=\"dgl-followups-list\">\n {suggestions.map((q, i) => (\n <button\n key={i}\n type=\"button\"\n className=\"dgl-followup-chip\"\n onClick={() => onPick(q)}\n >\n {q}\n </button>\n ))}\n </div>\n </div>\n );\n}\n\nfunction UserImage({\n client,\n imagePath,\n previewUrl,\n}: { client: WidgetClient; imagePath?: string; previewUrl?: string }) {\n const [url, setUrl] = useState<string | null>(previewUrl || null);\n useEffect(() => {\n if (previewUrl || !imagePath) return;\n let revoke: string | null = null;\n client.fetchImage(imagePath)\n .then((u) => { revoke = u; setUrl(u); })\n .catch(() => setUrl(null));\n return () => { if (revoke) URL.revokeObjectURL(revoke); };\n }, [client, imagePath, previewUrl]);\n if (!url) return null;\n return (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"dgl-user-image-link\">\n <img src={url} className=\"dgl-user-image\" alt=\"attached\" />\n </a>\n );\n}\n\nfunction CitationChips({ citations }: { citations: Citation[] }) {\n // Dedupe by source — many chunks often come from the same doc, no need to spam.\n const seen = new Set<string>();\n const unique = citations.filter((c) => {\n if (seen.has(c.source_id)) return false;\n seen.add(c.source_id);\n return true;\n });\n if (!unique.length) return null;\n return (\n <div className=\"dgl-citations\">\n {unique.map((c) => (\n <span key={c.chunk_id} className=\"dgl-citation\" title={c.snippet}>\n {c.source_name}{c.page ? ` · p${c.page}` : ''}\n </span>\n ))}\n </div>\n );\n}\n\n/** Pull the suggested follow-up questions out of the trailing\n * <followups>...</followups> block (max 3, 4-120 chars each). Returns []\n * if the block is missing, mid-stream, or empty. */\nfunction extractFollowups(content: string): string[] {\n const match = content.match(/<followups>([\\s\\S]*?)<\\/followups>/i);\n if (!match) return [];\n return match[1]\n .split('\\n')\n .map((line) => line.trim())\n .map((line) => line.replace(/^[-*•\\d.)\\s\"']+|[\"']$/g, '').trim())\n .filter((line) => line.length >= 4 && line.length <= 120)\n .slice(0, 3);\n}\n\n/** Strip citation markers, [Section: ...] tags, [doc:abc...] refs, the\n * trailing <followups>...</followups> block, and any leftover orphan\n * punctuation. Ported from the dashboard's cleanCitations so the widget\n * matches the main app's chat exactly.\n *\n * Why this is needed: the system prompt asks the LLM not to emit inline\n * citations, but it sometimes leaks `[doc:11]` / `[1]` / etc. anyway. The\n * user-visible answer must be clean — citations render as separate chips. */\nfunction cleanForDisplay(text: string): string {\n return text\n .replace(/\\n*<followups>[\\s\\S]*?(<\\/followups>|$)/gi, '')\n .replace(/\\s*\\[\\s*Section:[^\\]]*\\]?/gi, '')\n .replace(/\\s*\\[\\s*doc:[^\\]]*\\]?/gi, '')\n .replace(/\\s*\\[\\s*(?:document|doc|source|ref|reference)[^\\]]*\\]?/gi, '')\n .replace(/\\s*\\[\\s*(?:p\\.?\\s*)?\\d+(?:\\s*[,–-]\\s*\\d+)*\\s*\\]/gi, '')\n .replace(/[,;]?\\s*doc:\\s*[0-9a-fA-F][0-9a-fA-F-]{6,}\\]?/gi, '')\n .replace(/[,;]\\s*(?:\\d+|doc:?\\s*[0-9a-fA-F-]+)\\s*\\]?/gi, '')\n .replace(/([\\w%])\\s*\\]/g, '$1')\n .replace(/\\s+([,.;:!?])/g, '$1')\n .replace(/[ \\t]+/g, ' ')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\n/** Minimal markdown → React renderer for assistant answers. Handles the\n * patterns the system prompt emits: **bold**, `inline code`, paragraph\n * breaks, and `-` / `*` / `1.` lists. Deliberately no full markdown\n * parser to keep the bundle small — for richer needs, the customer can\n * override by post-processing `onToken` themselves later. */\nfunction renderMarkdown(text: string): React.ReactNode {\n // Split into paragraphs first (blank-line separated)\n const blocks = text.split(/\\n{2,}/);\n return blocks.map((block, i) => {\n const lines = block.split('\\n');\n const listMatch = lines.every((l) => /^(\\s*)([-*]|\\d+\\.)\\s/.test(l));\n if (listMatch && lines.length > 0) {\n const isOrdered = /^\\d+\\./.test(lines[0].trim());\n const items = lines.map((l) => l.replace(/^\\s*(?:[-*]|\\d+\\.)\\s+/, ''));\n const Tag = isOrdered ? 'ol' : 'ul';\n return (\n <Tag key={i} className={`dgl-md-list ${isOrdered ? 'dgl-md-ol' : 'dgl-md-ul'}`}>\n {items.map((it, j) => (\n <li key={j}>{renderInline(it)}</li>\n ))}\n </Tag>\n );\n }\n return (\n <p key={i} className=\"dgl-md-p\">\n {block.split('\\n').map((line, j, arr) => (\n <React.Fragment key={j}>\n {renderInline(line)}\n {j < arr.length - 1 && <br />}\n </React.Fragment>\n ))}\n </p>\n );\n });\n}\n\n/** Inline markdown: **bold**, *italic*, `code`, [text](url). */\nfunction renderInline(text: string): React.ReactNode {\n // Tokenize. We avoid a full parser; this regex captures the supported\n // patterns in order of precedence (code first so it shields its contents).\n const pattern = /(`[^`]+`|\\*\\*[^*\\n]+\\*\\*|\\*[^*\\n]+\\*|\\[[^\\]]+\\]\\([^)]+\\))/g;\n const parts = text.split(pattern);\n return parts.map((part, idx) => {\n if (!part) return null;\n if (part.startsWith('`') && part.endsWith('`')) {\n return <code key={idx} className=\"dgl-md-code\">{part.slice(1, -1)}</code>;\n }\n if (part.startsWith('**') && part.endsWith('**')) {\n return <strong key={idx}>{part.slice(2, -2)}</strong>;\n }\n if (part.startsWith('*') && part.endsWith('*') && part.length > 2) {\n return <em key={idx}>{part.slice(1, -1)}</em>;\n }\n const linkMatch = part.match(/^\\[([^\\]]+)\\]\\(([^)]+)\\)$/);\n if (linkMatch) {\n return (\n <a key={idx} href={linkMatch[2]} target=\"_blank\" rel=\"noopener noreferrer\" className=\"dgl-md-link\">\n {linkMatch[1]}\n </a>\n );\n }\n return <React.Fragment key={idx}>{part}</React.Fragment>;\n });\n}\n\n/** Bouncing-dots loading indicator shown after Send but before the first\n * token arrives. Matches the dashboard's ThinkingDots cadence. */\nfunction ThinkingDots() {\n return (\n <span className=\"dgl-thinking\">\n <span className=\"dgl-thinking-dot\" />\n <span className=\"dgl-thinking-dot\" />\n <span className=\"dgl-thinking-dot\" />\n </span>\n );\n}\n\n// ─── Inline SVG icons (no external deps) ────────────────────────────────\n\nfunction svgChat() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"currentColor\">\n <path d=\"M4 4h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-4 4V6a2 2 0 0 1 2-2z\" />\n </svg>\n );\n}\nfunction svgChevronDown() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\nfunction svgX() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\nfunction svgPlus() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n );\n}\nfunction svgSend() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\">\n <path d=\"M2 21l21-9L2 3v7l15 2-15 2z\" />\n </svg>\n );\n}\nfunction svgImage() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n );\n}\nfunction svgSpinner() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" className=\"dgl-spin\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\">\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\nfunction svgExpand() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\nfunction svgShrink() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"14\" y1=\"10\" x2=\"21\" y2=\"3\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\nfunction svgSparkles() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"currentColor\">\n <path d=\"M12 2l2.39 6.95L21 11l-6.61 2.05L12 20l-2.39-6.95L3 11l6.61-2.05L12 2z\" />\n </svg>\n );\n}\n","/**\n * @docgenlab.com/chat-widget — public entry.\n *\n * Two integration paths:\n *\n * 1. React (recommended for SPAs):\n *\n * import { DocGenLabChat } from '@docgenlab.com/chat-widget';\n * import '@docgenlab.com/chat-widget/style.css';\n *\n * <DocGenLabChat agentKey=\"pk_live_...\" />\n *\n * 2. Vanilla / script tag (WordPress, marketing pages, anything without\n * a build step). Use unpkg or jsdelivr to load the UMD bundle:\n *\n * <link rel=\"stylesheet\" href=\"https://unpkg.com/@docgenlab.com/chat-widget/dist/widget.css\" />\n * <script src=\"https://unpkg.com/@docgenlab.com/chat-widget\"></script>\n * <script>DocGenLab.init({ agentKey: 'pk_live_...' })</script>\n *\n * The UMD bundle exposes a global `DocGenLab` object with `init()` and\n * `destroy()` methods that mount/unmount the widget on a hidden div.\n */\n\nimport { createRoot, type Root } from 'react-dom/client';\nimport { createElement } from 'react';\nimport { DocGenLabChat, type DocGenLabChatProps } from './widget';\nimport type { ChatWidgetConfig, ChatWidgetTheme, ChatPosition, Citation, AgentInfo, StreamEvent, ChatMessage } from './types';\n\nexport { DocGenLabChat };\nexport type {\n DocGenLabChatProps,\n ChatWidgetConfig,\n ChatWidgetTheme,\n ChatPosition,\n Citation,\n AgentInfo,\n StreamEvent,\n ChatMessage,\n};\n\n// ─── Vanilla bootstrap ──────────────────────────────────────────────────\n\nlet _root: Root | null = null;\nlet _container: HTMLDivElement | null = null;\n\nexport function init(config: DocGenLabChatProps): void {\n if (typeof document === 'undefined') {\n throw new Error('DocGenLab.init() requires a browser environment.');\n }\n if (_root) {\n // Re-mount on second call (config change)\n _root.render(createElement(DocGenLabChat, config));\n return;\n }\n _container = document.createElement('div');\n _container.id = 'docgenlab-chat-widget-root';\n document.body.appendChild(_container);\n _root = createRoot(_container);\n _root.render(createElement(DocGenLabChat, config));\n}\n\nexport function destroy(): void {\n if (_root) {\n _root.unmount();\n _root = null;\n }\n if (_container) {\n _container.remove();\n _container = null;\n }\n}\n\n// Make sure the UMD global has these too. Vite assigns the default export to\n// the configured `name` ('DocGenLab'); explicitly attach methods so vanilla\n// HTML can use `DocGenLab.init(...)` without an import.\n// (This is a no-op when consumed via ESM imports.)\ndeclare global {\n interface Window {\n DocGenLab?: { init: typeof init; destroy: typeof destroy; DocGenLabChat: typeof DocGenLabChat };\n }\n}\nif (typeof window !== 'undefined') {\n window.DocGenLab = { init, destroy, DocGenLabChat };\n}\n"],"names":["PUBLIC_BASE","VISITOR_KEY","uuid","c","ch","r","getVisitorId","id","e","WidgetClient","opts","extra","resp","file","fd","detail","j","imagePath","url","blob","body","onEvent","ctrl","reader","decoder","buf","value","done","nl","raw","line","evt","DEFAULTS","DocGenLabChat","props","baseUrl","position","enableImageUpload","themeVars","_a","_b","_c","_d","clientRef","useRef","client","open","setOpen","useState","expanded","setExpanded","agent","setAgent","agentError","setAgentError","messages","setMessages","input","setInput","streaming","setStreaming","conversationId","setConversationId","attachedFile","setAttachedFile","attachedPreview","setAttachedPreview","uploadingImage","setUploadingImage","fileInputRef","abortRef","contentRef","scrollRef","useEffect","info","k","stored","clearAttachment","useCallback","stageImage","MAX","onSubmit","userText","previewForTurn","prev","snap","m","i","newChat","displayName","React","svgPlus","v","svgShrink","svgExpand","svgX","idx","MessageBubble","q","svgImage","f","item","it","svgSpinner","svgSend","svgChevronDown","svgChat","message","isLast","agentAvatarUrl","onPickFollowup","UserImage","cleaned","cleanForDisplay","followups","extractFollowups","svgSparkles","ThinkingDots","renderMarkdown","CitationChips","FollowupChips","suggestions","onPick","previewUrl","setUrl","revoke","u","citations","seen","unique","content","match","text","block","lines","l","isOrdered","items","Tag","renderInline","arr","pattern","part","linkMatch","_root","_container","init","config","createElement","createRoot","destroy"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.cjs","sources":["../src/api.ts","../src/widget.tsx","../src/index.ts"],"sourcesContent":["/**\n * Thin client for the /api/v1/public/kb/* surface. No axios — uses native\n * fetch + a manual SSE reader so the bundle stays small.\n *\n * All requests carry two headers:\n * X-DocGenLab-Key — the publishable key (server resolves to agent)\n * X-DocGenLab-Visitor-Id — a stable UUID minted in localStorage\n */\n\nimport type { AgentInfo, StreamEvent, TicketRef } from './types';\n\nconst PUBLIC_BASE = '/api/v1/public/kb';\nconst VISITOR_KEY = 'dgl-visitor-id';\n\n/** Generate a UUID v4. Avoids the `crypto.randomUUID` dependency for older\n * browsers; falls back to a Math.random-based variant. */\nfunction uuid(): string {\n const c = (globalThis as any).crypto;\n if (c && typeof c.randomUUID === 'function') return c.randomUUID();\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n const r = (Math.random() * 16) | 0;\n const v = ch === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nfunction getVisitorId(): string {\n try {\n let id = localStorage.getItem(VISITOR_KEY);\n if (!id) {\n id = uuid();\n localStorage.setItem(VISITOR_KEY, id);\n }\n return id;\n } catch {\n // Storage unavailable (private mode, blocked) — use a session-scoped id.\n return uuid();\n }\n}\n\nexport interface ClientOptions {\n agentKey: string;\n apiBaseUrl: string;\n /** Customer's stable user identifier. When provided, takes precedence\n * over the anonymous-per-browser UUID so conversations follow the user\n * across browsers + devices. Prefixed with 'user:' internally so an\n * attacker can't guess + collide with another user's anonymous UUID. */\n endUserId?: string;\n /** HMAC verification companion (currently passed to the server for\n * future enforcement). */\n endUserHash?: string;\n}\n\nexport class WidgetClient {\n private readonly agentKey: string;\n private readonly baseUrl: string;\n private readonly visitorId: string;\n private readonly endUserHash?: string;\n\n constructor(opts: ClientOptions) {\n this.agentKey = opts.agentKey;\n this.baseUrl = opts.apiBaseUrl.replace(/\\/+$/, '');\n // Customer-supplied id beats the anonymous cookie. The 'user:' prefix\n // ensures the namespace can never collide with an anonymous UUID.\n this.visitorId = opts.endUserId\n ? `user:${opts.endUserId}`\n : getVisitorId();\n this.endUserHash = opts.endUserHash;\n }\n\n private headers(extra?: Record<string, string>): Record<string, string> {\n const base: Record<string, string> = {\n 'X-DocGenLab-Key': this.agentKey,\n 'X-DocGenLab-Visitor-Id': this.visitorId,\n ...(extra || {}),\n };\n // Identity-verification HMAC — server may use this to confirm the\n // claimed visitor id is genuine (Intercom-style). Sent as a separate\n // header so the visitor id itself stays untrusted-but-stable.\n if (this.endUserHash) base['X-DocGenLab-User-Hash'] = this.endUserHash;\n return base;\n }\n\n async getAgent(): Promise<AgentInfo> {\n const resp = await fetch(`${this.baseUrl}${PUBLIC_BASE}/agent`, {\n method: 'GET',\n headers: this.headers(),\n });\n if (!resp.ok) throw new Error(`getAgent failed: ${resp.status}`);\n return resp.json();\n }\n\n /** Load a previous conversation's messages so the widget can show\n * history after a refresh / re-open. The visitor-id header is the\n * authorization — the backend only returns conversations owned by\n * the requesting visitor on this agent. */\n async getConversation(conversationId: string): Promise<any> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/conversations/${encodeURIComponent(conversationId)}`;\n const resp = await fetch(url, { headers: this.headers() });\n if (!resp.ok) throw new Error(`getConversation failed: ${resp.status}`);\n return resp.json();\n }\n\n /** Reconstruct the ticket card that SHOULD currently be on the\n * conversation, based on persisted state. Lets the widget restore\n * raise-ticket / \"already on it\" / created cards after refresh.\n * Returns kind=null when nothing should show. */\n async getTicketCardState(conversationId: string): Promise<{\n kind: 'offer' | 'existing' | 'created' | null;\n conversation_id: string | null;\n connector_type?: string | null;\n connector_name?: string | null;\n ticket_id?: string | null;\n external_ticket_number?: string | null;\n external_url?: string | null;\n status?: string | null;\n }> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/conversations/${encodeURIComponent(conversationId)}/ticket-card`;\n const resp = await fetch(url, { headers: this.headers() });\n if (!resp.ok) throw new Error(`getTicketCardState failed: ${resp.status}`);\n return resp.json();\n }\n\n async uploadImage(file: File): Promise<string> {\n const fd = new FormData();\n fd.append('file', file);\n const resp = await fetch(`${this.baseUrl}${PUBLIC_BASE}/chat-image`, {\n method: 'POST',\n headers: this.headers(), // browser sets Content-Type for FormData\n body: fd,\n });\n if (!resp.ok) {\n let detail = `${resp.status} ${resp.statusText}`;\n try {\n const j = await resp.json();\n detail = j?.detail || detail;\n } catch { /* keep status */ }\n throw new Error(detail);\n }\n const j = await resp.json();\n return j.image_path as string;\n }\n\n /** Fetch a previously-uploaded image as a blob URL. Caller must\n * URL.revokeObjectURL() when done to avoid memory leaks. */\n async fetchImage(imagePath: string): Promise<string> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/chat-image?path=${encodeURIComponent(imagePath)}&key=${encodeURIComponent(this.agentKey)}`;\n const resp = await fetch(url, {\n method: 'GET',\n headers: { 'X-DocGenLab-Visitor-Id': this.visitorId },\n });\n if (!resp.ok) throw new Error(`fetchImage failed: ${resp.status}`);\n const blob = await resp.blob();\n return URL.createObjectURL(blob);\n }\n\n /** Raise a support ticket from a conversation. Requires explicit user\n * consent — the widget only calls this after the user clicks the\n * in-chat \"Raise a ticket\" chip. */\n async raiseTicket(\n conversationId: string,\n body: {\n consent: boolean;\n end_user_email?: string;\n end_user_phone?: string;\n priority?: 'low' | 'medium' | 'high' | 'urgent';\n /** Escape hatch from the \"We're already on it\" card — bypasses\n * the duplicate guard so the user can raise a fresh ticket\n * for a different issue even when a recent one is still open. */\n force_new?: boolean;\n },\n ): Promise<TicketRef> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/conversations/${encodeURIComponent(conversationId)}/raise-ticket`;\n const resp = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-DocGenLab-Key': this.agentKey,\n 'X-DocGenLab-Visitor-Id': this.visitorId,\n ...(this.endUserHash ? { 'X-DocGenLab-User-Hash': this.endUserHash } : {}),\n },\n body: JSON.stringify(body),\n });\n if (!resp.ok) {\n let detail = `raiseTicket failed: ${resp.status}`;\n try { const j = await resp.json(); detail = j.detail || detail; } catch {}\n throw new Error(detail);\n }\n return resp.json();\n }\n\n /** List all tickets for THIS visitor on THIS agent. Used by the widget\n * to hydrate ticket cards on conversation reload and to power the\n * \"Manage tickets\" modal. Optionally filtered by conversation. */\n async listTickets(conversationId?: string): Promise<TicketRef[]> {\n const q = conversationId ? `?conversation_id=${encodeURIComponent(conversationId)}` : '';\n const url = `${this.baseUrl}${PUBLIC_BASE}/tickets${q}`;\n const resp = await fetch(url, {\n headers: {\n 'X-DocGenLab-Key': this.agentKey,\n 'X-DocGenLab-Visitor-Id': this.visitorId,\n },\n });\n if (!resp.ok) throw new Error(`listTickets failed: ${resp.status}`);\n return resp.json();\n }\n\n /** Fetch the latest status of a ticket the user raised. */\n async getTicket(ticketId: string, refresh = false): Promise<TicketRef> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/tickets/${encodeURIComponent(ticketId)}${refresh ? '?refresh=1' : ''}`;\n const resp = await fetch(url, {\n headers: {\n 'X-DocGenLab-Key': this.agentKey,\n 'X-DocGenLab-Visitor-Id': this.visitorId,\n },\n });\n if (!resp.ok) throw new Error(`getTicket failed: ${resp.status}`);\n return resp.json();\n }\n\n /** Fetch a video-source frame attached to a citation chunk.\n * Same auth pattern as fetchImage. */\n async fetchSourceFrame(sourceId: string, framePath: string): Promise<string> {\n const url = `${this.baseUrl}${PUBLIC_BASE}/sources/${encodeURIComponent(sourceId)}/frame?path=${encodeURIComponent(framePath)}&key=${encodeURIComponent(this.agentKey)}`;\n const resp = await fetch(url, {\n method: 'GET',\n headers: { 'X-DocGenLab-Visitor-Id': this.visitorId },\n });\n if (!resp.ok) throw new Error(`fetchSourceFrame failed: ${resp.status}`);\n const blob = await resp.blob();\n return URL.createObjectURL(blob);\n }\n\n /** Stream a chat response via SSE. Returns an abort fn the caller invokes\n * to cancel the stream. */\n streamChat(\n body: { message: string; conversation_id?: string; image_path?: string },\n onEvent: (event: StreamEvent) => void,\n ): () => void {\n const ctrl = new AbortController();\n (async () => {\n try {\n const resp = await fetch(`${this.baseUrl}${PUBLIC_BASE}/chat`, {\n method: 'POST',\n signal: ctrl.signal,\n headers: this.headers({ 'Content-Type': 'application/json', Accept: 'text/event-stream' }),\n body: JSON.stringify(body),\n });\n if (!resp.ok || !resp.body) {\n let detail = `${resp.status} ${resp.statusText}`;\n try { const j = await resp.json(); detail = j?.detail || detail; } catch {}\n onEvent({ type: 'error', error: detail });\n return;\n }\n const reader = resp.body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n let nl;\n while ((nl = buf.indexOf('\\n\\n')) !== -1) {\n const raw = buf.slice(0, nl);\n buf = buf.slice(nl + 2);\n const line = raw.trim();\n if (!line.startsWith('data:')) continue;\n try {\n const evt = JSON.parse(line.slice(5).trim()) as StreamEvent;\n onEvent(evt);\n } catch {\n // Ignore malformed SSE frames\n }\n }\n }\n } catch (e: any) {\n if (e?.name !== 'AbortError') {\n onEvent({ type: 'error', error: e?.message || String(e) });\n }\n }\n })();\n return () => ctrl.abort();\n }\n}\n","import * as React from 'react';\nimport { useCallback, useEffect, useRef, useState, type CSSProperties, type FormEvent } from 'react';\nimport type { ChatMessage, ChatWidgetConfig, AgentInfo, Citation, TicketRef } from './types';\nimport { WidgetClient } from './api';\nimport './styles.css';\n\nconst DEFAULTS = {\n apiBaseUrl: 'https://api.docgenlab.com',\n position: 'bottom-right' as const,\n primary: '#4F46E5',\n primaryText: '#FFFFFF',\n radius: '14px',\n fontFamily: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n greeting: 'How can I help you today?',\n greetingSub: \"Ask anything about your uploaded documents. I'll only answer from what's in the knowledge base.\",\n enableImageUpload: true,\n};\n\nexport interface DocGenLabChatProps extends ChatWidgetConfig {\n /** Called when the widget mounts and successfully resolves the agent. */\n onReady?: (agent: AgentInfo) => void;\n /** Called for unrecoverable errors so the customer can log them. */\n onError?: (err: string) => void;\n}\n\n/**\n * Floating-bubble chat widget. Renders a launcher button bottom-right\n * (or -left) that expands to a chat panel.\n */\nexport function DocGenLabChat(props: DocGenLabChatProps) {\n const baseUrl = props.apiBaseUrl || DEFAULTS.apiBaseUrl;\n const enableImageUpload = props.enableImageUpload !== false;\n\n const clientRef = useRef<WidgetClient | null>(null);\n // Rebuild the client when the customer's user identity changes (sign-in /\n // sign-out flows). We track via a ref-keyed effect rather than rebuilding\n // on every render — props are usually stable but should react to logins.\n const identityKey = `${props.agentKey}::${props.endUserId || ''}::${props.endUserHash || ''}`;\n const lastIdentityRef = useRef<string>('');\n if (!clientRef.current || lastIdentityRef.current !== identityKey) {\n clientRef.current = new WidgetClient({\n agentKey: props.agentKey,\n apiBaseUrl: baseUrl,\n endUserId: props.endUserId,\n endUserHash: props.endUserHash,\n });\n lastIdentityRef.current = identityKey;\n }\n const client = clientRef.current;\n\n // Three-layer config resolution: customer prop > dashboard widget_config\n // (fetched from /public/kb/agent) > library default. Prop always wins so a\n // customer can override per-page without touching the dashboard.\n const [agent, setAgent] = useState<AgentInfo | null>(null);\n const [agentError, setAgentError] = useState<string | null>(null);\n const remote = agent?.widget_config || {};\n\n const resolved = {\n position: (props.position || remote.position || DEFAULTS.position) as 'bottom-right' | 'bottom-left',\n primary: props.theme?.primary || remote.primary_color || DEFAULTS.primary,\n primaryText: props.theme?.primaryText || remote.primary_text_color || DEFAULTS.primaryText,\n radius: props.theme?.radius || remote.radius || DEFAULTS.radius,\n fontFamily: props.theme?.fontFamily || DEFAULTS.fontFamily,\n greeting: props.greeting || remote.greeting || DEFAULTS.greeting,\n agentName: props.agentName || remote.agent_name || agent?.name || 'Assistant',\n agentAvatarUrl: props.agentAvatarUrl || remote.agent_avatar_url || undefined,\n launcherAvatarUrl: remote.launcher_avatar_url || undefined,\n hideBranding: props.hideBranding ?? remote.hide_branding ?? false,\n openOnLoad: props.openOnLoad ?? remote.open_on_load ?? false,\n };\n\n const themeVars: CSSProperties & Record<string, string> = {\n ['--dgl-primary' as any]: resolved.primary,\n ['--dgl-primary-text' as any]: resolved.primaryText,\n ['--dgl-radius' as any]: resolved.radius,\n ['--dgl-font' as any]: resolved.fontFamily,\n };\n\n const [open, setOpen] = useState(resolved.openOnLoad);\n // Expanded: roughly 1.6x the default, capped to viewport on small screens.\n // Toggled by the icon next to close in the header.\n const [expanded, setExpanded] = useState(false);\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [input, setInput] = useState('');\n const [streaming, setStreaming] = useState(false);\n const [conversationId, setConversationId] = useState<string | null>(null);\n const [attachedFile, setAttachedFile] = useState<File | null>(null);\n const [attachedPreview, setAttachedPreview] = useState<string | null>(null);\n const [uploadingImage, setUploadingImage] = useState(false);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const abortRef = useRef<(() => void) | null>(null);\n const contentRef = useRef('');\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Tickets the visitor has raised on THIS agent (across conversations).\n // Used both to power the \"Manage tickets\" modal and to hydrate the\n // latest assistant turn with a ticket card on conversation reload —\n // mirrors the dashboard's hydrateTicketCards helper.\n const [tickets, setTickets] = useState<TicketRef[]>([]);\n const [ticketsModalOpen, setTicketsModalOpen] = useState(false);\n\n // Resolve agent on first open\n useEffect(() => {\n if (!open || agent) return;\n client.getAgent()\n .then((info) => {\n setAgent(info);\n props.onReady?.(info);\n })\n .catch((e: Error) => {\n setAgentError(e.message);\n props.onError?.(e.message);\n });\n }, [open, agent, client, props]);\n\n // Load this visitor's tickets when the panel opens so the badge and\n // modal stay in sync. Refetched after every successful raise/ticket\n // event by appending to the local state.\n useEffect(() => {\n if (!open || props.disableTicketing) return;\n let cancelled = false;\n client.listTickets()\n .then((rows) => { if (!cancelled) setTickets(rows); })\n .catch(() => { /* silent — header just won't show a badge */ });\n return () => { cancelled = true; };\n }, [open, client, props.disableTicketing]);\n\n // Restore conversation on mount — load both the persisted message\n // history AND the ticket-card the backend says should currently be\n // showing. Without the ticket-card call, refreshing the page would\n // wipe any \"Raise a ticket\" / \"We're already on it\" card and the\n // user would have to push back (\"not working\") again to bring it\n // back. The history GET is visitor-id-scoped server-side, so a\n // stale conversation_id from a different visitor returns 404 and we\n // silently clear it.\n useEffect(() => {\n if (!open) return;\n const k = `dgl-chat:${props.agentKey}`;\n const stored = localStorage.getItem(k);\n if (!stored) return;\n let cancelled = false;\n (async () => {\n try {\n const [detail, cardState] = await Promise.all([\n client.getConversation(stored),\n client.getTicketCardState(stored).catch(() => null),\n ]);\n if (cancelled) return;\n const restored: ChatMessage[] = [];\n for (const m of (detail.messages || []) as any[]) {\n if (m.role === 'user') {\n restored.push({\n id: m.id,\n role: 'user',\n content: m.content || '',\n imagePath: m.image_path || undefined,\n });\n } else if (m.role === 'assistant') {\n restored.push({\n id: m.id,\n role: 'assistant',\n content: m.content || '',\n citations: m.retrieved_chunks || undefined,\n });\n }\n }\n // Attach the ticket card to the last assistant turn.\n if (cardState && cardState.kind && restored.length) {\n let attachAt = -1;\n for (let i = restored.length - 1; i >= 0; i--) {\n if (restored[i].role === 'assistant') { attachAt = i; break; }\n }\n if (attachAt >= 0) {\n const msg = restored[attachAt];\n if (cardState.kind === 'offer' && cardState.conversation_id && cardState.connector_type && cardState.connector_name) {\n msg.ticketOffer = {\n conversationId: cardState.conversation_id,\n connectorType: cardState.connector_type,\n connectorName: cardState.connector_name,\n };\n } else if (cardState.kind === 'existing' && cardState.ticket_id && cardState.status) {\n msg.ticketExisting = {\n ticketId: cardState.ticket_id,\n externalNumber: cardState.external_ticket_number || null,\n externalUrl: cardState.external_url || null,\n status: cardState.status,\n };\n } else if (cardState.kind === 'created' && cardState.ticket_id) {\n msg.ticketCreated = {\n id: cardState.ticket_id,\n externalNumber: cardState.external_ticket_number || null,\n externalUrl: cardState.external_url || null,\n };\n }\n }\n }\n setConversationId(stored);\n setMessages(restored);\n } catch {\n // 404 / stale id — clear it so we don't keep retrying.\n localStorage.removeItem(k);\n }\n })();\n return () => { cancelled = true; };\n }, [props.agentKey, client, open]);\n\n // Persist conversation id whenever it changes\n useEffect(() => {\n if (conversationId) {\n localStorage.setItem(`dgl-chat:${props.agentKey}`, conversationId);\n }\n }, [conversationId, props.agentKey]);\n\n // Auto-scroll on new messages\n useEffect(() => {\n if (scrollRef.current) {\n scrollRef.current.scrollTop = scrollRef.current.scrollHeight;\n }\n }, [messages]);\n\n const clearAttachment = useCallback(() => {\n if (attachedPreview) URL.revokeObjectURL(attachedPreview);\n setAttachedFile(null);\n setAttachedPreview(null);\n }, [attachedPreview]);\n\n const stageImage = useCallback((file: File) => {\n if (!file.type.startsWith('image/')) return;\n const MAX = 10 * 1024 * 1024;\n if (file.size > MAX) return;\n if (attachedPreview) URL.revokeObjectURL(attachedPreview);\n setAttachedFile(file);\n setAttachedPreview(URL.createObjectURL(file));\n }, [attachedPreview]);\n\n const onSubmit = async (e: FormEvent) => {\n e.preventDefault();\n if (!input.trim() || streaming || uploadingImage) return;\n const userText = input.trim();\n\n // Upload image (if any) first\n let imagePath: string | undefined;\n let previewForTurn: string | undefined;\n if (attachedFile) {\n try {\n setUploadingImage(true);\n imagePath = await client.uploadImage(attachedFile);\n } catch (e: any) {\n props.onError?.(e?.message || 'Image upload failed');\n setUploadingImage(false);\n return;\n }\n setUploadingImage(false);\n previewForTurn = attachedPreview || undefined;\n }\n\n setInput('');\n contentRef.current = '';\n setMessages((prev) => [\n ...prev,\n { role: 'user', content: userText, imagePath, imagePreviewUrl: previewForTurn },\n { role: 'assistant', content: '', streaming: true },\n ]);\n setStreaming(true);\n // Clear the staged attachment; the turn owns the preview URL now\n setAttachedFile(null);\n setAttachedPreview(null);\n\n abortRef.current = client.streamChat(\n { message: userText, conversation_id: conversationId || undefined, image_path: imagePath },\n (evt) => {\n if (evt.type === 'conversation') {\n setConversationId(evt.conversation_id);\n } else if (evt.type === 'token') {\n contentRef.current += evt.content;\n const snap = contentRef.current;\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant' ? { ...m, content: snap } : m\n ));\n } else if (evt.type === 'citations') {\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant' ? { ...m, citations: evt.citations } : m\n ));\n } else if (evt.type === 'refused') {\n contentRef.current = evt.content;\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? { ...m, content: evt.content, refused: true }\n : m\n ));\n } else if (evt.type === 'ticket_offer') {\n // Attach the offer to the latest refusal so we render\n // a \"Raise a ticket\" chip. Skipped silently when the\n // customer set disableTicketing.\n if (props.disableTicketing) return;\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? {\n ...m,\n ticketOffer: {\n conversationId: evt.conversation_id,\n connectorType: evt.connector_type,\n connectorName: evt.connector_name,\n },\n }\n : m\n ));\n } else if (evt.type === 'ticket_existing') {\n // An open ticket already exists — surface reassurance.\n if (props.disableTicketing) return;\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? {\n ...m,\n ticketExisting: {\n ticketId: evt.ticket_id,\n externalNumber: evt.external_ticket_number,\n externalUrl: evt.external_url,\n status: evt.status,\n },\n }\n : m\n ));\n } else if (evt.type === 'ticket_status_card') {\n // Status query intent — replace the markdown reply with\n // a rich Jira-style card.\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? {\n ...m,\n ticketStatus: {\n ticketId: evt.ticket_id,\n externalNumber: evt.external_number,\n externalUrl: evt.external_url,\n status: evt.status,\n title: evt.title,\n priority: evt.priority,\n lastUpdate: evt.last_update,\n assignedTo: evt.assigned_to,\n createdAt: evt.created_at,\n },\n }\n : m\n ));\n } else if (evt.type === 'done') {\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? { ...m, streaming: false, id: evt.message_id, cacheHit: evt.cache_hit }\n : m\n ));\n setStreaming(false);\n } else if (evt.type === 'error') {\n setMessages((prev) => prev.map((m, i) =>\n i === prev.length - 1 && m.role === 'assistant'\n ? { ...m, content: `Error: ${evt.error}`, streaming: false, refused: true }\n : m\n ));\n setStreaming(false);\n props.onError?.(evt.error);\n }\n },\n );\n };\n\n const newChat = () => {\n if (abortRef.current) abortRef.current();\n setMessages([]);\n setConversationId(null);\n setStreaming(false);\n localStorage.removeItem(`dgl-chat:${props.agentKey}`);\n clearAttachment();\n };\n\n return (\n <div className={`dgl-root dgl-pos-${resolved.position}`} style={themeVars}>\n {open && (\n <div className={`dgl-panel ${expanded ? 'dgl-panel-expanded' : ''}`}>\n <div className=\"dgl-header\">\n <div className=\"dgl-header-info\">\n {resolved.agentAvatarUrl ? (\n <img src={resolved.agentAvatarUrl} alt=\"\" className=\"dgl-avatar\" />\n ) : (\n <div className=\"dgl-avatar dgl-avatar-fallback dgl-avatar-fallback-light\">\n {resolved.agentName.slice(0, 1).toUpperCase()}\n </div>\n )}\n <div className=\"dgl-header-text\">\n <div className=\"dgl-title\">{resolved.agentName}</div>\n {agent?.org_name && (\n <div className=\"dgl-subtitle\">{agent.org_name}</div>\n )}\n </div>\n </div>\n <div className=\"dgl-header-actions\">\n {!props.disableTicketing && tickets.length > 0 && (\n <button\n type=\"button\"\n onClick={() => setTicketsModalOpen(true)}\n className=\"dgl-tix-btn\"\n title=\"Your tickets\"\n aria-label=\"Your tickets\"\n >\n {svgLifebuoy()}\n <span>Tickets</span>\n <span className=\"dgl-tix-btn-badge\">{tickets.length}</span>\n </button>\n )}\n <button\n type=\"button\"\n onClick={newChat}\n className=\"dgl-icon-btn\"\n title=\"New chat\"\n aria-label=\"New chat\"\n >\n {svgPlus()}\n </button>\n <button\n type=\"button\"\n onClick={() => setExpanded((v) => !v)}\n className=\"dgl-icon-btn dgl-hide-on-mobile\"\n title={expanded ? 'Restore size' : 'Expand view'}\n aria-label={expanded ? 'Restore size' : 'Expand view'}\n >\n {expanded ? svgShrink() : svgExpand()}\n </button>\n <button\n type=\"button\"\n onClick={() => setOpen(false)}\n className=\"dgl-icon-btn\"\n title=\"Close\"\n aria-label=\"Close\"\n >\n {svgX()}\n </button>\n </div>\n </div>\n\n {ticketsModalOpen && (\n <ManageTicketsModal\n tickets={tickets}\n onClose={() => setTicketsModalOpen(false)}\n onRefresh={async () => {\n try {\n const rows = await client.listTickets();\n setTickets(rows);\n } catch { /* silent */ }\n }}\n />\n )}\n\n <div className=\"dgl-messages\" ref={scrollRef}>\n {messages.length === 0 && !agentError && (\n <div className=\"dgl-empty\">\n <div className=\"dgl-empty-icon\">{svgSparkles()}</div>\n <div className=\"dgl-empty-text\">\n {resolved.greeting}\n </div>\n <div className=\"dgl-empty-sub\">\n {agent?.description || DEFAULTS.greetingSub}\n </div>\n </div>\n )}\n {agentError && (\n <div className=\"dgl-error\">\n Couldn't load the assistant: {agentError}\n </div>\n )}\n {messages.map((m, idx) => (\n <MessageBubble\n key={idx}\n message={m}\n client={client}\n isLast={idx === messages.length - 1}\n agentAvatarUrl={resolved.agentAvatarUrl}\n onPickFollowup={(q) => {\n setInput(q);\n // Don't auto-send; user reviews + presses send.\n // Same UX as the dashboard.\n }}\n defaultEmail={props.endUserEmail}\n defaultPhone={props.endUserPhone}\n conversationId={conversationId || undefined}\n onTicketCreated={(target, t) => {\n setMessages((prev) => prev.map((mm) => (\n mm === target\n ? {\n ...mm,\n // Either an existing-issue card OR a fresh offer\n // can land here — clear both, render created.\n ticketOffer: undefined,\n ticketExisting: undefined,\n ticketCreated: {\n id: t.id,\n externalNumber: t.external_ticket_number,\n externalUrl: t.external_url,\n },\n }\n : mm\n )));\n // Keep the header badge + modal list in sync without\n // a round-trip to the server.\n setTickets((prev) => [t, ...prev.filter((x) => x.id !== t.id)]);\n }}\n />\n ))}\n </div>\n\n <form className=\"dgl-composer\" onSubmit={onSubmit}>\n {attachedPreview && (\n <div className=\"dgl-staged-image\">\n <img src={attachedPreview} alt=\"attachment\" />\n <button\n type=\"button\"\n onClick={clearAttachment}\n className=\"dgl-staged-remove\"\n aria-label=\"Remove image\"\n >\n {svgX()}\n </button>\n </div>\n )}\n <div className=\"dgl-composer-row\">\n {enableImageUpload && (\n <>\n <button\n type=\"button\"\n className=\"dgl-icon-btn\"\n onClick={() => fileInputRef.current?.click()}\n disabled={streaming || uploadingImage}\n title=\"Attach image\"\n aria-label=\"Attach image\"\n >\n {svgImage()}\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/webp,image/gif\"\n style={{ display: 'none' }}\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) stageImage(f);\n if (e.target) e.target.value = '';\n }}\n />\n </>\n )}\n <input\n className=\"dgl-input\"\n value={input}\n onChange={(e) => setInput(e.target.value)}\n placeholder={\n streaming\n ? 'Thinking…'\n : attachedPreview\n ? 'Describe what to know about this image…'\n : 'Type your question…'\n }\n disabled={streaming}\n onPaste={(e) => {\n if (!enableImageUpload) return;\n const item = Array.from(e.clipboardData?.items || []).find(\n (it) => it.kind === 'file' && it.type.startsWith('image/')\n );\n if (item) {\n const f = item.getAsFile();\n if (f) { e.preventDefault(); stageImage(f); }\n }\n }}\n />\n <button\n type=\"submit\"\n className=\"dgl-send-btn\"\n disabled={!input.trim() || streaming || uploadingImage}\n aria-label=\"Send\"\n >\n {streaming || uploadingImage ? svgSpinner() : svgSend()}\n </button>\n </div>\n {!resolved.hideBranding && (\n <div className=\"dgl-branding\">\n Powered by <a href=\"https://docgenlab.com\" target=\"_blank\" rel=\"noopener noreferrer\">DocGenLab</a>\n </div>\n )}\n </form>\n </div>\n )}\n\n <button\n type=\"button\"\n className=\"dgl-launcher\"\n onClick={() => setOpen((v) => !v)}\n aria-label={open ? 'Close chat' : 'Open chat'}\n >\n {open\n ? svgChevronDown()\n : resolved.launcherAvatarUrl\n ? <img src={resolved.launcherAvatarUrl} alt=\"\" className=\"dgl-launcher-avatar\" />\n : svgChat()}\n </button>\n </div>\n );\n}\n\n// ─── Message bubble ─────────────────────────────────────────────────────\n\nfunction MessageBubble({\n message,\n client,\n isLast,\n agentAvatarUrl,\n onPickFollowup,\n defaultEmail,\n defaultPhone,\n conversationId,\n onTicketCreated,\n}: {\n message: ChatMessage;\n client: WidgetClient;\n isLast: boolean;\n agentAvatarUrl?: string;\n onPickFollowup: (q: string) => void;\n defaultEmail?: string;\n defaultPhone?: string;\n /** Current conversation id — needed by TicketExistingCard so the\n * \"Different issue? Raise new ticket\" escape hatch can POST to the\n * right /raise-ticket endpoint. */\n conversationId?: string;\n onTicketCreated?: (message: ChatMessage, t: TicketRef) => void;\n}) {\n if (message.role === 'user') {\n return (\n <div className=\"dgl-msg dgl-msg-user\">\n <div className=\"dgl-bubble dgl-bubble-user\">\n {(message.imagePath || message.imagePreviewUrl) && (\n <UserImage client={client} imagePath={message.imagePath} previewUrl={message.imagePreviewUrl} />\n )}\n {message.content}\n </div>\n </div>\n );\n }\n const cleaned = cleanForDisplay(message.content);\n const followups = !message.streaming ? extractFollowups(message.content) : [];\n return (\n <div className=\"dgl-msg dgl-msg-assistant\">\n {agentAvatarUrl ? (\n <img src={agentAvatarUrl} className=\"dgl-avatar\" alt=\"\" />\n ) : (\n <div className=\"dgl-avatar dgl-avatar-fallback\">{svgSparkles()}</div>\n )}\n <div className=\"dgl-msg-body\">\n {message.refused ? (\n <div className=\"dgl-refused\">{cleaned}</div>\n ) : message.ticketStatus ? (\n /* Status query — suppress the markdown body and render\n the rich Jira-style card on its own. */\n <TicketStatusCard ticket={message.ticketStatus} />\n ) : (\n <div className=\"dgl-assistant-text\">\n {/* Tokens haven't started arriving yet — show thinking dots\n instead of an empty bubble. */}\n {message.streaming && !cleaned ? (\n <ThinkingDots />\n ) : (\n <>\n {renderMarkdown(cleaned)}\n {message.streaming && <span className=\"dgl-typing-cursor\">▍</span>}\n </>\n )}\n </div>\n )}\n {!message.streaming && !message.refused && !!message.citations?.length && !message.ticketStatus && (\n <CitationChips citations={message.citations} client={client} />\n )}\n {/* Ticket card — priority order: created > existing > offer.\n Skipped when ticketStatus is the message itself (rendered above). */}\n {!message.streaming && !message.ticketStatus && message.ticketCreated ? (\n <TicketCreatedChip created={message.ticketCreated} />\n ) : !message.streaming && !message.ticketStatus && message.ticketExisting ? (\n <TicketExistingCard\n existing={message.ticketExisting}\n client={client}\n conversationId={conversationId}\n defaultEmail={defaultEmail}\n defaultPhone={defaultPhone}\n onNewTicketRaised={(t) => onTicketCreated?.(message, t)}\n />\n ) : !message.streaming && !message.ticketStatus && message.ticketOffer ? (\n <RaiseTicketChip\n client={client}\n offer={message.ticketOffer}\n defaultEmail={defaultEmail}\n defaultPhone={defaultPhone}\n onCreated={(t) => onTicketCreated?.(message, t)}\n />\n ) : null}\n {followups.length > 0 && (\n <FollowupChips suggestions={followups} onPick={onPickFollowup} />\n )}\n </div>\n </div>\n );\n}\n\n/** Clickable chips below an assistant answer suggesting next questions.\n * Clicking pre-fills the input — the user reviews + presses send. */\nfunction FollowupChips({\n suggestions,\n onPick,\n}: {\n suggestions: string[];\n onPick: (q: string) => void;\n}) {\n return (\n <div className=\"dgl-followups\">\n <div className=\"dgl-followups-label\">Continue exploring</div>\n <div className=\"dgl-followups-list\">\n {suggestions.map((q, i) => (\n <button\n key={i}\n type=\"button\"\n className=\"dgl-followup-chip\"\n onClick={() => onPick(q)}\n >\n {q}\n </button>\n ))}\n </div>\n </div>\n );\n}\n\nfunction UserImage({\n client,\n imagePath,\n previewUrl,\n}: { client: WidgetClient; imagePath?: string; previewUrl?: string }) {\n const [url, setUrl] = useState<string | null>(previewUrl || null);\n const [open, setOpen] = useState(false);\n\n useEffect(() => {\n if (previewUrl || !imagePath) return;\n let revoke: string | null = null;\n client.fetchImage(imagePath)\n .then((u) => { revoke = u; setUrl(u); })\n .catch(() => setUrl(null));\n return () => { if (revoke) URL.revokeObjectURL(revoke); };\n }, [client, imagePath, previewUrl]);\n\n // Lightbox lifecycle — Escape closes, body scroll locked while open.\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); };\n window.addEventListener('keydown', onKey);\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n window.removeEventListener('keydown', onKey);\n document.body.style.overflow = prev;\n };\n }, [open]);\n\n if (!url) return null;\n return (\n <>\n <button\n type=\"button\"\n onClick={() => setOpen(true)}\n className=\"dgl-user-image-btn\"\n aria-label=\"View image\"\n >\n <img src={url} className=\"dgl-user-image\" alt=\"attached\" />\n </button>\n {open && (\n <div\n className=\"dgl-lightbox\"\n role=\"dialog\"\n aria-modal=\"true\"\n onClick={() => setOpen(false)}\n >\n <button\n type=\"button\"\n className=\"dgl-lightbox-close\"\n onClick={(e) => { e.stopPropagation(); setOpen(false); }}\n aria-label=\"Close image\"\n >\n {svgX()}\n </button>\n <img\n src={url}\n className=\"dgl-lightbox-img\"\n alt=\"attached\"\n onClick={(e) => e.stopPropagation()}\n />\n </div>\n )}\n </>\n );\n}\n\nfunction CitationChips({ citations, client }: { citations: Citation[]; client: WidgetClient }) {\n // Dedupe by source; pick the best-scored chunk as the representative\n // (its frame_path / heading is what we'll show in the popover).\n const bySource: Record<string, Citation> = {};\n for (const c of citations) {\n const prev = bySource[c.source_id];\n if (!prev || c.score > prev.score) bySource[c.source_id] = c;\n }\n const unique = Object.values(bySource)\n .sort((a, b) => b.score - a.score)\n .slice(0, 3); // cap to 3 to match dashboard behaviour\n const hidden = Object.keys(bySource).length - unique.length;\n if (!unique.length) return null;\n\n const [openId, setOpenId] = useState<string | null>(null);\n\n return (\n <div className=\"dgl-citations\">\n {unique.map((c) => (\n <CitationChip\n key={c.chunk_id}\n citation={c}\n client={client}\n isOpen={openId === c.chunk_id}\n onToggle={() => setOpenId(openId === c.chunk_id ? null : c.chunk_id)}\n />\n ))}\n {hidden > 0 && (\n <span className=\"dgl-citation-more\">+{hidden} more</span>\n )}\n </div>\n );\n}\n\n/** One citation chip with an expandable popover showing the frame\n * thumbnail (for video sources) + heading breadcrumb + snippet. */\nfunction CitationChip({\n citation, client, isOpen, onToggle,\n}: { citation: Citation; client: WidgetClient; isOpen: boolean; onToggle: () => void }) {\n const cit = citation;\n const isVideo = !!cit.frame_path;\n const breadcrumb = cit.heading\n ? `${cit.heading}${cit.subheading ? ' › ' + cit.subheading : ''}`\n : null;\n const stamp = cit.start_seconds != null\n ? `${Math.floor(cit.start_seconds / 60)}:${String(cit.start_seconds % 60).padStart(2, '0')}`\n : null;\n\n return (\n <span className=\"dgl-citation-wrap\">\n <button\n type=\"button\"\n className={`dgl-citation ${isOpen ? 'dgl-citation-open' : ''}`}\n onClick={onToggle}\n title={cit.snippet || ''}\n >\n {isVideo && <span className=\"dgl-citation-icon\">▶</span>}\n {cit.source_name}\n {stamp && <span className=\"dgl-citation-stamp\"> · {stamp}</span>}\n {cit.page && <span className=\"dgl-citation-stamp\"> · p{cit.page}</span>}\n </button>\n {isOpen && (\n <div className=\"dgl-citation-popover\">\n {cit.frame_path && (\n <CitationFrame\n client={client}\n sourceId={cit.source_id}\n framePath={cit.frame_path}\n />\n )}\n {breadcrumb && (\n <div className=\"dgl-citation-breadcrumb\">{breadcrumb}</div>\n )}\n {cit.snippet && (\n <div className=\"dgl-citation-snippet\">{cit.snippet}</div>\n )}\n </div>\n )}\n </span>\n );\n}\n\n/** Lazy-loads a citation frame thumbnail via the auth-gated public endpoint. */\nfunction CitationFrame({\n client, sourceId, framePath,\n}: { client: WidgetClient; sourceId: string; framePath: string }) {\n const [url, setUrl] = useState<string | null>(null);\n useEffect(() => {\n let revoke: string | null = null;\n client.fetchSourceFrame(sourceId, framePath)\n .then((u) => { revoke = u; setUrl(u); })\n .catch(() => setUrl(null));\n return () => { if (revoke) URL.revokeObjectURL(revoke); };\n }, [client, sourceId, framePath]);\n if (!url) return <div className=\"dgl-citation-frame-loading\" />;\n return (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"dgl-citation-frame-link\">\n <img src={url} alt=\"\" className=\"dgl-citation-frame\" />\n </a>\n );\n}\n\n/** Pull the suggested follow-up questions out of the trailing\n * <followups>...</followups> block (max 3, 4-120 chars each). Returns []\n * if the block is missing, mid-stream, or empty. */\nfunction extractFollowups(content: string): string[] {\n const match = content.match(/<followups>([\\s\\S]*?)<\\/followups>/i);\n if (!match) return [];\n return match[1]\n .split('\\n')\n .map((line) => line.trim())\n .map((line) => line.replace(/^[-*•\\d.)\\s\"']+|[\"']$/g, '').trim())\n .filter((line) => line.length >= 4 && line.length <= 120)\n .slice(0, 3);\n}\n\n/** Strip citation markers, [Section: ...] tags, [doc:abc...] refs, the\n * trailing <followups>...</followups> block, and any leftover orphan\n * punctuation. Ported from the dashboard's cleanCitations so the widget\n * matches the main app's chat exactly.\n *\n * Why this is needed: the system prompt asks the LLM not to emit inline\n * citations, but it sometimes leaks `[doc:11]` / `[1]` / etc. anyway. The\n * user-visible answer must be clean — citations render as separate chips. */\nfunction cleanForDisplay(text: string): string {\n // Rule 2 mixed-pattern strip — only when stripping leaves real content.\n // A whole-message refusal (sometimes followed by empty <followups>)\n // must NOT be stripped. The followups block is subtracted first so the\n // length check doesn't see an empty tag as \"real content\".\n const REFUSAL_RE = /\\s*I\\s+(don'?t|do not)\\s+have\\s+(?:specific|enough|that|the|any)?\\s*information\\s+on\\s+(?:this|that)[^.]*?\\.(?:\\s*Please\\s+(?:contact|reach\\s*out\\s+to)\\s+(?:your\\s+)?(?:support|admin)[^.]*?\\.)?/gi;\n const FOLLOWUPS_RE = /\\n*<followups>[\\s\\S]*?(<\\/followups>|$)/gi;\n const withoutFollowups = text.replace(FOLLOWUPS_RE, '');\n const remainingAfterRefusal = withoutFollowups.replace(REFUSAL_RE, '').trim();\n const isPureRefusal = (\n withoutFollowups.trim().length > 0\n && remainingAfterRefusal.length < 20\n );\n const stage1 = isPureRefusal ? text : text.replace(REFUSAL_RE, '');\n\n return stage1\n .replace(/\\n*<followups>[\\s\\S]*?(<\\/followups>|$)/gi, '')\n .replace(/\\s*\\[\\s*Section:[^\\]]*\\]?/gi, '')\n .replace(/\\s*\\[\\s*doc:[^\\]]*\\]?/gi, '')\n .replace(/\\s*\\[\\s*(?:document|doc|source|ref|reference)[^\\]]*\\]?/gi, '')\n .replace(/\\s*\\[\\s*(?:p\\.?\\s*)?\\d+(?:\\s*[,–-]\\s*\\d+)*\\s*\\]/gi, '')\n .replace(/[,;]?\\s*doc:\\s*[0-9a-fA-F][0-9a-fA-F-]{6,}\\]?/gi, '')\n .replace(/[,;]\\s*(?:\\d+|doc:?\\s*[0-9a-fA-F-]+)\\s*\\]?/gi, '')\n .replace(/([\\w%])\\s*\\]/g, '$1')\n .replace(/\\s+([,.;:!?])/g, '$1')\n .replace(/[ \\t]+/g, ' ')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\n/** Minimal markdown → React renderer for assistant answers. Handles the\n * patterns the system prompt emits: **bold**, `inline code`, paragraph\n * breaks, and `-` / `*` / `1.` lists. Deliberately no full markdown\n * parser to keep the bundle small — for richer needs, the customer can\n * override by post-processing `onToken` themselves later. */\nfunction renderMarkdown(text: string): React.ReactNode {\n // Split into paragraphs first (blank-line separated)\n const blocks = text.split(/\\n{2,}/);\n return blocks.map((block, i) => {\n const lines = block.split('\\n');\n const listMatch = lines.every((l) => /^(\\s*)([-*]|\\d+\\.)\\s/.test(l));\n if (listMatch && lines.length > 0) {\n const isOrdered = /^\\d+\\./.test(lines[0].trim());\n const items = lines.map((l) => l.replace(/^\\s*(?:[-*]|\\d+\\.)\\s+/, ''));\n const Tag = isOrdered ? 'ol' : 'ul';\n return (\n <Tag key={i} className={`dgl-md-list ${isOrdered ? 'dgl-md-ol' : 'dgl-md-ul'}`}>\n {items.map((it, j) => (\n <li key={j}>{renderInline(it)}</li>\n ))}\n </Tag>\n );\n }\n return (\n <p key={i} className=\"dgl-md-p\">\n {block.split('\\n').map((line, j, arr) => (\n <React.Fragment key={j}>\n {renderInline(line)}\n {j < arr.length - 1 && <br />}\n </React.Fragment>\n ))}\n </p>\n );\n });\n}\n\n/** Inline markdown: **bold**, *italic*, `code`, [text](url). */\nfunction renderInline(text: string): React.ReactNode {\n // Tokenize. We avoid a full parser; this regex captures the supported\n // patterns in order of precedence (code first so it shields its contents).\n const pattern = /(`[^`]+`|\\*\\*[^*\\n]+\\*\\*|\\*[^*\\n]+\\*|\\[[^\\]]+\\]\\([^)]+\\))/g;\n const parts = text.split(pattern);\n return parts.map((part, idx) => {\n if (!part) return null;\n if (part.startsWith('`') && part.endsWith('`')) {\n return <code key={idx} className=\"dgl-md-code\">{part.slice(1, -1)}</code>;\n }\n if (part.startsWith('**') && part.endsWith('**')) {\n return <strong key={idx}>{part.slice(2, -2)}</strong>;\n }\n if (part.startsWith('*') && part.endsWith('*') && part.length > 2) {\n return <em key={idx}>{part.slice(1, -1)}</em>;\n }\n const linkMatch = part.match(/^\\[([^\\]]+)\\]\\(([^)]+)\\)$/);\n if (linkMatch) {\n return (\n <a key={idx} href={linkMatch[2]} target=\"_blank\" rel=\"noopener noreferrer\" className=\"dgl-md-link\">\n {linkMatch[1]}\n </a>\n );\n }\n return <React.Fragment key={idx}>{part}</React.Fragment>;\n });\n}\n\n/** Bouncing-dots loading indicator shown after Send but before the first\n * token arrives. Matches the dashboard's ThinkingDots cadence. */\nfunction ThinkingDots() {\n return (\n <span className=\"dgl-thinking\">\n <span className=\"dgl-thinking-dot\" />\n <span className=\"dgl-thinking-dot\" />\n <span className=\"dgl-thinking-dot\" />\n </span>\n );\n}\n\n// ─── Ticket escalation UI ────────────────────────────────────────────────\n// All four card states share the same _TicketCardShell layout so the family\n// of cards looks consistent: top accent stripe, branded icon puck, title,\n// pills, body, footer. Matches the dashboard's Jira/Linear style.\n\nconst _TICKET_STATUS_STYLE: Record<string, { label: string; stripe: string; iconBg: string; pillBg: string; pillFg: string }> = {\n open: { label: 'Open', stripe: 'linear-gradient(90deg,#3b82f6,#6366f1)', iconBg: '#3b82f6', pillBg: '#dbeafe', pillFg: '#1e40af' },\n in_progress: { label: 'In progress', stripe: 'linear-gradient(90deg,#8b5cf6,#d946ef)', iconBg: '#8b5cf6', pillBg: '#ede9fe', pillFg: '#5b21b6' },\n on_hold: { label: 'On hold', stripe: 'linear-gradient(90deg,#f59e0b,#f97316)', iconBg: '#f59e0b', pillBg: '#fef3c7', pillFg: '#92400e' },\n resolved: { label: 'Resolved', stripe: 'linear-gradient(90deg,#10b981,#14b8a6)', iconBg: '#10b981', pillBg: '#d1fae5', pillFg: '#065f46' },\n closed: { label: 'Closed', stripe: 'linear-gradient(90deg,#94a3b8,#64748b)', iconBg: '#64748b', pillBg: '#f1f5f9', pillFg: '#334155' },\n cancelled: { label: 'Cancelled', stripe: 'linear-gradient(90deg,#ef4444,#f43f5e)', iconBg: '#ef4444', pillBg: '#fee2e2', pillFg: '#991b1b' },\n};\n\nconst _TICKET_PRIORITY_STYLE: Record<string, { bg: string; fg: string }> = {\n low: { bg: '#f1f5f9', fg: '#475569' },\n medium: { bg: '#dbeafe', fg: '#1e40af' },\n high: { bg: '#fef3c7', fg: '#92400e' },\n urgent: { bg: '#fee2e2', fg: '#991b1b' },\n};\n\nfunction _ticketRelative(iso: string | null | undefined): string {\n if (!iso) return '—';\n const d = new Date(iso);\n const diff = Date.now() - d.getTime();\n if (Number.isNaN(diff)) return iso;\n const min = Math.floor(diff / 60_000);\n if (min < 1) return 'just now';\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const day = Math.floor(hr / 24);\n if (day < 7) return `${day}d ago`;\n return d.toLocaleDateString();\n}\n\n/** RaiseTicketChip — inline form, no modal. Uses endUserEmail prop when\n * set; falls back to an inline input when the user is anonymous. */\nfunction RaiseTicketChip({\n client, offer, defaultEmail, defaultPhone, onCreated,\n}: {\n client: WidgetClient;\n offer: { conversationId: string; connectorType: string; connectorName: string };\n defaultEmail?: string;\n defaultPhone?: string;\n onCreated: (t: TicketRef) => void;\n}) {\n const [email, setEmail] = useState(defaultEmail || '');\n const [phone, setPhone] = useState(defaultPhone || '');\n const [editEmail, setEditEmail] = useState(!defaultEmail);\n const [priority, setPriority] = useState<'low' | 'medium' | 'high' | 'urgent'>('medium');\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async () => {\n if (!email.trim()) {\n setError('Email is required so the team can follow up.');\n return;\n }\n setSubmitting(true);\n setError(null);\n try {\n const t = await client.raiseTicket(offer.conversationId, {\n consent: true,\n end_user_email: email.trim(),\n end_user_phone: phone.trim() || undefined,\n priority,\n });\n onCreated(t);\n } catch (e: any) {\n setError(e?.message || 'Could not create ticket. Try again.');\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"dgl-ticket-card\">\n <div className=\"dgl-ticket-card-stripe\" style={{ background: 'linear-gradient(90deg,#6366f1,#8b5cf6)' }} />\n <div className=\"dgl-ticket-card-body\">\n <div className=\"dgl-ticket-card-head\">\n <div className=\"dgl-ticket-card-icon\" style={{ background: 'linear-gradient(135deg,#6366f1,#8b5cf6,#ec4899)' }}>\n {svgLifebuoy()}\n </div>\n <div className=\"dgl-ticket-card-titles\">\n <div className=\"dgl-ticket-card-eyebrow\">Support escalation</div>\n <div className=\"dgl-ticket-card-title\">Need a human to look at this?</div>\n </div>\n </div>\n <div className=\"dgl-ticket-card-desc\">\n We'll summarise this chat and raise a ticket. Our team will follow up on the email below.\n </div>\n <div className=\"dgl-ticket-form-grid\">\n <div>\n <div className=\"dgl-ticket-field-label\">Reply to</div>\n {editEmail ? (\n <input\n type=\"email\"\n className=\"dgl-ticket-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n onBlur={() => email && setEditEmail(false)}\n placeholder=\"you@example.com\"\n autoFocus\n />\n ) : (\n <button\n type=\"button\"\n className=\"dgl-ticket-email-link\"\n onClick={() => setEditEmail(true)}\n title=\"Click to change\"\n >\n {email || 'Set email'} <span className=\"dgl-ticket-email-change\">(change)</span>\n </button>\n )}\n </div>\n <div>\n <div className=\"dgl-ticket-field-label\">Priority</div>\n <select\n className=\"dgl-ticket-input\"\n value={priority}\n onChange={(e) => setPriority(e.target.value as any)}\n >\n <option value=\"low\">Low</option>\n <option value=\"medium\">Medium</option>\n <option value=\"high\">High</option>\n <option value=\"urgent\">Urgent</option>\n </select>\n </div>\n </div>\n {error && <div className=\"dgl-ticket-error\">{error}</div>}\n <div className=\"dgl-ticket-card-footer\">\n <span className=\"dgl-ticket-hint\">\n The bot writes the title + description from this chat.\n </span>\n <button\n type=\"button\"\n className=\"dgl-ticket-submit\"\n onClick={submit}\n disabled={submitting || !email.trim()}\n >\n {submitting ? svgSpinner() : svgLifebuoy()}\n <span>{submitting ? 'Submitting…' : 'Submit ticket'}</span>\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction TicketCreatedChip({ created }: { created: { id: string; externalNumber: string | null; externalUrl: string | null } }) {\n const s = _TICKET_STATUS_STYLE.open;\n return (\n <div className=\"dgl-ticket-card\">\n <div className=\"dgl-ticket-card-stripe\" style={{ background: 'linear-gradient(90deg,#10b981,#14b8a6)' }} />\n <div className=\"dgl-ticket-card-body\">\n <div className=\"dgl-ticket-card-head\">\n <div className=\"dgl-ticket-card-icon\" style={{ background: 'linear-gradient(135deg,#10b981,#14b8a6)' }}>\n {svgCheck()}\n </div>\n <div className=\"dgl-ticket-card-titles\">\n <div className=\"dgl-ticket-card-eyebrow\" style={{ color: '#059669' }}>Ticket created</div>\n <div className=\"dgl-ticket-card-title\">#{created.externalNumber || created.id.slice(0, 8)}</div>\n </div>\n {created.externalUrl && (\n <a className=\"dgl-ticket-open-btn\" href={created.externalUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Open\n </a>\n )}\n </div>\n <div className=\"dgl-ticket-pills\">\n <span className=\"dgl-ticket-pill\" style={{ background: s.pillBg, color: s.pillFg }}>\n <span className=\"dgl-ticket-pill-dot\" style={{ background: s.iconBg }} /> Open\n </span>\n </div>\n <div className=\"dgl-ticket-card-desc\">\n Support team has been notified — they'll follow up directly on your email.\n </div>\n </div>\n </div>\n );\n}\n\nfunction TicketExistingCard({\n existing,\n client,\n conversationId,\n defaultEmail,\n defaultPhone,\n onNewTicketRaised,\n}: {\n existing: { ticketId: string; externalNumber: string | null; externalUrl: string | null; status: string };\n client: WidgetClient;\n conversationId?: string;\n defaultEmail?: string;\n defaultPhone?: string;\n onNewTicketRaised?: (t: TicketRef) => void;\n}) {\n const s = _TICKET_STATUS_STYLE[existing.status] || _TICKET_STATUS_STYLE.open;\n // Escape hatch: \"Different issue? Raise new ticket\" — when the smart\n // heuristic didn't catch a new topic, the user can still force-create\n // a fresh ticket. The form mirrors RaiseTicketChip's inline UX.\n const [raiseMode, setRaiseMode] = useState(false);\n const [email, setEmail] = useState(defaultEmail || '');\n const [priority, setPriority] = useState<'low' | 'medium' | 'high' | 'urgent'>('medium');\n const [submitting, setSubmitting] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n\n const submit = async () => {\n if (!email.trim()) {\n setErr('Email is required so the team can follow up.');\n return;\n }\n if (!conversationId) {\n setErr('Conversation not available yet.');\n return;\n }\n setSubmitting(true);\n setErr(null);\n try {\n const t = await client.raiseTicket(conversationId, {\n consent: true,\n end_user_email: email.trim(),\n end_user_phone: defaultPhone || undefined,\n priority,\n force_new: true,\n });\n onNewTicketRaised?.(t);\n } catch (e: any) {\n setErr(e?.message || 'Could not create ticket. Try again.');\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"dgl-ticket-card\">\n <div className=\"dgl-ticket-card-stripe\" style={{ background: s.stripe }} />\n <div className=\"dgl-ticket-card-body\">\n <div className=\"dgl-ticket-card-head\">\n <div className=\"dgl-ticket-card-icon\" style={{ background: s.iconBg }}>\n {svgLifebuoy()}\n </div>\n <div className=\"dgl-ticket-card-titles\">\n <div className=\"dgl-ticket-card-eyebrow\">We're already on it</div>\n <div className=\"dgl-ticket-card-title\">#{existing.externalNumber || existing.ticketId.slice(0, 8)}</div>\n </div>\n {existing.externalUrl && (\n <a className=\"dgl-ticket-open-btn\" href={existing.externalUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Open\n </a>\n )}\n </div>\n <div className=\"dgl-ticket-pills\">\n <span className=\"dgl-ticket-pill\" style={{ background: s.pillBg, color: s.pillFg }}>\n <span className=\"dgl-ticket-pill-dot\" style={{ background: s.iconBg }} /> {s.label}\n </span>\n </div>\n <div className=\"dgl-ticket-card-desc\">\n A ticket has already been raised for this conversation. Our team will follow up — no need to file another.\n </div>\n {!raiseMode ? (\n <button\n type=\"button\"\n className=\"dgl-ticket-diff-link\"\n onClick={() => setRaiseMode(true)}\n >\n Different issue? Raise new ticket →\n </button>\n ) : (\n <div className=\"dgl-ticket-diff-form\">\n <div className=\"dgl-ticket-field-label\" style={{ marginTop: 4 }}>\n File a separate ticket for a new issue\n </div>\n <div className=\"dgl-ticket-form-grid\">\n <div>\n <div className=\"dgl-ticket-field-label\">Reply to</div>\n <input\n type=\"email\"\n className=\"dgl-ticket-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n />\n </div>\n <div>\n <div className=\"dgl-ticket-field-label\">Priority</div>\n <select\n className=\"dgl-ticket-input\"\n value={priority}\n onChange={(e) => setPriority(e.target.value as any)}\n >\n <option value=\"low\">Low</option>\n <option value=\"medium\">Medium</option>\n <option value=\"high\">High</option>\n <option value=\"urgent\">Urgent</option>\n </select>\n </div>\n </div>\n {err && <div className=\"dgl-ticket-error\">{err}</div>}\n <div className=\"dgl-ticket-card-footer\">\n <button\n type=\"button\"\n className=\"dgl-ticket-diff-cancel\"\n onClick={() => setRaiseMode(false)}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"dgl-ticket-submit\"\n onClick={submit}\n disabled={submitting || !email.trim()}\n >\n {submitting ? svgSpinner() : svgLifebuoy()}\n <span>{submitting ? 'Submitting…' : 'Submit new ticket'}</span>\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction TicketStatusCard({\n ticket,\n}: { ticket: NonNullable<ChatMessage['ticketStatus']> }) {\n const s = _TICKET_STATUS_STYLE[ticket.status] || _TICKET_STATUS_STYLE.open;\n const p = _TICKET_PRIORITY_STYLE[(ticket.priority || 'medium').toLowerCase()] || _TICKET_PRIORITY_STYLE.medium;\n return (\n <div className=\"dgl-ticket-card\">\n <div className=\"dgl-ticket-card-stripe\" style={{ background: s.stripe }} />\n <div className=\"dgl-ticket-card-body\">\n <div className=\"dgl-ticket-card-head\">\n <div className=\"dgl-ticket-card-icon\" style={{ background: s.iconBg }}>\n {svgLifebuoy()}\n </div>\n <div className=\"dgl-ticket-card-titles\">\n <div className=\"dgl-ticket-card-eyebrow\">Support ticket</div>\n <div className=\"dgl-ticket-card-title\">#{ticket.externalNumber || ticket.ticketId.slice(0, 8)}</div>\n </div>\n {ticket.externalUrl && (\n <a className=\"dgl-ticket-open-btn\" href={ticket.externalUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Open\n </a>\n )}\n </div>\n <div className=\"dgl-ticket-pills\">\n <span className=\"dgl-ticket-pill\" style={{ background: s.pillBg, color: s.pillFg }}>\n <span className=\"dgl-ticket-pill-dot\" style={{ background: s.iconBg }} /> {s.label}\n </span>\n <span className=\"dgl-ticket-pill\" style={{ background: p.bg, color: p.fg }}>\n {ticket.priority || 'medium'} priority\n </span>\n </div>\n {ticket.title && <div className=\"dgl-ticket-card-body-title\">{ticket.title}</div>}\n <div className=\"dgl-ticket-meta-grid\">\n <div>\n <div className=\"dgl-ticket-meta-label\">Last update</div>\n <div className=\"dgl-ticket-meta-value\">{_ticketRelative(ticket.lastUpdate)}</div>\n </div>\n <div>\n <div className=\"dgl-ticket-meta-label\">Assigned to</div>\n <div className=\"dgl-ticket-meta-value\">{ticket.assignedTo || 'Unassigned'}</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n// ─── Manage tickets modal ───────────────────────────────────────────────\n// Slides into the panel from above the messages area. Shows ALL tickets\n// this visitor has raised on this agent — including tickets from prior\n// conversations — so the user has a single place to track support state.\n\nfunction ManageTicketsModal({\n tickets,\n onClose,\n onRefresh,\n}: {\n tickets: TicketRef[];\n onClose: () => void;\n onRefresh: () => Promise<void>;\n}) {\n const [refreshing, setRefreshing] = useState(false);\n\n // Escape closes — matches the lightbox pattern.\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [onClose]);\n\n const handleRefresh = async () => {\n setRefreshing(true);\n try { await onRefresh(); } finally { setRefreshing(false); }\n };\n\n const sorted = [...tickets].sort((a, b) => {\n const at = a.created_at ? new Date(a.created_at).getTime() : 0;\n const bt = b.created_at ? new Date(b.created_at).getTime() : 0;\n return bt - at;\n });\n\n return (\n <div className=\"dgl-tix-modal-backdrop\" onClick={onClose}>\n <div className=\"dgl-tix-modal\" onClick={(e) => e.stopPropagation()}>\n <div className=\"dgl-tix-modal-header\">\n <div>\n <div className=\"dgl-tix-modal-title\">Your tickets</div>\n <div className=\"dgl-tix-modal-sub\">\n {tickets.length === 0\n ? 'No tickets yet'\n : `${tickets.length} ticket${tickets.length === 1 ? '' : 's'} on this assistant`}\n </div>\n </div>\n <div style={{ display: 'flex', gap: 4 }}>\n <button\n type=\"button\"\n onClick={handleRefresh}\n className=\"dgl-icon-btn\"\n title=\"Refresh\"\n aria-label=\"Refresh tickets\"\n disabled={refreshing}\n style={{ color: '#475569' }}\n >\n {refreshing ? svgSpinner() : svgRefresh()}\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"dgl-icon-btn\"\n title=\"Close\"\n aria-label=\"Close\"\n style={{ color: '#475569' }}\n >\n {svgX()}\n </button>\n </div>\n </div>\n <div className=\"dgl-tix-modal-list\">\n {sorted.length === 0 ? (\n <div className=\"dgl-tix-empty\">\n You haven't raised any support tickets here yet. They'll show up here once you do.\n </div>\n ) : (\n sorted.map((t) => {\n const s = _TICKET_STATUS_STYLE[t.status] || _TICKET_STATUS_STYLE.open;\n return (\n <div key={t.id} className=\"dgl-tix-row\">\n <div className=\"dgl-tix-row-head\">\n <span className=\"dgl-tix-row-num\">\n #{t.external_ticket_number || t.id.slice(0, 8)}\n </span>\n <span\n className=\"dgl-ticket-pill\"\n style={{ background: s.pillBg, color: s.pillFg }}\n >\n <span className=\"dgl-ticket-pill-dot\" style={{ background: s.iconBg }} />\n {s.label}\n </span>\n {t.external_url && (\n <a\n href={t.external_url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"dgl-ticket-open-btn\"\n style={{ marginLeft: 'auto' }}\n >\n Open\n </a>\n )}\n </div>\n {t.title && <div className=\"dgl-tix-row-title\">{t.title}</div>}\n <div className=\"dgl-tix-row-meta\">\n {t.priority || 'medium'} priority · raised {_ticketRelative(t.created_at)}\n </div>\n </div>\n );\n })\n )}\n </div>\n </div>\n </div>\n );\n}\n\n// ─── Inline SVG icons (no external deps) ────────────────────────────────\n\nfunction svgLifebuoy() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M4.93 4.93l4.24 4.24M14.83 14.83l4.24 4.24M14.83 9.17l4.24-4.24M14.83 9.17l3.53-3.53M4.93 19.07l4.24-4.24\" />\n </svg>\n );\n}\n\nfunction svgCheck() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"white\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction svgChat() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"currentColor\">\n <path d=\"M4 4h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H8l-4 4V6a2 2 0 0 1 2-2z\" />\n </svg>\n );\n}\nfunction svgChevronDown() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\nfunction svgX() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n}\nfunction svgPlus() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n );\n}\nfunction svgSend() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\">\n <path d=\"M2 21l21-9L2 3v7l15 2-15 2z\" />\n </svg>\n );\n}\nfunction svgImage() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" />\n <polyline points=\"21 15 16 10 5 21\" />\n </svg>\n );\n}\nfunction svgSpinner() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" className=\"dgl-spin\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\">\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\nfunction svgExpand() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"15 3 21 3 21 9\" />\n <polyline points=\"9 21 3 21 3 15\" />\n <line x1=\"21\" y1=\"3\" x2=\"14\" y2=\"10\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\nfunction svgShrink() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"4 14 10 14 10 20\" />\n <polyline points=\"20 10 14 10 14 4\" />\n <line x1=\"14\" y1=\"10\" x2=\"21\" y2=\"3\" />\n <line x1=\"3\" y1=\"21\" x2=\"10\" y2=\"14\" />\n </svg>\n );\n}\nfunction svgRefresh() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"23 4 23 10 17 10\" />\n <polyline points=\"1 20 1 14 7 14\" />\n <path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\" />\n </svg>\n );\n}\nfunction svgSparkles() {\n return (\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"currentColor\">\n <path d=\"M12 2l2.39 6.95L21 11l-6.61 2.05L12 20l-2.39-6.95L3 11l6.61-2.05L12 2z\" />\n </svg>\n );\n}\n","/**\n * @docgenlab.com/chat-widget — public entry.\n *\n * Two integration paths:\n *\n * 1. React (recommended for SPAs):\n *\n * import { DocGenLabChat } from '@docgenlab.com/chat-widget';\n * import '@docgenlab.com/chat-widget/style.css';\n *\n * <DocGenLabChat agentKey=\"pk_live_...\" />\n *\n * 2. Vanilla / script tag (WordPress, marketing pages, anything without\n * a build step). Use unpkg or jsdelivr to load the UMD bundle:\n *\n * <link rel=\"stylesheet\" href=\"https://unpkg.com/@docgenlab.com/chat-widget/dist/widget.css\" />\n * <script src=\"https://unpkg.com/@docgenlab.com/chat-widget\"></script>\n * <script>DocGenLab.init({ agentKey: 'pk_live_...' })</script>\n *\n * The UMD bundle exposes a global `DocGenLab` object with `init()` and\n * `destroy()` methods that mount/unmount the widget on a hidden div.\n */\n\nimport { createRoot, type Root } from 'react-dom/client';\nimport { createElement } from 'react';\nimport { DocGenLabChat, type DocGenLabChatProps } from './widget';\nimport type { ChatWidgetConfig, ChatWidgetTheme, ChatPosition, Citation, AgentInfo, StreamEvent, ChatMessage } from './types';\n\nexport { DocGenLabChat };\nexport type {\n DocGenLabChatProps,\n ChatWidgetConfig,\n ChatWidgetTheme,\n ChatPosition,\n Citation,\n AgentInfo,\n StreamEvent,\n ChatMessage,\n};\n\n// ─── Vanilla bootstrap ──────────────────────────────────────────────────\n\nlet _root: Root | null = null;\nlet _container: HTMLDivElement | null = null;\n\nexport function init(config: DocGenLabChatProps): void {\n if (typeof document === 'undefined') {\n throw new Error('DocGenLab.init() requires a browser environment.');\n }\n if (_root) {\n // Re-mount on second call (config change)\n _root.render(createElement(DocGenLabChat, config));\n return;\n }\n _container = document.createElement('div');\n _container.id = 'docgenlab-chat-widget-root';\n document.body.appendChild(_container);\n _root = createRoot(_container);\n _root.render(createElement(DocGenLabChat, config));\n}\n\nexport function destroy(): void {\n if (_root) {\n _root.unmount();\n _root = null;\n }\n if (_container) {\n _container.remove();\n _container = null;\n }\n}\n\n// Make sure the UMD global has these too. Vite assigns the default export to\n// the configured `name` ('DocGenLab'); explicitly attach methods so vanilla\n// HTML can use `DocGenLab.init(...)` without an import.\n// (This is a no-op when consumed via ESM imports.)\ndeclare global {\n interface Window {\n DocGenLab?: { init: typeof init; destroy: typeof destroy; DocGenLabChat: typeof DocGenLabChat };\n }\n}\nif (typeof window !== 'undefined') {\n window.DocGenLab = { init, destroy, DocGenLabChat };\n}\n"],"names":["PUBLIC_BASE","VISITOR_KEY","uuid","c","ch","getVisitorId","id","e","WidgetClient","opts","extra","base","resp","conversationId","url","file","fd","detail","j","imagePath","blob","body","q","ticketId","refresh","sourceId","framePath","onEvent","ctrl","reader","decoder","buf","value","done","nl","raw","line","evt","DEFAULTS","DocGenLabChat","props","baseUrl","enableImageUpload","clientRef","useRef","identityKey","lastIdentityRef","client","agent","setAgent","useState","agentError","setAgentError","remote","resolved","_a","_b","_c","_d","_f","_e","_h","_g","themeVars","open","setOpen","expanded","setExpanded","messages","setMessages","input","setInput","streaming","setStreaming","setConversationId","attachedFile","setAttachedFile","attachedPreview","setAttachedPreview","uploadingImage","setUploadingImage","fileInputRef","abortRef","contentRef","scrollRef","tickets","setTickets","ticketsModalOpen","setTicketsModalOpen","useEffect","info","cancelled","rows","k","stored","cardState","restored","m","attachAt","i","msg","clearAttachment","useCallback","stageImage","MAX","onSubmit","userText","previewForTurn","prev","snap","newChat","React","svgLifebuoy","svgPlus","v","svgShrink","svgExpand","svgX","ManageTicketsModal","svgSparkles","idx","MessageBubble","target","t","mm","x","svgImage","f","item","it","svgSpinner","svgSend","svgChevronDown","svgChat","message","isLast","agentAvatarUrl","onPickFollowup","defaultEmail","defaultPhone","onTicketCreated","UserImage","cleaned","cleanForDisplay","followups","extractFollowups","TicketStatusCard","ThinkingDots","renderMarkdown","CitationChips","TicketCreatedChip","TicketExistingCard","RaiseTicketChip","FollowupChips","suggestions","onPick","previewUrl","setUrl","revoke","u","onKey","citations","bySource","unique","a","b","hidden","openId","setOpenId","CitationChip","citation","isOpen","onToggle","cit","isVideo","breadcrumb","stamp","CitationFrame","content","match","text","REFUSAL_RE","FOLLOWUPS_RE","withoutFollowups","remainingAfterRefusal","block","lines","l","isOrdered","items","Tag","renderInline","arr","pattern","part","linkMatch","_TICKET_STATUS_STYLE","_TICKET_PRIORITY_STYLE","_ticketRelative","iso","d","diff","min","hr","day","offer","onCreated","email","setEmail","phone","setPhone","editEmail","setEditEmail","priority","setPriority","submitting","setSubmitting","error","setError","submit","created","s","svgCheck","existing","onNewTicketRaised","raiseMode","setRaiseMode","err","setErr","ticket","p","onClose","onRefresh","refreshing","setRefreshing","handleRefresh","sorted","at","svgRefresh","_root","_container","init","config","createElement","createRoot","destroy"],"mappings":"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"}
|