@surf-kit/agent 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/chat/index.cjs +131 -41
  2. package/dist/chat/index.cjs.map +1 -1
  3. package/dist/chat/index.d.cts +3 -2
  4. package/dist/chat/index.d.ts +3 -2
  5. package/dist/chat/index.js +132 -42
  6. package/dist/chat/index.js.map +1 -1
  7. package/dist/{chat-CGamM7Mz.d.cts → chat-BRY3xGg_.d.cts} +1 -1
  8. package/dist/{chat-BIIDOGrD.d.ts → chat-CcKc6OAR.d.ts} +1 -1
  9. package/dist/{hooks-CTeEqnBQ.d.ts → hooks-BLeiVk-x.d.ts} +3 -2
  10. package/dist/{hooks-B1NYoLLs.d.cts → hooks-CSGGLd7j.d.cts} +3 -2
  11. package/dist/hooks.cjs +41 -11
  12. package/dist/hooks.cjs.map +1 -1
  13. package/dist/hooks.d.cts +3 -3
  14. package/dist/hooks.d.ts +3 -3
  15. package/dist/hooks.js +41 -11
  16. package/dist/hooks.js.map +1 -1
  17. package/dist/index.cjs +131 -41
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +3 -3
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +136 -46
  22. package/dist/index.js.map +1 -1
  23. package/dist/layouts/index.cjs +131 -41
  24. package/dist/layouts/index.cjs.map +1 -1
  25. package/dist/layouts/index.d.cts +1 -1
  26. package/dist/layouts/index.d.ts +1 -1
  27. package/dist/layouts/index.js +134 -44
  28. package/dist/layouts/index.js.map +1 -1
  29. package/dist/response/index.cjs +34 -3
  30. package/dist/response/index.cjs.map +1 -1
  31. package/dist/response/index.d.cts +1 -1
  32. package/dist/response/index.d.ts +1 -1
  33. package/dist/response/index.js +35 -4
  34. package/dist/response/index.js.map +1 -1
  35. package/dist/streaming/index.cjs +14 -3
  36. package/dist/streaming/index.cjs.map +1 -1
  37. package/dist/streaming/index.d.cts +2 -2
  38. package/dist/streaming/index.d.ts +2 -2
  39. package/dist/streaming/index.js +14 -3
  40. package/dist/streaming/index.js.map +1 -1
  41. package/dist/{streaming-x7umFHoP.d.cts → streaming-BHPXnwwo.d.cts} +3 -1
  42. package/dist/{streaming-Bx-ff2tt.d.ts → streaming-C6mbU7My.d.ts} +3 -1
  43. package/package.json +5 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/layouts/AgentFullPage/AgentFullPage.tsx","../../src/chat/AgentChat/AgentChat.tsx","../../src/hooks/useAgentChat.ts","../../src/chat/MessageThread/MessageThread.tsx","../../src/chat/MessageBubble/MessageBubble.tsx","../../src/response/AgentResponse/AgentResponse.tsx","../../src/response/ResponseMessage/ResponseMessage.tsx","../../src/response/StructuredResponse/StructuredResponse.tsx","../../src/sources/SourceList/SourceList.tsx","../../src/sources/SourceCard/SourceCard.tsx","../../src/response/FollowUpChips/FollowUpChips.tsx","../../src/chat/MessageComposer/MessageComposer.tsx","../../src/chat/WelcomeScreen/WelcomeScreen.tsx","../../src/streaming/StreamingMessage/StreamingMessage.tsx","../../src/hooks/useCharacterDrain.ts","../../src/chat/ConversationList/ConversationList.tsx","../../src/layouts/AgentPanel/AgentPanel.tsx","../../src/layouts/AgentWidget/AgentWidget.tsx","../../src/layouts/AgentEmbed/AgentEmbed.tsx"],"sourcesContent":["'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useState, useCallback } from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\nimport { ConversationList } from '../../chat/ConversationList'\nimport type { ConversationSummary } from '../../types/chat'\n\nexport type AgentFullPageProps = {\n endpoint: string\n title?: string\n showConversationList?: boolean\n conversations?: ConversationSummary[]\n activeConversationId?: string\n onConversationSelect?: (id: string) => void\n onConversationDelete?: (id: string) => void\n onNewConversation?: () => void\n className?: string\n}\n\nfunction AgentFullPage({\n endpoint,\n title = 'Chat',\n showConversationList = false,\n conversations = [],\n activeConversationId,\n onConversationSelect,\n onConversationDelete,\n onNewConversation,\n className,\n}: AgentFullPageProps) {\n const [sidebarOpen, setSidebarOpen] = useState(false)\n\n const handleSelect = useCallback(\n (id: string) => {\n onConversationSelect?.(id)\n setSidebarOpen(false)\n },\n [onConversationSelect],\n )\n\n return (\n <div\n className={twMerge('flex h-screen w-full overflow-hidden bg-brand-dark', className)}\n data-testid=\"agent-full-page\"\n >\n {/* Sidebar */}\n {showConversationList && (\n <>\n {/* Mobile overlay */}\n {sidebarOpen && (\n <div\n className=\"fixed inset-0 bg-brand-dark/80 backdrop-blur-sm z-30 md:hidden\"\n onClick={() => setSidebarOpen(false)}\n data-testid=\"sidebar-overlay\"\n />\n )}\n\n {/* Sidebar panel */}\n <aside\n className={twMerge(\n 'bg-brand-dark border-r border-brand-gold/15 w-72 shrink-0 flex-col z-40',\n // Desktop: always visible\n 'hidden md:flex',\n // Mobile: overlay when open\n sidebarOpen && 'fixed inset-y-0 left-0 flex md:relative',\n )}\n aria-label=\"Conversations sidebar\"\n >\n <ConversationList\n conversations={conversations}\n activeId={activeConversationId}\n onSelect={handleSelect}\n onDelete={onConversationDelete}\n onNew={onNewConversation}\n />\n </aside>\n </>\n )}\n\n {/* Main chat area */}\n <div className=\"flex-1 flex flex-col min-w-0 bg-brand-dark\">\n {/* Mobile sidebar toggle */}\n {showConversationList && (\n <div className=\"md:hidden flex items-center border-b border-brand-gold/15 px-3 py-2 bg-brand-dark-panel/60 backdrop-blur-sm\">\n <button\n type=\"button\"\n onClick={() => setSidebarOpen(true)}\n aria-label=\"Open conversations sidebar\"\n className=\"p-2 rounded-xl text-brand-cream/60 hover:text-brand-cream hover:bg-brand-dark-panel transition-colors duration-200\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </svg>\n </button>\n </div>\n )}\n\n <AgentChat\n endpoint={endpoint}\n title={title}\n className=\"flex-1 rounded-none border-0\"\n />\n </div>\n </div>\n )\n}\n\nexport { AgentFullPage }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport { useAgentChat } from '../../hooks/useAgentChat'\nimport { MessageThread } from '../MessageThread'\nimport { MessageComposer } from '../MessageComposer'\nimport { WelcomeScreen } from '../WelcomeScreen'\nimport { StreamingMessage } from '../../streaming/StreamingMessage'\nimport type { ChatMessage } from '../../types/chat'\n\nexport type AgentChatProps = {\n endpoint: string\n title?: string\n welcomeTitle?: string\n welcomeMessage?: string\n suggestedQuestions?: string[]\n showHeader?: boolean\n showWelcomeTitle?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n enableFeedback?: boolean\n onMessage?: (message: ChatMessage) => void\n className?: string\n}\n\nfunction AgentChat({\n endpoint,\n title = 'Chat',\n welcomeTitle,\n welcomeMessage = 'How can I help you today?',\n suggestedQuestions = [],\n showHeader = true,\n showWelcomeTitle = true,\n showSources,\n showConfidence,\n showVerification,\n className,\n}: AgentChatProps) {\n const { state, actions } = useAgentChat({ apiUrl: endpoint })\n\n const hasMessages = state.messages.length > 0\n\n const handleSend = (content: string) => {\n void actions.sendMessage(content)\n }\n\n const handleQuestionSelect = (question: string) => {\n void actions.sendMessage(question)\n }\n\n return (\n <div\n className={twMerge(\n 'flex flex-col h-full bg-canvas border border-border rounded-xl overflow-hidden',\n className,\n )}\n >\n {showHeader && (\n <div className=\"flex items-center justify-between border-b border-border px-4 py-3 bg-surface-raised shrink-0\">\n <h1 className=\"text-base font-semibold text-text-primary\">{title}</h1>\n </div>\n )}\n\n {hasMessages ? (\n <MessageThread\n messages={state.messages}\n streamingSlot={\n state.isLoading ? (\n <StreamingMessage\n stream={{\n active: state.isLoading,\n phase: state.streamPhase,\n content: state.streamingContent,\n sources: [],\n agent: null,\n agentLabel: null,\n }}\n />\n ) : undefined\n }\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n />\n ) : (\n <WelcomeScreen\n title={showWelcomeTitle ? (welcomeTitle ?? title) : ''}\n message={welcomeMessage}\n suggestedQuestions={suggestedQuestions}\n onQuestionSelect={handleQuestionSelect}\n />\n )}\n\n <MessageComposer onSend={handleSend} isLoading={state.isLoading} />\n </div>\n )\n}\n\nexport { AgentChat }\n","'use client'\n\nimport { useReducer, useCallback, useRef } from 'react'\nimport type { ChatMessage, ChatError, Attachment } from '../types/chat'\nimport type { AgentResponse } from '../types/agent'\nimport type { StreamState } from '../types/streaming'\nimport type { AgentChatConfig } from '../types/config'\n\n// ── State ──────────────────────────────────────────────────────────────\n\nexport interface AgentChatState {\n messages: ChatMessage[]\n conversationId: string | null\n isLoading: boolean\n error: ChatError | null\n inputValue: string\n streamPhase: StreamState['phase']\n streamingContent: string\n streamingAgent: string | null\n}\n\nconst initialState: AgentChatState = {\n messages: [],\n conversationId: null,\n isLoading: false,\n error: null,\n inputValue: '',\n streamPhase: 'idle',\n streamingContent: '',\n streamingAgent: null,\n}\n\n// ── Actions ────────────────────────────────────────────────────────────\n\ntype Action =\n | { type: 'SET_INPUT'; value: string }\n | { type: 'SEND_START'; message: ChatMessage }\n | { type: 'STREAM_PHASE'; phase: StreamState['phase'] }\n | { type: 'STREAM_CONTENT'; content: string }\n | { type: 'STREAM_AGENT'; agent: string }\n | { type: 'SEND_SUCCESS'; message: ChatMessage; streamingContent: string; conversationId: string | null }\n | { type: 'SEND_ERROR'; error: ChatError }\n | { type: 'LOAD_CONVERSATION'; conversationId: string; messages: ChatMessage[] }\n | { type: 'RESET' }\n | { type: 'CLEAR_ERROR' }\n\nfunction reducer(state: AgentChatState, action: Action): AgentChatState {\n switch (action.type) {\n case 'SET_INPUT':\n return { ...state, inputValue: action.value }\n\n case 'SEND_START':\n return {\n ...state,\n messages: [...state.messages, action.message],\n isLoading: true,\n error: null,\n inputValue: '',\n streamPhase: 'thinking',\n streamingContent: '',\n streamingAgent: null,\n }\n\n case 'STREAM_PHASE':\n return { ...state, streamPhase: action.phase }\n\n case 'STREAM_CONTENT':\n return { ...state, streamingContent: state.streamingContent + action.content }\n\n case 'STREAM_AGENT':\n return { ...state, streamingAgent: action.agent }\n\n case 'SEND_SUCCESS':\n return {\n ...state,\n messages: [...state.messages, action.message],\n conversationId: action.conversationId ?? state.conversationId,\n isLoading: false,\n streamPhase: 'idle',\n streamingContent: '',\n }\n\n case 'SEND_ERROR':\n return {\n ...state,\n isLoading: false,\n error: action.error,\n streamPhase: 'idle',\n streamingContent: '',\n streamingAgent: null,\n }\n\n case 'LOAD_CONVERSATION':\n return {\n ...state,\n conversationId: action.conversationId,\n messages: action.messages,\n error: null,\n }\n\n case 'RESET':\n return { ...initialState }\n\n case 'CLEAR_ERROR':\n return { ...state, error: null }\n\n default:\n return state\n }\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────\n\nlet msgIdCounter = 0\nfunction generateMessageId(): string {\n return `msg-${Date.now()}-${++msgIdCounter}`\n}\n\nexport interface AgentChatActions {\n sendMessage: (content: string, attachments?: Attachment[]) => Promise<void>\n setInputValue: (value: string) => void\n loadConversation: (conversationId: string, messages: ChatMessage[]) => void\n submitFeedback: (messageId: string, rating: 'positive' | 'negative', comment?: string) => Promise<void>\n retry: () => Promise<void>\n reset: () => void\n}\n\nexport function useAgentChat(config: AgentChatConfig) {\n const [state, dispatch] = useReducer(reducer, initialState)\n const configRef = useRef(config)\n configRef.current = config\n const lastUserMessageRef = useRef<string | null>(null)\n const lastUserAttachmentsRef = useRef<Attachment[] | undefined>(undefined)\n\n const sendMessage = useCallback(\n async (content: string, attachments?: Attachment[]) => {\n const { apiUrl, streamPath = '/chat/stream', headers: headersOrFn, timeout = 30000, bodyExtra } = configRef.current\n const headers = typeof headersOrFn === 'function' ? await headersOrFn() : (headersOrFn ?? {})\n\n lastUserMessageRef.current = content\n lastUserAttachmentsRef.current = attachments\n\n const userMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'user',\n content,\n attachments,\n timestamp: new Date(),\n }\n\n dispatch({ type: 'SEND_START', message: userMessage })\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n try {\n const url = `${apiUrl}${streamPath}`\n const mergedHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n }\n\n // Build request body — include attachments if present\n const requestBody: Record<string, unknown> = {\n message: content,\n conversation_id: state.conversationId,\n ...bodyExtra,\n }\n if (attachments && attachments.length > 0) {\n requestBody.attachments = attachments.map(a => ({\n filename: a.filename,\n content_type: a.content_type,\n data: a.data,\n }))\n }\n const body = JSON.stringify(requestBody)\n\n // These variables are mutated inside handleEvent (called from async stream processing).\n // TypeScript can't track mutations through closures, so we use a mutable context object.\n const ctx = {\n accumulatedContent: '',\n agentResponse: null as AgentResponse | null,\n capturedAgent: null as string | null,\n capturedConversationId: null as string | null,\n hadStreamError: false,\n }\n\n // Shared handler for parsed SSE events (used by both adapter and default paths)\n const handleEvent = (event: { type: string; [key: string]: unknown }) => {\n switch (event.type) {\n case 'agent':\n ctx.capturedAgent = event.agent as string\n dispatch({ type: 'STREAM_AGENT', agent: ctx.capturedAgent })\n break\n case 'phase':\n dispatch({ type: 'STREAM_PHASE', phase: event.phase as StreamState['phase'] })\n break\n case 'delta':\n ctx.accumulatedContent += event.content\n dispatch({ type: 'STREAM_CONTENT', content: event.content as string })\n break\n case 'done':\n ctx.agentResponse = event.response as AgentResponse\n ctx.capturedConversationId = (event.conversation_id as string) ?? null\n break\n case 'error':\n ctx.hadStreamError = true\n dispatch({ type: 'SEND_ERROR', error: event.error as ChatError })\n break\n }\n }\n\n const { streamAdapter } = configRef.current\n\n if (streamAdapter) {\n // Use the custom stream adapter (e.g. React Native XHR-based SSE)\n await streamAdapter(\n url,\n { method: 'POST', headers: mergedHeaders, body, signal: controller.signal },\n handleEvent,\n )\n clearTimeout(timeoutId)\n } else {\n // Default path: fetch + ReadableStream getReader()\n const response = await fetch(url, {\n method: 'POST',\n headers: mergedHeaders,\n body,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'API_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n retryable: response.status >= 500,\n },\n })\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'STREAM_ERROR', message: 'No response body', retryable: true },\n })\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data)\n handleEvent(event)\n } catch {\n // Skip malformed events\n }\n }\n }\n }\n\n // If an error event was dispatched during streaming, don't dispatch success\n if (ctx.hadStreamError) return\n\n const assistantMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: ctx.agentResponse?.message ?? ctx.accumulatedContent,\n response: ctx.agentResponse ?? undefined,\n agent: ctx.capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n\n dispatch({\n type: 'SEND_SUCCESS',\n message: assistantMessage,\n streamingContent: ctx.accumulatedContent,\n conversationId: ctx.capturedConversationId,\n })\n } catch (err: unknown) {\n clearTimeout(timeoutId)\n if ((err as Error).name === 'AbortError') {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'TIMEOUT', message: 'Request timed out', retryable: true },\n })\n } else {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'NETWORK_ERROR',\n message: (err as Error).message ?? 'Network error',\n retryable: true,\n },\n })\n }\n }\n },\n [state.conversationId],\n )\n\n const setInputValue = useCallback((value: string) => {\n dispatch({ type: 'SET_INPUT', value })\n }, [])\n\n const loadConversation = useCallback((conversationId: string, messages: ChatMessage[]) => {\n dispatch({ type: 'LOAD_CONVERSATION', conversationId, messages })\n }, [])\n\n const submitFeedback = useCallback(\n async (messageId: string, rating: 'positive' | 'negative', comment?: string) => {\n const { apiUrl, feedbackPath = '/feedback', headers: headersOrFn } = configRef.current\n const headers = typeof headersOrFn === 'function' ? await headersOrFn() : (headersOrFn ?? {})\n await fetch(`${apiUrl}${feedbackPath}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({ messageId, rating, comment }),\n })\n },\n [],\n )\n\n const retry = useCallback(async () => {\n if (lastUserMessageRef.current) {\n await sendMessage(lastUserMessageRef.current, lastUserAttachmentsRef.current)\n }\n }, [sendMessage])\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' })\n lastUserMessageRef.current = null\n lastUserAttachmentsRef.current = undefined\n }, [])\n\n const actions: AgentChatActions = {\n sendMessage,\n setInputValue,\n loadConversation,\n submitFeedback,\n retry,\n reset,\n }\n\n return { state, actions }\n}\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport type { ChatMessage } from '../../types/chat'\nimport { MessageBubble } from '../MessageBubble'\n\nexport type MessageThreadProps = {\n messages: ChatMessage[]\n streamingSlot?: React.ReactNode\n showAgent?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n hideLastAssistant?: boolean\n userBubbleClassName?: string\n className?: string\n}\n\nfunction MessageThread({ messages, streamingSlot, showAgent, showSources, showConfidence, showVerification, hideLastAssistant, userBubbleClassName, className }: MessageThreadProps) {\n const scrollRef = useRef<HTMLDivElement>(null)\n const isNearBottom = useRef(true)\n const isProgrammaticScroll = useRef(false)\n const hasStreaming = !!streamingSlot\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current\n if (el && isNearBottom.current) {\n isProgrammaticScroll.current = true\n el.scrollTop = el.scrollHeight\n }\n }, [])\n\n const handleScroll = useCallback(() => {\n if (isProgrammaticScroll.current) {\n isProgrammaticScroll.current = false\n return\n }\n const el = scrollRef.current\n if (!el) return\n isNearBottom.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80\n }, [])\n\n // Scroll on new messages\n useEffect(scrollToBottom, [messages.length, scrollToBottom])\n\n // Continuously follow streaming content growth\n useEffect(() => {\n if (!hasStreaming) return\n let raf: number\n const tick = () => {\n scrollToBottom()\n raf = requestAnimationFrame(tick)\n }\n raf = requestAnimationFrame(tick)\n return () => cancelAnimationFrame(raf)\n }, [hasStreaming, scrollToBottom])\n\n return (\n <div\n ref={scrollRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Message thread\"\n onScroll={handleScroll}\n className={twMerge(\n 'flex flex-col gap-4 overflow-y-auto flex-1 px-4 py-6',\n className,\n )}\n >\n <div className=\"flex-1 shrink-0\" />\n {messages.map((message, i) => {\n if (\n hideLastAssistant &&\n i === messages.length - 1 &&\n message.role === 'assistant'\n ) {\n return null\n }\n return (\n <MessageBubble\n key={message.id}\n message={message}\n showAgent={showAgent}\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n userBubbleClassName={userBubbleClassName}\n />\n )\n })}\n {streamingSlot}\n </div>\n )\n}\n\nexport { MessageThread }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport type { ChatMessage, Attachment } from '../../types/chat'\nimport { AgentResponse } from '../../response/AgentResponse'\nimport { ResponseMessage } from '../../response/ResponseMessage'\n\nfunction DocumentIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n </svg>\n )\n}\n\nfunction AttachmentThumbnail({ attachment }: { attachment: Attachment }) {\n const isImage = attachment.content_type.startsWith('image/')\n\n if (isImage) {\n return (\n <div className=\"rounded-lg overflow-hidden border border-black/10 max-w-[240px]\">\n <img\n src={attachment.preview_url ?? `data:${attachment.content_type};base64,${attachment.data}`}\n alt={attachment.filename}\n className=\"max-w-full max-h-[200px] object-contain\"\n />\n </div>\n )\n }\n\n return (\n <div className=\"flex items-center gap-2 px-3 py-2 rounded-lg border border-black/10 bg-black/5\">\n <DocumentIcon />\n <span className=\"text-xs truncate max-w-[160px]\">{attachment.filename}</span>\n </div>\n )\n}\n\nexport type MessageBubbleProps = {\n message: ChatMessage\n showAgent?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n animated?: boolean\n userBubbleClassName?: string\n className?: string\n}\n\nfunction MessageBubble({\n message,\n showAgent,\n showSources = true,\n showConfidence = true,\n showVerification = true,\n animated = true,\n userBubbleClassName,\n className,\n}: MessageBubbleProps) {\n const isUser = message.role === 'user'\n const hasAttachments = message.attachments && message.attachments.length > 0\n\n if (isUser) {\n return (\n <div\n data-message-id={message.id}\n className={twMerge('flex w-full justify-end', className)}\n >\n <div\n className={twMerge(\n 'max-w-[70%] rounded-[18px] rounded-br-[4px] px-4 py-2.5 bg-[#e8e8e8] text-[#1a1a1a] break-words whitespace-pre-wrap text-sm leading-relaxed',\n animated && 'motion-safe:animate-slideFromRight',\n userBubbleClassName,\n )}\n >\n {hasAttachments && (\n <div className=\"flex flex-wrap gap-2 mb-2\">\n {message.attachments!.map((att, i) => (\n <AttachmentThumbnail key={`${att.filename}-${i}`} attachment={att} />\n ))}\n </div>\n )}\n {message.content}\n </div>\n </div>\n )\n }\n\n return (\n <div\n data-message-id={message.id}\n className={twMerge('flex w-full flex-col items-start gap-1.5', className)}\n >\n {showAgent && message.agent && (\n <div className=\"text-[11px] font-display font-semibold uppercase tracking-[0.08em] text-text-muted px-1\">\n {message.agent.replace('_agent', '').replace('_', ' ')}\n </div>\n )}\n <div\n className={twMerge(\n 'max-w-[88%] rounded-[18px] rounded-tl-[4px] px-4 py-3 bg-surface border border-border',\n animated && 'motion-safe:animate-springFromLeft',\n )}\n >\n {message.response ? (\n <AgentResponse\n response={message.response}\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n />\n ) : (\n <ResponseMessage content={message.content} />\n )}\n </div>\n </div>\n )\n}\n\nexport { MessageBubble }\n","import React from 'react'\nimport { Badge } from '@surf-kit/core'\nimport type { AgentResponse as AgentResponseType } from '../../types/agent'\nimport { ResponseMessage } from '../ResponseMessage'\nimport { StructuredResponse } from '../StructuredResponse'\nimport { SourceList } from '../../sources/SourceList'\nimport { FollowUpChips } from '../FollowUpChips'\n\ntype AgentResponseProps = {\n response: AgentResponseType\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n onFollowUp?: (suggestion: string) => void\n onNavigateSource?: (source: AgentResponseType['sources'][number]) => void\n className?: string\n}\n\nfunction getConfidenceIntent(overall: 'high' | 'medium' | 'low') {\n if (overall === 'high') return 'success' as const\n if (overall === 'medium') return 'warning' as const\n return 'error' as const\n}\n\nfunction getVerificationIntent(status: 'passed' | 'flagged' | 'failed') {\n if (status === 'passed') return 'success' as const\n if (status === 'flagged') return 'warning' as const\n return 'error' as const\n}\n\nfunction getVerificationLabel(status: 'passed' | 'flagged' | 'failed') {\n if (status === 'passed') return 'Verified'\n if (status === 'flagged') return 'Flagged'\n return 'Failed'\n}\n\nfunction AgentResponse({\n response,\n showSources = true,\n showConfidence = false,\n showVerification = false,\n onFollowUp,\n onNavigateSource,\n className,\n}: AgentResponseProps) {\n return (\n <div className={`flex flex-col gap-4 ${className ?? ''}`} data-testid=\"agent-response\">\n {/* Lead message — always shown as a short 1-3 sentence summary */}\n <ResponseMessage content={response.message} />\n\n {/* Structured content — rendered when ui_hint is not plain text */}\n {response.ui_hint !== 'text' && response.structured_data && (() => {\n const parsed = typeof response.structured_data === 'string'\n ? (() => { try { return JSON.parse(response.structured_data) as Record<string, unknown> } catch { return null } })()\n : response.structured_data as Record<string, unknown>\n return parsed ? <StructuredResponse uiHint={response.ui_hint} data={parsed} /> : null\n })()}\n\n {/* Confidence & Verification badges */}\n {(showConfidence || showVerification) && (\n <div className=\"flex flex-wrap items-center gap-2 mt-1\" data-testid=\"response-meta\">\n {showConfidence && (\n <Badge\n intent={getConfidenceIntent(response.confidence.overall)}\n size=\"sm\"\n >\n {response.confidence.overall} confidence\n </Badge>\n )}\n {showVerification && (\n <Badge\n intent={getVerificationIntent(response.verification.status)}\n size=\"sm\"\n >\n {getVerificationLabel(response.verification.status)} ({response.verification.claims_verified}/{response.verification.claims_checked})\n </Badge>\n )}\n </div>\n )}\n\n {/* Sources */}\n {showSources && response.sources.length > 0 && (\n <SourceList\n sources={response.sources}\n variant=\"compact\"\n collapsible\n defaultExpanded={false}\n onNavigate={onNavigateSource}\n />\n )}\n\n {/* Follow-up suggestions */}\n {response.follow_up_suggestions.length > 0 && onFollowUp && (\n <FollowUpChips\n suggestions={response.follow_up_suggestions}\n onSelect={onFollowUp}\n />\n )}\n </div>\n )\n}\n\nexport { AgentResponse }\nexport type { AgentResponseProps }\n","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeSanitize from 'rehype-sanitize'\nimport { twMerge } from 'tailwind-merge'\n\ntype ResponseMessageProps = {\n content: string\n className?: string\n}\n\nfunction normalizeMarkdownLists(content: string) {\n // Some providers emit compact list markdown like \"Intro: - item 1 - item 2\".\n // Insert a paragraph break before an inline list marker so markdown parses it as a list.\n return content.replace(/:\\s+-\\s+/g, ':\\n\\n- ')\n}\n\nfunction ResponseMessage({ content, className }: ResponseMessageProps) {\n return (\n <div\n className={twMerge(\n 'text-sm leading-relaxed text-text-primary',\n '[&_p]:my-2',\n '[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6',\n '[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6',\n '[&_li]:my-1',\n '[&_strong]:text-text-primary [&_strong]:font-semibold',\n '[&_em]:text-text-secondary',\n '[&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-text-primary [&_h1]:mt-4 [&_h1]:mb-2',\n '[&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-text-primary [&_h2]:mt-3 [&_h2]:mb-1.5',\n '[&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-accent [&_h3]:mt-2 [&_h3]:mb-1',\n '[&_code]:bg-surface-raised [&_code]:text-accent [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono',\n '[&_pre]:bg-surface-raised [&_pre]:border [&_pre]:border-border [&_pre]:rounded-xl [&_pre]:p-4 [&_pre]:overflow-x-auto',\n '[&_hr]:my-3 [&_hr]:border-border',\n '[&_blockquote]:border-l-2 [&_blockquote]:border-border-strong [&_blockquote]:pl-4 [&_blockquote]:text-text-secondary',\n '[&_a]:text-accent [&_a]:underline-offset-2 [&_a]:hover:text-accent/80',\n className,\n )}\n data-testid=\"response-message\"\n >\n <ReactMarkdown\n rehypePlugins={[rehypeSanitize]}\n components={{\n script: () => null,\n iframe: () => null,\n p: ({ children }) => <p className=\"my-2\">{children}</p>,\n ul: ({ children }) => <ul className=\"my-2 list-disc pl-6\">{children}</ul>,\n ol: ({ children }) => <ol className=\"my-2 list-decimal pl-6\">{children}</ol>,\n li: ({ children, ...props }) => {\n let content = children\n // Strip leading \"N.\" or \"N)\" text that duplicates the ol counter\n if ((props as Record<string, unknown>).ordered) {\n content = React.Children.map(children, (child, i) => {\n if (i === 0 && typeof child === 'string') {\n return child.replace(/^\\d+[.)]\\s*/, '')\n }\n return child\n })\n }\n return <li className=\"my-1\">{content}</li>\n },\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n em: ({ children }) => <em className=\"italic text-text-secondary\">{children}</em>,\n h1: ({ children }) => <h1 className=\"text-base font-bold mt-4 mb-2\">{children}</h1>,\n h2: ({ children }) => <h2 className=\"text-sm font-bold mt-3 mb-1\">{children}</h2>,\n h3: ({ children }) => <h3 className=\"text-sm font-semibold mt-2 mb-1\">{children}</h3>,\n hr: () => <hr className=\"my-3 border-border\" />,\n code: ({ children }) => <code className=\"bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono\">{children}</code>,\n }}\n >\n {normalizeMarkdownLists(content)}\n </ReactMarkdown>\n </div>\n )\n}\n\nexport { ResponseMessage }\nexport type { ResponseMessageProps }\n","import React from 'react'\nimport type { AgentResponse } from '../../types/agent'\n\ntype StructuredResponseProps = {\n uiHint: AgentResponse['ui_hint']\n data: Record<string, unknown> | null\n className?: string\n}\n\n/** Parse a value that may be a JSON-encoded string or already parsed. */\nfunction tryParse<T>(value: unknown): T | null {\n if (value === undefined || value === null) return null\n if (typeof value === 'string') {\n try {\n return JSON.parse(value) as T\n } catch {\n return null\n }\n }\n return value as T\n}\n\nfunction renderSteps(data: Record<string, unknown>) {\n const steps = tryParse<string[]>(data.steps)\n if (!steps || !Array.isArray(steps)) return null\n return (\n <ol className=\"flex flex-col gap-2\" data-testid=\"structured-steps\">\n {steps.map((step, i) => (\n <li key={i} className=\"flex items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-accent text-[11px] font-semibold text-white\"\n aria-hidden=\"true\"\n >\n {i + 1}\n </span>\n <span className=\"text-sm text-text-primary leading-relaxed\">{step}</span>\n </li>\n ))}\n </ol>\n )\n}\n\nfunction renderTable(data: Record<string, unknown>) {\n const columns = tryParse<string[]>(data.columns)\n // rows may be array-of-arrays or array-of-objects; normalise to array-of-arrays\n const rawRows = tryParse<unknown[]>(data.rows)\n\n if (columns && rawRows && Array.isArray(columns) && Array.isArray(rawRows)) {\n return (\n <div className=\"overflow-x-auto rounded-lg border border-border\" data-testid=\"structured-table\">\n <table role=\"table\" className=\"w-full border-collapse text-sm\">\n <thead className=\"bg-surface-raised\">\n <tr>\n {columns.map((col) => (\n <th\n key={col}\n className=\"text-left px-4 py-2.5 font-semibold text-text-primary border-b border-border\"\n >\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rawRows.map((row, i) => {\n const cells = Array.isArray(row)\n ? row\n : columns.map((col) => (row as Record<string, unknown>)[col])\n return (\n <tr key={i} className=\"even:bg-surface-raised/40\">\n {cells.map((cell, j) => (\n <td key={j} className=\"px-4 py-2 text-text-secondary border-b border-border\">\n {String(cell ?? '')}\n </td>\n ))}\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )\n }\n\n // Fallback: key-value table\n const entries = Object.entries(data)\n return (\n <div className=\"overflow-x-auto rounded-lg border border-border\" data-testid=\"structured-table\">\n <table role=\"table\" className=\"w-full border-collapse text-sm\">\n <tbody>\n {entries.map(([key, value]) => (\n <tr key={key} className=\"even:bg-surface-raised/40\">\n <td className=\"px-4 py-2 text-text-primary font-medium border-b border-border w-1/3\">\n {key}\n </td>\n <td className=\"px-4 py-2 text-text-secondary border-b border-border\">\n {typeof value === 'object' ? JSON.stringify(value) : String(value ?? '')}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\nfunction renderCard(data: Record<string, unknown>) {\n const title = typeof data.title === 'string' ? data.title : null\n const body = typeof data.body === 'string' ? data.body : null\n const link = typeof data.link === 'string' ? data.link : null\n const linkLabel = typeof data.link_label === 'string' ? data.link_label : 'Learn more'\n\n return (\n <div\n className=\"rounded-xl border border-border bg-surface-raised p-4 flex flex-col gap-2\"\n data-testid=\"structured-card\"\n >\n {title && <p className=\"text-sm font-semibold text-text-primary\">{title}</p>}\n {body && <p className=\"text-sm text-text-secondary leading-relaxed\">{body}</p>}\n {link && (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-1 inline-flex items-center gap-1 text-xs font-medium text-accent hover:text-accent/80 underline-offset-2 hover:underline transition-colors\"\n >\n {linkLabel}\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\" />\n </svg>\n </a>\n )}\n </div>\n )\n}\n\nfunction renderList(data: Record<string, unknown>) {\n const items = tryParse<string[]>(data.items)\n const title = typeof data.title === 'string' ? data.title : null\n if (!items || !Array.isArray(items)) return null\n\n return (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"structured-list\">\n {title && (\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary mb-1\">{title}</p>\n )}\n <ul className=\"flex flex-col gap-1.5\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-start gap-2.5\">\n <span className=\"mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-accent\" aria-hidden=\"true\" />\n <span className=\"text-sm text-text-primary leading-relaxed\">{item}</span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n\nfunction renderWarning(data: Record<string, unknown>) {\n const severity = typeof data.severity === 'string' ? data.severity : 'medium'\n const action = typeof data.action === 'string' ? data.action : null\n const details = typeof data.details === 'string' ? data.details : null\n const isHigh = severity === 'high'\n\n return (\n <div\n role=\"alert\"\n className={`rounded-xl border p-4 flex gap-3 ${\n isHigh\n ? 'border-red-200 bg-red-50 dark:border-red-900/50 dark:bg-red-950/30'\n : 'border-amber-200 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/30'\n }`}\n data-testid=\"structured-warning\"\n >\n <svg\n className={`mt-0.5 h-5 w-5 shrink-0 ${isHigh ? 'text-red-500' : 'text-amber-500'}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\" />\n </svg>\n <div className=\"flex flex-col gap-1\">\n {action && (\n <p className={`text-sm font-semibold ${isHigh ? 'text-red-700 dark:text-red-300' : 'text-amber-700 dark:text-amber-300'}`}>\n {action}\n </p>\n )}\n {details && (\n <p className={`text-sm ${isHigh ? 'text-red-600 dark:text-red-400' : 'text-amber-600 dark:text-amber-400'}`}>\n {details}\n </p>\n )}\n </div>\n </div>\n )\n}\n\nfunction StructuredResponse({ uiHint, data: rawData, className }: StructuredResponseProps) {\n // Defensive: data may arrive as a JSON string from the API instead of a parsed object.\n const data = typeof rawData === 'string'\n ? (() => { try { return JSON.parse(rawData) as Record<string, unknown> } catch { return null } })()\n : rawData\n if (!data) return null\n\n let content: React.ReactNode\n\n switch (uiHint) {\n case 'steps':\n content = renderSteps(data)\n break\n case 'table':\n content = renderTable(data)\n break\n case 'card':\n content = renderCard(data)\n break\n case 'list':\n content = renderList(data)\n break\n case 'warning':\n content = renderWarning(data)\n break\n case 'text':\n content = typeof data.text === 'string'\n ? <p data-testid=\"structured-text\">{data.text}</p>\n : null\n break\n default:\n content = null\n }\n\n if (!content) return null\n\n return (\n <div className={className} data-testid=\"structured-response\">\n {content}\n </div>\n )\n}\n\nexport { StructuredResponse }\nexport type { StructuredResponseProps }\n","'use client'\n\nimport React, { useState } from 'react'\nimport type { Source } from '../../types/agent'\nimport { SourceCard } from '../SourceCard'\n\ntype SourceListProps = {\n sources: Source[]\n variant?: 'compact' | 'expanded'\n collapsible?: boolean\n defaultExpanded?: boolean\n onNavigate?: (source: Source) => void\n className?: string\n}\n\nfunction SourceList({\n sources,\n variant = 'compact',\n collapsible = false,\n defaultExpanded = true,\n onNavigate,\n className,\n}: SourceListProps) {\n const [isExpanded, setIsExpanded] = useState(defaultExpanded)\n\n if (sources.length === 0) return null\n\n const content = (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"source-list-items\">\n {sources.map((source) => (\n <SourceCard\n key={source.document_id}\n source={source}\n variant={variant}\n onNavigate={onNavigate}\n />\n ))}\n </div>\n )\n\n if (!collapsible) {\n return (\n <div className={className} data-testid=\"source-list\">\n {content}\n </div>\n )\n }\n\n return (\n <div className={className} data-testid=\"source-list\">\n <button\n type=\"button\"\n onClick={() => setIsExpanded(prev => !prev)}\n aria-expanded={isExpanded}\n className=\"flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-text-secondary hover:text-accent mb-2 transition-colors duration-200\"\n >\n <svg\n className={`w-4 h-4 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n Sources ({sources.length})\n </button>\n {isExpanded && content}\n </div>\n )\n}\n\nexport { SourceList }\nexport type { SourceListProps }\n","import React from 'react'\nimport { Badge } from '@surf-kit/core'\nimport { twMerge } from 'tailwind-merge'\nimport type { Source } from '../../types/agent'\n\ntype SourceCardProps = {\n source: Source\n variant?: 'compact' | 'expanded'\n onNavigate?: (source: Source) => void\n className?: string\n}\n\nfunction getConfidenceIntent(confidence: number) {\n if (confidence >= 0.8) return 'success' as const\n if (confidence >= 0.5) return 'warning' as const\n return 'error' as const\n}\n\nfunction getConfidenceLabel(confidence: number) {\n if (confidence >= 0.8) return 'High'\n if (confidence >= 0.5) return 'Medium'\n return 'Low'\n}\n\nfunction SourceCard({ source, variant = 'compact', onNavigate, className }: SourceCardProps) {\n const handleClick = () => {\n if (onNavigate) {\n onNavigate(source)\n }\n }\n\n const isCompact = variant === 'compact'\n\n return (\n <div\n className={twMerge(\n 'rounded-xl border transition-all duration-200',\n 'bg-surface border-border',\n onNavigate && 'cursor-pointer hover:border-border-strong',\n className,\n )}\n data-document-id={source.document_id}\n data-testid=\"source-card\"\n >\n <div\n className={isCompact ? 'px-4 py-3' : 'px-6 py-4'}\n onClick={handleClick}\n role={onNavigate ? 'button' : undefined}\n tabIndex={onNavigate ? 0 : undefined}\n onKeyDown={\n onNavigate\n ? (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick()\n }\n }\n : undefined\n }\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n {source.url ? (\n <a\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm font-medium text-accent hover:underline truncate block\"\n onClick={(e) => e.stopPropagation()}\n >\n {source.title}\n <svg\n className=\"inline-block ml-1 w-3 h-3 opacity-60\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n </a>\n ) : (\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {source.title}\n </p>\n )}\n {source.section && (\n <p className=\"text-[11px] font-semibold uppercase tracking-wider text-text-secondary truncate mt-0.5\">\n {source.section}\n </p>\n )}\n </div>\n <Badge\n intent={getConfidenceIntent(source.confidence)}\n size=\"sm\"\n >\n {getConfidenceLabel(source.confidence)}\n </Badge>\n </div>\n {!isCompact && (\n <p className=\"text-xs text-text-secondary mt-2 line-clamp-3 leading-relaxed\">\n {source.snippet}\n </p>\n )}\n </div>\n </div>\n )\n}\n\nexport { SourceCard }\nexport type { SourceCardProps }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\n\ntype FollowUpChipsProps = {\n suggestions: string[]\n onSelect: (suggestion: string) => void\n className?: string\n}\n\nfunction FollowUpChips({ suggestions, onSelect, className }: FollowUpChipsProps) {\n if (suggestions.length === 0) return null\n\n return (\n <div\n className={twMerge('flex flex-wrap gap-2 py-1', className)}\n role=\"group\"\n aria-label=\"Follow-up suggestions\"\n data-testid=\"follow-up-chips\"\n >\n {suggestions.map(suggestion => (\n <button\n key={suggestion}\n type=\"button\"\n onClick={() => onSelect(suggestion)}\n className={twMerge(\n 'px-4 py-1.5 rounded-full text-sm whitespace-nowrap',\n 'border border-border bg-transparent text-text-secondary',\n 'hover:bg-accent/10 hover:border-interactive hover:text-text-primary',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'transition-all duration-200',\n )}\n >\n {suggestion}\n </button>\n ))}\n </div>\n )\n}\n\nexport { FollowUpChips }\nexport type { FollowUpChipsProps }\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useState, useRef, useCallback } from 'react'\nimport type { Attachment } from '../../types/chat'\n\nconst ALLOWED_TYPES = new Set([\n 'image/png',\n 'image/jpeg',\n 'image/gif',\n 'image/webp',\n 'application/pdf',\n])\nconst MAX_FILE_SIZE = 10 * 1024 * 1024 // 10 MB\nconst MAX_ATTACHMENTS = 5\n\nexport type MessageComposerProps = {\n onSend: (content: string, attachments?: Attachment[]) => void\n isLoading?: boolean\n placeholder?: string\n className?: string\n}\n\nfunction ArrowUpIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10 16V4\" />\n <path d=\"M4 10l6-6 6 6\" />\n </svg>\n )\n}\n\nfunction StopIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <rect x=\"3\" y=\"3\" width=\"10\" height=\"10\" rx=\"2\" />\n </svg>\n )\n}\n\nfunction PaperclipIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48\" />\n </svg>\n )\n}\n\nfunction XIcon({ size = 14 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M18 6L6 18\" />\n <path d=\"M6 6l12 12\" />\n </svg>\n )\n}\n\nfunction DocumentIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n )\n}\n\nfunction fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n const result = reader.result as string\n // Strip data URL prefix (e.g. \"data:image/png;base64,\")\n const base64 = result.split(',')[1]\n resolve(base64)\n }\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction AttachmentPreview({\n attachment,\n onRemove,\n}: {\n attachment: Attachment\n onRemove: () => void\n}) {\n const isImage = attachment.content_type.startsWith('image/')\n\n return (\n <div className=\"relative group flex-shrink-0\">\n {isImage ? (\n <div className=\"w-16 h-16 rounded-lg overflow-hidden border border-border/60 bg-surface-alt\">\n <img\n src={attachment.preview_url ?? `data:${attachment.content_type};base64,${attachment.data}`}\n alt={attachment.filename}\n className=\"w-full h-full object-cover\"\n />\n </div>\n ) : (\n <div className=\"h-16 px-3 rounded-lg border border-border/60 bg-surface-alt flex items-center gap-2\">\n <div className=\"text-text-muted\">\n <DocumentIcon />\n </div>\n <div className=\"flex flex-col min-w-0\">\n <span className=\"text-xs text-text-primary truncate max-w-[120px]\">\n {attachment.filename}\n </span>\n <span className=\"text-[10px] text-text-muted\">PDF</span>\n </div>\n </div>\n )}\n <button\n type=\"button\"\n onClick={onRemove}\n className={twMerge(\n 'absolute -top-1.5 -right-1.5',\n 'w-5 h-5 rounded-full',\n 'bg-text-muted/80 text-white',\n 'flex items-center justify-center',\n 'opacity-0 group-hover:opacity-100',\n 'transition-opacity duration-150',\n 'hover:bg-text-primary',\n )}\n aria-label={`Remove ${attachment.filename}`}\n >\n <XIcon size={10} />\n </button>\n </div>\n )\n}\n\nfunction MessageComposer({\n onSend,\n isLoading = false,\n placeholder = 'Type a message...',\n className,\n}: MessageComposerProps) {\n const [value, setValue] = useState('')\n const [attachments, setAttachments] = useState<Attachment[]>([])\n const [dragOver, setDragOver] = useState(false)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const canSend = (value.trim().length > 0 || attachments.length > 0) && !isLoading\n\n const resetHeight = useCallback(() => {\n const el = textareaRef.current\n if (el) {\n el.style.height = 'auto'\n el.style.overflowY = 'hidden'\n }\n }, [])\n\n const handleSend = useCallback(() => {\n if (!canSend) return\n const message = value.trim() || (attachments.length > 0 ? 'Please analyse the attached file(s).' : '')\n if (!message && attachments.length === 0) return\n onSend(message, attachments.length > 0 ? attachments : undefined)\n setValue('')\n setAttachments([])\n resetHeight()\n textareaRef.current?.focus()\n }, [canSend, onSend, value, attachments, resetHeight])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n },\n [handleSend],\n )\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setValue(e.target.value)\n const el = e.target\n el.style.height = 'auto'\n const capped = Math.min(el.scrollHeight, 200)\n el.style.height = `${capped}px`\n el.style.overflowY = el.scrollHeight > 200 ? 'auto' : 'hidden'\n },\n [],\n )\n\n const addFiles = useCallback(async (files: FileList | File[]) => {\n const fileArray = Array.from(files)\n\n for (const file of fileArray) {\n if (attachments.length >= MAX_ATTACHMENTS) break\n if (!ALLOWED_TYPES.has(file.type)) continue\n if (file.size > MAX_FILE_SIZE) continue\n\n try {\n const data = await fileToBase64(file)\n const previewUrl = file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined\n const attachment: Attachment = {\n filename: file.name,\n content_type: file.type,\n data,\n preview_url: previewUrl,\n }\n setAttachments(prev => {\n if (prev.length >= MAX_ATTACHMENTS) return prev\n return [...prev, attachment]\n })\n } catch {\n // Skip files that can't be read\n }\n }\n }, [attachments.length])\n\n const handleFileSelect = useCallback(() => {\n fileInputRef.current?.click()\n }, [])\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (e.target.files) {\n void addFiles(e.target.files)\n e.target.value = '' // reset so the same file can be selected again\n }\n },\n [addFiles],\n )\n\n const removeAttachment = useCallback((index: number) => {\n setAttachments(prev => {\n const removed = prev[index]\n if (removed?.preview_url) URL.revokeObjectURL(removed.preview_url)\n return prev.filter((_, i) => i !== index)\n })\n }, [])\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent) => {\n const items = e.clipboardData.items\n const files: File[] = []\n for (const item of items) {\n if (item.kind === 'file' && ALLOWED_TYPES.has(item.type)) {\n const file = item.getAsFile()\n if (file) files.push(file)\n }\n }\n if (files.length > 0) {\n void addFiles(files)\n }\n },\n [addFiles],\n )\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOver(true)\n }, [])\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOver(false)\n }, [])\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOver(false)\n if (e.dataTransfer.files.length > 0) {\n void addFiles(e.dataTransfer.files)\n }\n },\n [addFiles],\n )\n\n return (\n <div\n className={twMerge(\n 'relative shrink-0 rounded-3xl border bg-surface',\n 'shadow-lg shadow-black/10',\n 'transition-all duration-200',\n 'focus-within:border-accent/40 focus-within:shadow-accent/5',\n dragOver ? 'border-accent/60 bg-accent/5' : 'border-border/60',\n className,\n )}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept=\"image/png,image/jpeg,image/gif,image/webp,application/pdf\"\n onChange={handleFileInputChange}\n className=\"hidden\"\n aria-hidden=\"true\"\n />\n\n {/* Attachment previews */}\n {attachments.length > 0 && (\n <div className=\"flex gap-2 px-4 pt-3 pb-1 overflow-x-auto\">\n {attachments.map((att, i) => (\n <AttachmentPreview\n key={`${att.filename}-${i}`}\n attachment={att}\n onRemove={() => removeAttachment(i)}\n />\n ))}\n </div>\n )}\n\n {/* Drag overlay */}\n {dragOver && (\n <div className=\"absolute inset-0 rounded-3xl flex items-center justify-center bg-accent/10 border-2 border-dashed border-accent/40 z-10 pointer-events-none\">\n <span className=\"text-sm font-display font-semibold text-accent\">Drop files here</span>\n </div>\n )}\n\n <div className=\"flex items-end\">\n {/* Attach button */}\n <button\n type=\"button\"\n onClick={handleFileSelect}\n disabled={isLoading || attachments.length >= MAX_ATTACHMENTS}\n aria-label=\"Attach file\"\n className={twMerge(\n 'flex-shrink-0 ml-2 mb-3',\n 'inline-flex items-center justify-center',\n 'w-9 h-9 rounded-full',\n 'transition-all duration-200',\n 'text-text-muted/60 hover:text-text-secondary hover:bg-text-muted/10',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-transparent',\n )}\n >\n <PaperclipIcon />\n </button>\n\n <textarea\n ref={textareaRef}\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n rows={1}\n disabled={isLoading}\n className={twMerge(\n 'flex-1 resize-none bg-transparent',\n 'pl-2 pr-14 pt-4 pb-4 text-[15px] leading-relaxed',\n 'text-text-primary placeholder:text-text-muted/70',\n 'focus:outline-none',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n 'overflow-hidden',\n )}\n style={{ colorScheme: 'dark' }}\n aria-label=\"Message input\"\n />\n\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n aria-label=\"Send message\"\n className={twMerge(\n 'absolute bottom-3 right-3',\n 'inline-flex items-center justify-center',\n 'w-9 h-9 rounded-full',\n 'transition-all duration-200',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n canSend\n ? 'bg-accent text-white hover:bg-accent-hover active:scale-90 shadow-md shadow-accent/25'\n : isLoading\n ? 'bg-text-muted/20 text-text-secondary hover:bg-text-muted/30'\n : 'bg-transparent text-text-muted/40 cursor-default',\n )}\n >\n {isLoading ? <StopIcon /> : <ArrowUpIcon />}\n </button>\n </div>\n </div>\n )\n}\n\nexport { MessageComposer }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\n\nexport type WelcomeScreenProps = {\n title?: string\n message?: React.ReactNode\n icon?: React.ReactNode\n iconClassName?: string\n suggestedQuestions?: string[]\n onQuestionSelect?: (question: string) => void\n className?: string\n}\n\nfunction WelcomeScreen({\n title = 'Welcome',\n message = 'How can I help you today?',\n icon,\n iconClassName,\n suggestedQuestions = [],\n onQuestionSelect,\n className,\n}: WelcomeScreenProps) {\n return (\n <div\n className={twMerge(\n 'flex flex-1 flex-col items-center justify-center gap-8 p-8 text-center motion-safe:animate-fadeUp',\n className,\n )}\n >\n {/* Icon */}\n {icon ? (\n iconClassName ? (\n <div className={iconClassName} aria-hidden=\"true\">\n {icon}\n </div>\n ) : (\n icon\n )\n ) : (\n <div\n className={twMerge(\n 'w-14 h-14 rounded-2xl bg-accent/10 border border-border flex items-center justify-center pulse-glow',\n iconClassName,\n )}\n aria-hidden=\"true\"\n >\n <span className=\"text-2xl\">✦</span>\n </div>\n )}\n\n {/* Text */}\n <div className=\"flex flex-col gap-2\">\n {title && (\n <h2 className=\"text-3xl font-bold text-text-primary\">{title}</h2>\n )}\n <p className=\"text-text-secondary text-base leading-relaxed max-w-md\">{message}</p>\n </div>\n\n {/* Suggested question chips */}\n {suggestedQuestions.length > 0 && (\n <div\n className=\"flex flex-wrap justify-center gap-2 max-w-xl\"\n role=\"group\"\n aria-label=\"Suggested questions\"\n >\n {suggestedQuestions.map(question => (\n <button\n key={question}\n type=\"button\"\n onClick={() => onQuestionSelect?.(question)}\n className={twMerge(\n 'px-3.5 py-1.5 rounded-full text-[12px]',\n 'border border-border bg-transparent text-text-secondary',\n 'hover:bg-accent/10 hover:border-interactive hover:text-text-primary',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'transition-colors duration-200',\n )}\n >\n {question}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nexport { WelcomeScreen }\n","'use client'\n\nimport React, { useEffect, useRef } from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport { WaveLoader } from '@surf-kit/core'\nimport type { StreamState } from '../../types/streaming'\nimport { useCharacterDrain } from '../../hooks/useCharacterDrain'\nimport { ResponseMessage } from '../../response/ResponseMessage'\n\ntype StreamingMessageProps = {\n stream: StreamState\n onComplete?: () => void\n onDraining?: (isDraining: boolean) => void\n showPhases?: boolean\n className?: string\n}\n\nconst phaseLabels: Record<StreamState['phase'], string> = {\n idle: '',\n waiting: 'Waiting...',\n thinking: 'Thinking...',\n retrieving: 'Searching...',\n generating: 'Writing...',\n verifying: 'Verifying...',\n}\n\n// Cursor styles: a catch-all targets any last-child element, with overrides\n// for ul/ol (target last li) and blockquote (target last p) so the cursor\n// appears inline with the final text rather than on a new line.\n// Uses steps(1) for a crisp blink that won't smooth-fade to invisible.\nconst CURSOR_STYLES = `\n.sk-streaming-cursor > :not(ul,ol,blockquote):last-child::after,\n.sk-streaming-cursor > :is(ul,ol):last-child > li:last-child::after,\n.sk-streaming-cursor > blockquote:last-child > p:last-child::after {\n content: \"\";\n display: inline-block;\n width: 2px;\n height: 1em;\n background: var(--color-accent, #38bdf8);\n animation: sk-cursor-blink 0.8s steps(1) infinite;\n margin-left: 2px;\n vertical-align: text-bottom;\n}\n@keyframes sk-cursor-blink {\n 0%, 60% { opacity: 1; }\n 61%, 100% { opacity: 0; }\n}\n`\n\nfunction StreamingMessage({\n stream,\n onComplete,\n onDraining,\n showPhases = true,\n className,\n}: StreamingMessageProps) {\n const onCompleteRef = useRef(onComplete)\n onCompleteRef.current = onComplete\n const onDrainingRef = useRef(onDraining)\n onDrainingRef.current = onDraining\n const wasActiveRef = useRef(stream.active)\n\n useEffect(() => {\n if (wasActiveRef.current && !stream.active) {\n onCompleteRef.current?.()\n }\n wasActiveRef.current = stream.active\n }, [stream.active])\n\n const phaseLabel = phaseLabels[stream.phase]\n const { displayed: rawDisplayed, isDraining } = useCharacterDrain(stream.content)\n // Trim trailing whitespace so ReactMarkdown doesn't create empty trailing\n // block elements that the cursor would land inside.\n const displayedContent = (stream.active || isDraining) ? rawDisplayed.trimEnd() : rawDisplayed\n\n // Notify parent of draining state changes\n useEffect(() => {\n onDrainingRef.current?.(isDraining)\n }, [isDraining])\n\n // Format agent label from stream.agent (e.g. \"coordinator_agent\" → \"coordinator\")\n const agentLabel = stream.agent\n ? stream.agent.replace('_agent', '').replace('_', ' ')\n : null\n\n // Show phase indicator only when there's no displayed content yet\n const showPhaseIndicator = showPhases && stream.active && stream.phase !== 'idle' && !displayedContent\n const showCursor = (stream.active || isDraining) && !!displayedContent\n\n return (\n <div className={twMerge('flex w-full flex-col items-start', className)} data-testid=\"streaming-message\">\n {/* Screen reader announcements */}\n <div aria-live=\"assertive\" className=\"sr-only\">\n {stream.active && stream.phase !== 'idle' && 'Response started'}\n {!stream.active && stream.content && 'Response complete'}\n </div>\n\n {showCursor && <style>{CURSOR_STYLES}</style>}\n\n {/* Agent label */}\n {agentLabel && (\n <div className=\"text-[11px] font-display font-semibold uppercase tracking-[0.08em] text-text-muted px-1 mb-1.5\">\n {agentLabel}\n </div>\n )}\n\n <div className=\"max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft\">\n {showPhaseIndicator && (\n <div\n className=\"flex items-center gap-2 text-sm text-text-secondary\"\n data-testid=\"phase-indicator\"\n >\n <span aria-hidden=\"true\">\n <WaveLoader size=\"sm\" color=\"#38bdf8\" />\n </span>\n <span>{phaseLabel}</span>\n </div>\n )}\n\n {displayedContent && (\n <ResponseMessage\n content={displayedContent}\n className={showCursor ? 'sk-streaming-cursor' : undefined}\n />\n )}\n </div>\n </div>\n )\n}\n\nexport { StreamingMessage }\nexport type { StreamingMessageProps }\n","'use client'\n\nimport { useState, useRef, useEffect } from 'react'\n\nexport interface CharacterDrainResult {\n displayed: string\n isDraining: boolean\n}\n\n/**\n * Smoothly drains a growing `target` string character-by-character using\n * `requestAnimationFrame`, decoupling visual rendering from network packet\n * timing so text appears to type out instead of arriving in chunks.\n *\n * When `target` resets to empty (e.g. stream finished), the hook continues\n * draining the previous content to completion before resetting, so the\n * typing animation isn't cut short.\n *\n * Design: the RAF loop is long-lived — it does NOT restart on every delta.\n * The tick function is stored in a ref (updated each render) so the loop\n * always reads the latest drainTarget without being cancelled/restarted.\n * A separate kick-start effect re-fires the loop when it was idle and new\n * content arrives.\n */\nexport function useCharacterDrain(target: string, msPerChar = 15): CharacterDrainResult {\n const [displayed, setDisplayed] = useState('')\n const indexRef = useRef(0)\n const lastTimeRef = useRef(0)\n const rafRef = useRef<number | null>(null)\n // Holds the last non-empty target so we can finish draining after source resets\n const drainTargetRef = useRef('')\n const msPerCharRef = useRef(msPerChar)\n\n msPerCharRef.current = msPerChar\n\n // Update drain target when new content arrives; preserve old value on reset\n if (target !== '') {\n drainTargetRef.current = target\n }\n\n const drainTarget = drainTargetRef.current\n const isDraining = displayed.length < drainTarget.length\n\n // Tick function stored in ref so the long-lived RAF loop always reads the\n // latest drainTarget and msPerChar without being cancelled/recreated.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const tickRef = useRef<(now: number) => void>(() => {})\n tickRef.current = (now: number) => {\n const currentTarget = drainTargetRef.current\n if (currentTarget === '') {\n rafRef.current = null\n return\n }\n\n if (lastTimeRef.current === 0) lastTimeRef.current = now\n const elapsed = now - lastTimeRef.current\n const charsToAdvance = Math.floor(elapsed / msPerCharRef.current)\n\n if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {\n let nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length)\n // When the slice would end with whitespace, advance past it to include\n // the next visible character. This prevents trimEnd() in the streaming\n // UI from stripping trailing newlines and causing ReactMarkdown to\n // \"jump\" between block structures in a single frame (e.g. a heading\n // suddenly gaining a following paragraph with no transition).\n while (\n nextIndex < currentTarget.length &&\n currentTarget[nextIndex - 1].trim() === ''\n ) {\n nextIndex++\n }\n indexRef.current = nextIndex\n lastTimeRef.current = now\n setDisplayed(currentTarget.slice(0, nextIndex))\n }\n\n if (indexRef.current < currentTarget.length) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n } else {\n rafRef.current = null\n }\n }\n\n // Kick-start the RAF loop when new content arrives and the loop is idle.\n // No cleanup here — we intentionally do NOT cancel the running loop when\n // drainTarget grows; the long-lived tick will pick up new chars automatically.\n useEffect(() => {\n if (\n drainTargetRef.current !== '' &&\n indexRef.current < drainTargetRef.current.length &&\n rafRef.current === null\n ) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n }\n }, [drainTarget]) // drainTarget change = new content; check if loop needs kicking\n\n // Once drain completes and source stream is already done, reset all state\n useEffect(() => {\n if (target === '' && !isDraining && displayed !== '') {\n indexRef.current = 0\n lastTimeRef.current = 0\n drainTargetRef.current = ''\n setDisplayed('')\n }\n }, [target, isDraining, displayed])\n\n // Cancel any pending RAF on unmount\n useEffect(() => {\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n }\n }, [])\n\n return { displayed, isDraining }\n}\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport type { ConversationSummary } from '../../types/chat'\n\nexport type ConversationListProps = {\n conversations: ConversationSummary[]\n activeId?: string\n onSelect: (id: string) => void\n onDelete?: (id: string) => void\n onNew?: () => void\n className?: string\n}\n\nfunction ConversationList({\n conversations,\n activeId,\n onSelect,\n onDelete,\n onNew,\n className,\n}: ConversationListProps) {\n return (\n <nav\n aria-label=\"Conversation list\"\n className={twMerge('flex flex-col h-full bg-canvas', className)}\n >\n {onNew && (\n <div className=\"p-3 border-b border-border\">\n <button\n type=\"button\"\n onClick={onNew}\n className=\"w-full px-4 py-2.5 rounded-xl text-sm font-semibold bg-accent text-white hover:bg-accent-hover transition-all duration-200\"\n >\n New conversation\n </button>\n </div>\n )}\n\n <ul role=\"list\" className=\"flex-1 overflow-y-auto\">\n {conversations.map((conversation) => {\n const isActive = conversation.id === activeId\n return (\n <li\n key={conversation.id}\n className={twMerge(\n 'flex items-start border-b border-border transition-colors duration-200',\n 'hover:bg-surface',\n isActive && 'bg-surface-raised border-l-2 border-l-accent',\n )}\n >\n <button\n type=\"button\"\n onClick={() => onSelect(conversation.id)}\n aria-current={isActive ? 'true' : undefined}\n className=\"flex-1 min-w-0 text-left px-4 py-3\"\n >\n <div className=\"text-sm font-medium text-brand-cream truncate\">\n {conversation.title}\n </div>\n <div className=\"text-xs text-brand-cream/40 truncate mt-0.5 leading-relaxed\">\n {conversation.lastMessage}\n </div>\n </button>\n {onDelete && (\n <button\n type=\"button\"\n onClick={() => onDelete(conversation.id)}\n aria-label={`Delete ${conversation.title}`}\n className=\"shrink-0 p-1.5 m-2 rounded-lg text-brand-cream/25 hover:text-brand-watermelon hover:bg-brand-watermelon/10 transition-colors duration-200\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n </button>\n )}\n </li>\n )\n })}\n\n {conversations.length === 0 && (\n <li className=\"px-4 py-8 text-center\">\n <span className=\"text-sm text-brand-cream/30 font-body\">No conversations yet</span>\n </li>\n )}\n </ul>\n </nav>\n )\n}\n\nexport { ConversationList }\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useRef, useEffect } from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\n\nexport type AgentPanelProps = {\n endpoint: string\n isOpen: boolean\n onClose: () => void\n side?: 'left' | 'right'\n width?: string | number\n title?: string\n className?: string\n}\n\nfunction AgentPanel({\n endpoint,\n isOpen,\n onClose,\n side = 'right',\n width = 400,\n title = 'Chat',\n className,\n}: AgentPanelProps) {\n const panelRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!isOpen) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, onClose])\n\n const widthStyle = typeof width === 'number' ? `${width}px` : width\n\n return (\n <div\n className={twMerge('fixed inset-0 z-50', !isOpen && 'pointer-events-none')}\n aria-hidden={!isOpen}\n >\n {/* Backdrop */}\n <div\n className={twMerge(\n 'fixed inset-0 transition-opacity duration-300',\n isOpen\n ? 'opacity-100 bg-brand-dark/70 backdrop-blur-sm pointer-events-auto'\n : 'opacity-0 pointer-events-none',\n )}\n onClick={isOpen ? onClose : undefined}\n data-testid=\"panel-backdrop\"\n />\n\n {/* Panel */}\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-label={title}\n aria-modal={isOpen ? 'true' : undefined}\n style={{ width: widthStyle, maxWidth: '100vw' }}\n className={twMerge(\n 'fixed top-0 h-full flex flex-col z-50 bg-brand-dark shadow-card',\n 'transition-transform duration-300 ease-in-out',\n side === 'left'\n ? `left-0 border-r border-brand-gold/15 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`\n : `right-0 border-l border-brand-gold/15 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`,\n className,\n )}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-brand-gold/15 px-5 py-3.5 bg-brand-dark-panel/60 backdrop-blur-sm shrink-0\">\n <h2 className=\"text-base font-display font-semibold text-brand-cream\">{title}</h2>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close panel\"\n className=\"rounded-xl p-2 text-brand-cream/40 hover:text-brand-cream/80 hover:bg-brand-cream/5 transition-colors duration-200\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n {/* Chat */}\n <AgentChat\n endpoint={endpoint}\n title={title}\n showHeader={false}\n showWelcomeTitle={false}\n className=\"flex-1 rounded-none border-0\"\n />\n </div>\n </div>\n )\n}\n\nexport { AgentPanel }\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useState, useCallback } from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\n\nexport type AgentWidgetProps = {\n endpoint: string\n position?: 'bottom-right' | 'bottom-left'\n triggerLabel?: string\n title?: string\n className?: string\n}\n\nfunction AgentWidget({\n endpoint,\n position = 'bottom-right',\n triggerLabel = 'Chat',\n title = 'Chat',\n className,\n}: AgentWidgetProps) {\n const [isOpen, setIsOpen] = useState(false)\n\n const toggle = useCallback(() => {\n setIsOpen((prev) => !prev)\n }, [])\n\n const positionClasses = position === 'bottom-left' ? 'left-4 bottom-4' : 'right-4 bottom-4'\n const popoverPositionClasses = position === 'bottom-left' ? 'left-4 bottom-20' : 'right-4 bottom-20'\n const popoverOrigin = position === 'bottom-left' ? 'origin-bottom-left' : 'origin-bottom-right'\n\n return (\n <div className={className}>\n {/* Popover — always rendered, animated with CSS */}\n <div\n role=\"dialog\"\n aria-label={title}\n aria-hidden={!isOpen}\n className={twMerge(\n 'fixed z-50 flex flex-col',\n 'w-[min(400px,calc(100vw-2rem))] h-[min(600px,calc(100vh-6rem))]',\n 'rounded-2xl overflow-hidden border border-brand-gold/15',\n 'bg-brand-dark/95 backdrop-blur-[12px] shadow-card',\n popoverPositionClasses,\n popoverOrigin,\n 'transition-all duration-200 ease-out',\n isOpen\n ? 'opacity-100 scale-100 pointer-events-auto translate-y-0'\n : 'opacity-0 scale-95 pointer-events-none translate-y-2',\n )}\n >\n {/* Popover header */}\n <div className=\"flex items-center justify-between px-4 py-2.5 bg-brand-dark-panel/80 border-b border-brand-gold/15 shrink-0\">\n <h2 className=\"text-sm font-display font-semibold text-brand-cream\">{title}</h2>\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n aria-label=\"Minimize chat\"\n className=\"rounded-lg p-1.5 text-brand-cream/40 hover:text-brand-cream/70 transition-colors duration-200\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n <AgentChat\n endpoint={endpoint}\n title={title}\n showHeader={false}\n showWelcomeTitle={false}\n className=\"flex-1 rounded-none border-0 min-h-0\"\n />\n </div>\n\n {/* FAB — gold glow */}\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={isOpen ? 'Close chat' : triggerLabel}\n aria-expanded={isOpen}\n className={twMerge(\n 'fixed z-50 flex items-center justify-center w-14 h-14 rounded-full',\n 'bg-brand-blue text-brand-cream shadow-glow-cyan',\n 'hover:bg-brand-cyan hover:shadow-glow-cyan hover:scale-105',\n 'active:scale-95',\n 'transition-all duration-200',\n positionClasses,\n )}\n >\n {isOpen ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n )}\n </button>\n </div>\n )\n}\n\nexport { AgentWidget }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\n\nexport type AgentEmbedProps = {\n endpoint: string\n title?: string\n className?: string\n}\n\nfunction AgentEmbed({\n endpoint,\n title = 'Chat',\n className,\n}: AgentEmbedProps) {\n return (\n <div\n className={twMerge('w-full h-full min-h-0', className)}\n data-testid=\"agent-embed\"\n >\n <AgentChat\n endpoint={endpoint}\n title={title}\n className=\"h-full rounded-none border-0\"\n />\n </div>\n )\n}\n\nexport { AgentEmbed }\n"],"mappings":"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","names":["twMerge","useState","useCallback","twMerge","twMerge","useCallback","useRef","twMerge","Badge","content","jsx","twMerge","jsx","jsxs","jsx","jsxs","twMerge","jsx","jsx","jsxs","getConfidenceIntent","Badge","jsx","jsxs","twMerge","jsx","jsxs","useRef","useCallback","twMerge","twMerge","useState","useRef","useCallback","jsx","jsxs","DocumentIcon","jsxs","jsx","DocumentIcon","twMerge","useState","useRef","useCallback","twMerge","jsx","jsxs","useEffect","useRef","twMerge","useState","useRef","useEffect","jsx","jsxs","useRef","useEffect","twMerge","jsx","jsxs","twMerge","twMerge","jsx","jsxs","jsx","jsxs","useState","useCallback","twMerge","twMerge","useRef","useEffect","jsx","jsxs","useRef","useEffect","twMerge","twMerge","useState","useCallback","jsx","jsxs","useState","useCallback","twMerge","twMerge","jsx","twMerge"]}
1
+ {"version":3,"sources":["../../src/layouts/AgentFullPage/AgentFullPage.tsx","../../src/chat/AgentChat/AgentChat.tsx","../../src/hooks/useAgentChat.ts","../../src/chat/MessageThread/MessageThread.tsx","../../src/chat/MessageBubble/MessageBubble.tsx","../../src/response/AgentResponse/AgentResponse.tsx","../../src/response/ResponseMessage/ResponseMessage.tsx","../../src/response/StructuredResponse/StructuredResponse.tsx","../../src/sources/SourceList/SourceList.tsx","../../src/sources/SourceCard/SourceCard.tsx","../../src/response/FollowUpChips/FollowUpChips.tsx","../../src/chat/MessageComposer/MessageComposer.tsx","../../src/chat/WelcomeScreen/WelcomeScreen.tsx","../../src/streaming/StreamingMessage/StreamingMessage.tsx","../../src/hooks/useCharacterDrain.ts","../../src/chat/ConversationList/ConversationList.tsx","../../src/layouts/AgentPanel/AgentPanel.tsx","../../src/layouts/AgentWidget/AgentWidget.tsx","../../src/layouts/AgentEmbed/AgentEmbed.tsx"],"sourcesContent":["'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useState, useCallback } from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\nimport { ConversationList } from '../../chat/ConversationList'\nimport type { ConversationSummary } from '../../types/chat'\n\nexport type AgentFullPageProps = {\n endpoint: string\n title?: string\n showConversationList?: boolean\n conversations?: ConversationSummary[]\n activeConversationId?: string\n onConversationSelect?: (id: string) => void\n onConversationDelete?: (id: string) => void\n onNewConversation?: () => void\n className?: string\n}\n\nfunction AgentFullPage({\n endpoint,\n title = 'Chat',\n showConversationList = false,\n conversations = [],\n activeConversationId,\n onConversationSelect,\n onConversationDelete,\n onNewConversation,\n className,\n}: AgentFullPageProps) {\n const [sidebarOpen, setSidebarOpen] = useState(false)\n\n const handleSelect = useCallback(\n (id: string) => {\n onConversationSelect?.(id)\n setSidebarOpen(false)\n },\n [onConversationSelect],\n )\n\n return (\n <div\n className={twMerge('flex h-screen w-full overflow-hidden bg-brand-dark', className)}\n data-testid=\"agent-full-page\"\n >\n {/* Sidebar */}\n {showConversationList && (\n <>\n {/* Mobile overlay */}\n {sidebarOpen && (\n <div\n className=\"fixed inset-0 bg-brand-dark/80 backdrop-blur-sm z-30 md:hidden\"\n onClick={() => setSidebarOpen(false)}\n data-testid=\"sidebar-overlay\"\n />\n )}\n\n {/* Sidebar panel */}\n <aside\n className={twMerge(\n 'bg-brand-dark border-r border-brand-gold/15 w-72 shrink-0 flex-col z-40',\n // Desktop: always visible\n 'hidden md:flex',\n // Mobile: overlay when open\n sidebarOpen && 'fixed inset-y-0 left-0 flex md:relative',\n )}\n aria-label=\"Conversations sidebar\"\n >\n <ConversationList\n conversations={conversations}\n activeId={activeConversationId}\n onSelect={handleSelect}\n onDelete={onConversationDelete}\n onNew={onNewConversation}\n />\n </aside>\n </>\n )}\n\n {/* Main chat area */}\n <div className=\"flex-1 flex flex-col min-w-0 bg-brand-dark\">\n {/* Mobile sidebar toggle */}\n {showConversationList && (\n <div className=\"md:hidden flex items-center border-b border-brand-gold/15 px-3 py-2 bg-brand-dark-panel/60 backdrop-blur-sm\">\n <button\n type=\"button\"\n onClick={() => setSidebarOpen(true)}\n aria-label=\"Open conversations sidebar\"\n className=\"p-2 rounded-xl text-brand-cream/60 hover:text-brand-cream hover:bg-brand-dark-panel transition-colors duration-200\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"3\" y1=\"12\" x2=\"21\" y2=\"12\" />\n <line x1=\"3\" y1=\"6\" x2=\"21\" y2=\"6\" />\n <line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\" />\n </svg>\n </button>\n </div>\n )}\n\n <AgentChat\n endpoint={endpoint}\n title={title}\n className=\"flex-1 rounded-none border-0\"\n />\n </div>\n </div>\n )\n}\n\nexport { AgentFullPage }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport { useAgentChat } from '../../hooks/useAgentChat'\nimport { MessageThread } from '../MessageThread'\nimport { MessageComposer } from '../MessageComposer'\nimport { WelcomeScreen } from '../WelcomeScreen'\nimport { StreamingMessage } from '../../streaming/StreamingMessage'\nimport type { ChatMessage } from '../../types/chat'\n\nexport type AgentChatProps = {\n endpoint: string\n title?: string\n welcomeTitle?: string\n welcomeMessage?: string\n suggestedQuestions?: string[]\n showHeader?: boolean\n showWelcomeTitle?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n enableFeedback?: boolean\n onMessage?: (message: ChatMessage) => void\n className?: string\n}\n\nfunction AgentChat({\n endpoint,\n title = 'Chat',\n welcomeTitle,\n welcomeMessage = 'How can I help you today?',\n suggestedQuestions = [],\n showHeader = true,\n showWelcomeTitle = true,\n showSources,\n showConfidence,\n showVerification,\n className,\n}: AgentChatProps) {\n const { state, actions } = useAgentChat({ apiUrl: endpoint })\n\n const hasMessages = state.messages.length > 0\n\n const handleSend = (content: string) => {\n void actions.sendMessage(content)\n }\n\n const handleQuestionSelect = (question: string) => {\n void actions.sendMessage(question)\n }\n\n return (\n <div\n className={twMerge(\n 'flex flex-col h-full bg-canvas border border-border rounded-xl overflow-hidden',\n className,\n )}\n >\n {showHeader && (\n <div className=\"flex items-center justify-between border-b border-border px-4 py-3 bg-surface-raised shrink-0\">\n <h1 className=\"text-base font-semibold text-text-primary\">{title}</h1>\n </div>\n )}\n\n {hasMessages ? (\n <MessageThread\n messages={state.messages}\n streamingSlot={\n state.isLoading ? (\n <StreamingMessage\n stream={{\n active: state.isLoading,\n phase: state.streamPhase,\n content: state.streamingContent,\n sources: [],\n agent: null,\n agentLabel: null,\n }}\n />\n ) : undefined\n }\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n />\n ) : (\n <WelcomeScreen\n title={showWelcomeTitle ? (welcomeTitle ?? title) : ''}\n message={welcomeMessage}\n suggestedQuestions={suggestedQuestions}\n onQuestionSelect={handleQuestionSelect}\n />\n )}\n\n <MessageComposer onSend={handleSend} onStop={actions.stop} isLoading={state.isLoading} />\n </div>\n )\n}\n\nexport { AgentChat }\n","'use client'\n\nimport { useReducer, useCallback, useRef } from 'react'\nimport type { ChatMessage, ChatError, Attachment } from '../types/chat'\nimport type { AgentResponse } from '../types/agent'\nimport type { StreamState } from '../types/streaming'\nimport type { AgentChatConfig } from '../types/config'\n\n// ── State ──────────────────────────────────────────────────────────────\n\nexport interface AgentChatState {\n messages: ChatMessage[]\n conversationId: string | null\n isLoading: boolean\n error: ChatError | null\n inputValue: string\n streamPhase: StreamState['phase']\n streamingContent: string\n streamingAgent: string | null\n}\n\nconst initialState: AgentChatState = {\n messages: [],\n conversationId: null,\n isLoading: false,\n error: null,\n inputValue: '',\n streamPhase: 'idle',\n streamingContent: '',\n streamingAgent: null,\n}\n\n// ── Actions ────────────────────────────────────────────────────────────\n\ntype Action =\n | { type: 'SET_INPUT'; value: string }\n | { type: 'SEND_START'; message: ChatMessage }\n | { type: 'STREAM_PHASE'; phase: StreamState['phase'] }\n | { type: 'STREAM_CONTENT'; content: string }\n | { type: 'STREAM_CONTENT_RESET' }\n | { type: 'STREAM_AGENT'; agent: string }\n | { type: 'SEND_SUCCESS'; message: ChatMessage; streamingContent: string; conversationId: string | null }\n | { type: 'SEND_ERROR'; error: ChatError }\n | { type: 'LOAD_CONVERSATION'; conversationId: string; messages: ChatMessage[] }\n | { type: 'RESET' }\n | { type: 'CLEAR_ERROR' }\n\nfunction reducer(state: AgentChatState, action: Action): AgentChatState {\n switch (action.type) {\n case 'SET_INPUT':\n return { ...state, inputValue: action.value }\n\n case 'SEND_START':\n return {\n ...state,\n messages: [...state.messages, action.message],\n isLoading: true,\n error: null,\n inputValue: '',\n streamPhase: 'thinking',\n streamingContent: '',\n streamingAgent: null,\n }\n\n case 'STREAM_PHASE':\n return { ...state, streamPhase: action.phase }\n\n case 'STREAM_CONTENT':\n return { ...state, streamingContent: state.streamingContent + action.content }\n\n case 'STREAM_CONTENT_RESET':\n return { ...state, streamingContent: '' }\n\n case 'STREAM_AGENT':\n return { ...state, streamingAgent: action.agent }\n\n case 'SEND_SUCCESS':\n return {\n ...state,\n messages: [...state.messages, action.message],\n conversationId: action.conversationId ?? state.conversationId,\n isLoading: false,\n streamPhase: 'idle',\n streamingContent: '',\n }\n\n case 'SEND_ERROR':\n return {\n ...state,\n isLoading: false,\n error: action.error,\n streamPhase: 'idle',\n streamingContent: '',\n streamingAgent: null,\n }\n\n case 'LOAD_CONVERSATION':\n return {\n ...state,\n conversationId: action.conversationId,\n messages: action.messages,\n error: null,\n }\n\n case 'RESET':\n return { ...initialState }\n\n case 'CLEAR_ERROR':\n return { ...state, error: null }\n\n default:\n return state\n }\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────\n\nlet msgIdCounter = 0\nfunction generateMessageId(): string {\n return `msg-${Date.now()}-${++msgIdCounter}`\n}\n\nexport interface AgentChatActions {\n sendMessage: (content: string, attachments?: Attachment[]) => Promise<void>\n setInputValue: (value: string) => void\n loadConversation: (conversationId: string, messages: ChatMessage[]) => void\n submitFeedback: (messageId: string, rating: 'positive' | 'negative', comment?: string) => Promise<void>\n retry: () => Promise<void>\n stop: () => void\n reset: () => void\n}\n\nexport function useAgentChat(config: AgentChatConfig) {\n const [state, dispatch] = useReducer(reducer, initialState)\n const configRef = useRef(config)\n configRef.current = config\n const lastUserMessageRef = useRef<string | null>(null)\n const lastUserAttachmentsRef = useRef<Attachment[] | undefined>(undefined)\n const abortControllerRef = useRef<AbortController | null>(null)\n\n const sendMessage = useCallback(\n async (content: string, attachments?: Attachment[]) => {\n const { apiUrl, streamPath = '/chat/stream', headers: headersOrFn, timeout = 30000, bodyExtra } = configRef.current\n const headers = typeof headersOrFn === 'function' ? await headersOrFn() : (headersOrFn ?? {})\n\n lastUserMessageRef.current = content\n lastUserAttachmentsRef.current = attachments\n\n const userMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'user',\n content,\n attachments,\n timestamp: new Date(),\n }\n\n dispatch({ type: 'SEND_START', message: userMessage })\n\n const controller = new AbortController()\n abortControllerRef.current = controller\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n // These variables are mutated inside handleEvent (called from async stream processing).\n // TypeScript can't track mutations through closures, so we use a mutable context object.\n // Defined outside try so the catch block can access accumulated content for user-initiated stop.\n const ctx = {\n accumulatedContent: '',\n agentResponse: null as AgentResponse | null,\n capturedAgent: null as string | null,\n capturedConversationId: null as string | null,\n hadStreamError: false,\n }\n\n try {\n const url = `${apiUrl}${streamPath}`\n const mergedHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n }\n\n // Build request body — include attachments if present\n const requestBody: Record<string, unknown> = {\n message: content,\n conversation_id: state.conversationId,\n ...bodyExtra,\n }\n if (attachments && attachments.length > 0) {\n requestBody.attachments = attachments.map(a => ({\n filename: a.filename,\n content_type: a.content_type,\n data: a.data,\n }))\n }\n const body = JSON.stringify(requestBody)\n\n // Shared handler for parsed SSE events (used by both adapter and default paths)\n const handleEvent = (event: { type: string; [key: string]: unknown }) => {\n switch (event.type) {\n case 'agent':\n ctx.capturedAgent = event.agent as string\n dispatch({ type: 'STREAM_AGENT', agent: ctx.capturedAgent })\n break\n case 'phase':\n dispatch({ type: 'STREAM_PHASE', phase: event.phase as StreamState['phase'] })\n break\n case 'delta':\n ctx.accumulatedContent += event.content\n dispatch({ type: 'STREAM_CONTENT', content: event.content as string })\n break\n case 'delta_reset':\n ctx.accumulatedContent = ''\n dispatch({ type: 'STREAM_CONTENT_RESET' })\n break\n case 'done':\n ctx.agentResponse = event.response as AgentResponse\n ctx.capturedConversationId = (event.conversation_id as string) ?? null\n break\n case 'error':\n ctx.hadStreamError = true\n dispatch({ type: 'SEND_ERROR', error: event.error as ChatError })\n break\n }\n }\n\n const { streamAdapter } = configRef.current\n\n if (streamAdapter) {\n // Use the custom stream adapter (e.g. React Native XHR-based SSE)\n await streamAdapter(\n url,\n { method: 'POST', headers: mergedHeaders, body, signal: controller.signal },\n handleEvent,\n )\n clearTimeout(timeoutId)\n } else {\n // Default path: fetch + ReadableStream getReader()\n const response = await fetch(url, {\n method: 'POST',\n headers: mergedHeaders,\n body,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'API_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n retryable: response.status >= 500,\n },\n })\n return\n }\n\n const reader = response.body?.getReader()\n if (!reader) {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'STREAM_ERROR', message: 'No response body', retryable: true },\n })\n return\n }\n\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const line of lines) {\n if (!line.startsWith('data: ')) continue\n const data = line.slice(6).trim()\n if (data === '[DONE]') continue\n\n try {\n const event = JSON.parse(data)\n handleEvent(event)\n } catch {\n // Skip malformed events\n }\n }\n }\n }\n\n // If an error event was dispatched during streaming, don't dispatch success\n if (ctx.hadStreamError) return\n\n const assistantMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: ctx.agentResponse?.message ?? ctx.accumulatedContent,\n response: ctx.agentResponse ?? undefined,\n agent: ctx.capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n\n dispatch({\n type: 'SEND_SUCCESS',\n message: assistantMessage,\n streamingContent: ctx.accumulatedContent,\n conversationId: ctx.capturedConversationId,\n })\n } catch (err: unknown) {\n clearTimeout(timeoutId)\n if ((err as Error).name === 'AbortError') {\n // User-initiated stop: commit whatever content we have so far\n if (ctx.accumulatedContent) {\n const partialMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: ctx.accumulatedContent,\n agent: ctx.capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n dispatch({\n type: 'SEND_SUCCESS',\n message: partialMessage,\n streamingContent: ctx.accumulatedContent,\n conversationId: ctx.capturedConversationId,\n })\n } else {\n dispatch({\n type: 'SEND_ERROR',\n error: { code: 'ABORTED', message: 'Request stopped', retryable: true },\n })\n }\n } else {\n dispatch({\n type: 'SEND_ERROR',\n error: {\n code: 'NETWORK_ERROR',\n message: (err as Error).message ?? 'Network error',\n retryable: true,\n },\n })\n }\n } finally {\n abortControllerRef.current = null\n }\n },\n [state.conversationId],\n )\n\n const setInputValue = useCallback((value: string) => {\n dispatch({ type: 'SET_INPUT', value })\n }, [])\n\n const loadConversation = useCallback((conversationId: string, messages: ChatMessage[]) => {\n dispatch({ type: 'LOAD_CONVERSATION', conversationId, messages })\n }, [])\n\n const submitFeedback = useCallback(\n async (messageId: string, rating: 'positive' | 'negative', comment?: string) => {\n const { apiUrl, feedbackPath = '/feedback', headers: headersOrFn } = configRef.current\n const headers = typeof headersOrFn === 'function' ? await headersOrFn() : (headersOrFn ?? {})\n await fetch(`${apiUrl}${feedbackPath}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...headers },\n body: JSON.stringify({ messageId, rating, comment }),\n })\n },\n [],\n )\n\n const retry = useCallback(async () => {\n if (lastUserMessageRef.current) {\n await sendMessage(lastUserMessageRef.current, lastUserAttachmentsRef.current)\n }\n }, [sendMessage])\n\n const stop = useCallback(() => {\n abortControllerRef.current?.abort()\n }, [])\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' })\n lastUserMessageRef.current = null\n lastUserAttachmentsRef.current = undefined\n }, [])\n\n const actions: AgentChatActions = {\n sendMessage,\n setInputValue,\n loadConversation,\n submitFeedback,\n retry,\n stop,\n reset,\n }\n\n return { state, actions }\n}\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport type { ChatMessage } from '../../types/chat'\nimport { MessageBubble } from '../MessageBubble'\n\nexport type MessageThreadProps = {\n messages: ChatMessage[]\n streamingSlot?: React.ReactNode\n showAgent?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n hideLastAssistant?: boolean\n userBubbleClassName?: string\n className?: string\n}\n\nfunction MessageThread({ messages, streamingSlot, showAgent, showSources, showConfidence, showVerification, hideLastAssistant, userBubbleClassName, className }: MessageThreadProps) {\n const scrollRef = useRef<HTMLDivElement>(null)\n const shouldAutoScroll = useRef(true)\n const hasStreaming = !!streamingSlot\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current\n if (el && shouldAutoScroll.current) {\n el.scrollTop = el.scrollHeight\n }\n }, [])\n\n // Detect user scroll-up intent via wheel events (never fired by programmatic scrolling)\n useEffect(() => {\n const el = scrollRef.current\n if (!el) return\n const onWheel = (e: WheelEvent) => {\n if (e.deltaY < 0) {\n shouldAutoScroll.current = false\n }\n }\n const onPointerDown = () => {\n // If the user interacts with the scroll area (e.g. scrollbar drag),\n // let handleScroll determine whether to pause auto-scroll\n // by marking this as a user-initiated interaction.\n el.dataset.userPointer = '1'\n }\n const onPointerUp = () => {\n delete el.dataset.userPointer\n }\n el.addEventListener('wheel', onWheel, { passive: true })\n el.addEventListener('pointerdown', onPointerDown)\n window.addEventListener('pointerup', onPointerUp)\n return () => {\n el.removeEventListener('wheel', onWheel)\n el.removeEventListener('pointerdown', onPointerDown)\n window.removeEventListener('pointerup', onPointerUp)\n }\n }, [])\n\n const handleScroll = useCallback(() => {\n const el = scrollRef.current\n if (!el) return\n const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 80\n if (nearBottom) {\n shouldAutoScroll.current = true\n } else if (el.dataset.userPointer) {\n // User is dragging scrollbar upward\n shouldAutoScroll.current = false\n }\n }, [])\n\n // Scroll on new messages\n useEffect(scrollToBottom, [messages.length, scrollToBottom])\n\n // Continuously follow streaming content growth\n useEffect(() => {\n if (!hasStreaming) return\n let raf: number\n const tick = () => {\n scrollToBottom()\n raf = requestAnimationFrame(tick)\n }\n raf = requestAnimationFrame(tick)\n return () => cancelAnimationFrame(raf)\n }, [hasStreaming, scrollToBottom])\n\n // Reset auto-scroll when streaming ends so the next message auto-scrolls\n useEffect(() => {\n if (!hasStreaming) {\n shouldAutoScroll.current = true\n }\n }, [hasStreaming])\n\n return (\n <div\n ref={scrollRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Message thread\"\n onScroll={handleScroll}\n className={twMerge(\n 'flex flex-col gap-4 overflow-y-auto flex-1 px-4 py-6',\n className,\n )}\n >\n <div className=\"flex-1 shrink-0\" />\n {messages.map((message, i) => {\n if (\n hideLastAssistant &&\n i === messages.length - 1 &&\n message.role === 'assistant'\n ) {\n return null\n }\n return (\n <MessageBubble\n key={message.id}\n message={message}\n showAgent={showAgent}\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n userBubbleClassName={userBubbleClassName}\n />\n )\n })}\n {streamingSlot}\n </div>\n )\n}\n\nexport { MessageThread }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport type { ChatMessage, Attachment } from '../../types/chat'\nimport { AgentResponse } from '../../response/AgentResponse'\nimport { ResponseMessage } from '../../response/ResponseMessage'\n\nfunction DocumentIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n </svg>\n )\n}\n\nfunction AttachmentThumbnail({ attachment }: { attachment: Attachment }) {\n const isImage = attachment.content_type.startsWith('image/')\n\n if (isImage) {\n return (\n <div className=\"rounded-lg overflow-hidden border border-black/10 max-w-[240px]\">\n <img\n src={attachment.preview_url ?? `data:${attachment.content_type};base64,${attachment.data}`}\n alt={attachment.filename}\n className=\"max-w-full max-h-[200px] object-contain\"\n />\n </div>\n )\n }\n\n return (\n <div className=\"flex items-center gap-2 px-3 py-2 rounded-lg border border-black/10 bg-black/5\">\n <DocumentIcon />\n <span className=\"text-xs truncate max-w-[160px]\">{attachment.filename}</span>\n </div>\n )\n}\n\nexport type MessageBubbleProps = {\n message: ChatMessage\n showAgent?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n animated?: boolean\n userBubbleClassName?: string\n className?: string\n}\n\nfunction MessageBubble({\n message,\n showAgent,\n showSources = true,\n showConfidence = true,\n showVerification = true,\n animated = true,\n userBubbleClassName,\n className,\n}: MessageBubbleProps) {\n const isUser = message.role === 'user'\n const hasAttachments = message.attachments && message.attachments.length > 0\n\n if (isUser) {\n return (\n <div\n data-message-id={message.id}\n className={twMerge('flex w-full justify-end', className)}\n >\n <div\n className={twMerge(\n 'max-w-[70%] rounded-[18px] rounded-br-[4px] px-4 py-2.5 bg-[#e8e8e8] text-[#1a1a1a] break-words whitespace-pre-wrap text-sm leading-relaxed',\n animated && 'motion-safe:animate-slideFromRight',\n userBubbleClassName,\n )}\n >\n {hasAttachments && (\n <div className=\"flex flex-wrap gap-2 mb-2\">\n {message.attachments!.map((att, i) => (\n <AttachmentThumbnail key={`${att.filename}-${i}`} attachment={att} />\n ))}\n </div>\n )}\n {message.content}\n </div>\n </div>\n )\n }\n\n return (\n <div\n data-message-id={message.id}\n className={twMerge('flex w-full flex-col items-start gap-1.5', className)}\n >\n {showAgent && message.agent && (\n <div className=\"text-[11px] font-display font-semibold uppercase tracking-[0.08em] text-text-muted px-1\">\n {message.agent.replace('_agent', '').replace('_', ' ')}\n </div>\n )}\n <div\n className={twMerge(\n 'max-w-[88%] rounded-[18px] rounded-tl-[4px] px-4 py-3 bg-surface border border-border',\n animated && 'motion-safe:animate-springFromLeft',\n )}\n >\n {message.response ? (\n <AgentResponse\n response={message.response}\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n />\n ) : (\n <ResponseMessage content={message.content} />\n )}\n </div>\n </div>\n )\n}\n\nexport { MessageBubble }\n","import React from 'react'\nimport { Badge } from '@surf-kit/core'\nimport type { AgentResponse as AgentResponseType } from '../../types/agent'\nimport { ResponseMessage } from '../ResponseMessage'\nimport { StructuredResponse } from '../StructuredResponse'\nimport { SourceList } from '../../sources/SourceList'\nimport { FollowUpChips } from '../FollowUpChips'\n\ntype AgentResponseProps = {\n response: AgentResponseType\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n onFollowUp?: (suggestion: string) => void\n onNavigateSource?: (source: AgentResponseType['sources'][number]) => void\n className?: string\n}\n\nfunction getConfidenceIntent(overall: 'high' | 'medium' | 'low') {\n if (overall === 'high') return 'success' as const\n if (overall === 'medium') return 'warning' as const\n return 'error' as const\n}\n\nfunction getVerificationIntent(status: 'passed' | 'flagged' | 'failed') {\n if (status === 'passed') return 'success' as const\n if (status === 'flagged') return 'warning' as const\n return 'error' as const\n}\n\nfunction getVerificationLabel(status: 'passed' | 'flagged' | 'failed') {\n if (status === 'passed') return 'Verified'\n if (status === 'flagged') return 'Flagged'\n return 'Failed'\n}\n\nfunction AgentResponse({\n response,\n showSources = true,\n showConfidence = false,\n showVerification = false,\n onFollowUp,\n onNavigateSource,\n className,\n}: AgentResponseProps) {\n return (\n <div className={`flex flex-col gap-4 ${className ?? ''}`} data-testid=\"agent-response\">\n {/* Lead message — always shown as a short 1-3 sentence summary */}\n <ResponseMessage content={response.message} />\n\n {/* Structured content — rendered when ui_hint is not plain text */}\n {response.ui_hint !== 'text' && response.structured_data && (() => {\n const parsed = typeof response.structured_data === 'string'\n ? (() => { try { return JSON.parse(response.structured_data) as Record<string, unknown> } catch { return null } })()\n : response.structured_data as Record<string, unknown>\n return parsed ? <StructuredResponse uiHint={response.ui_hint} data={parsed} /> : null\n })()}\n\n {/* Confidence & Verification badges */}\n {(showConfidence || showVerification) && (\n <div className=\"flex flex-wrap items-center gap-2 mt-1\" data-testid=\"response-meta\">\n {showConfidence && (\n <Badge\n intent={getConfidenceIntent(response.confidence.overall)}\n size=\"sm\"\n >\n {response.confidence.overall} confidence\n </Badge>\n )}\n {showVerification && (\n <Badge\n intent={getVerificationIntent(response.verification.status)}\n size=\"sm\"\n >\n {getVerificationLabel(response.verification.status)} ({response.verification.claims_verified}/{response.verification.claims_checked})\n </Badge>\n )}\n </div>\n )}\n\n {/* Sources */}\n {showSources && response.sources.length > 0 && (\n <SourceList\n sources={response.sources}\n variant=\"compact\"\n collapsible\n defaultExpanded={false}\n onNavigate={onNavigateSource}\n />\n )}\n\n {/* Follow-up suggestions */}\n {response.follow_up_suggestions.length > 0 && onFollowUp && (\n <FollowUpChips\n suggestions={response.follow_up_suggestions}\n onSelect={onFollowUp}\n />\n )}\n </div>\n )\n}\n\nexport { AgentResponse }\nexport type { AgentResponseProps }\n","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeSanitize from 'rehype-sanitize'\nimport remarkGfm from 'remark-gfm'\nimport { twMerge } from 'tailwind-merge'\n\ntype ResponseMessageProps = {\n content: string\n className?: string\n}\n\nfunction normalizeMarkdownLists(content: string) {\n // Some providers emit compact list markdown like \"Intro: - item 1 - item 2\".\n // Insert a paragraph break before an inline list marker so markdown parses it as a list.\n return content.replace(/:\\s+-\\s+/g, ':\\n\\n- ')\n}\n\nfunction ResponseMessage({ content, className }: ResponseMessageProps) {\n return (\n <div\n className={twMerge(\n 'text-sm leading-relaxed text-text-primary',\n '[&_p]:my-2',\n '[&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-6',\n '[&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-6',\n '[&_li]:my-1',\n '[&_strong]:text-text-primary [&_strong]:font-semibold',\n '[&_em]:text-text-secondary',\n '[&_h1]:text-lg [&_h1]:font-semibold [&_h1]:text-text-primary [&_h1]:mt-4 [&_h1]:mb-2',\n '[&_h2]:text-base [&_h2]:font-semibold [&_h2]:text-text-primary [&_h2]:mt-3 [&_h2]:mb-1.5',\n '[&_h3]:text-sm [&_h3]:font-semibold [&_h3]:text-accent [&_h3]:mt-2 [&_h3]:mb-1',\n '[&_code]:bg-surface-raised [&_code]:text-accent [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono',\n '[&_pre]:bg-surface-raised [&_pre]:border [&_pre]:border-border [&_pre]:rounded-xl [&_pre]:p-4 [&_pre]:overflow-x-auto',\n '[&_hr]:my-3 [&_hr]:border-border',\n '[&_blockquote]:border-l-2 [&_blockquote]:border-border-strong [&_blockquote]:pl-4 [&_blockquote]:text-text-secondary',\n '[&_table]:w-full [&_table]:text-sm [&_table]:border-collapse [&_table]:my-2',\n '[&_thead]:border-b [&_thead]:border-border',\n '[&_th]:text-left [&_th]:px-2 [&_th]:py-1.5 [&_th]:font-semibold',\n '[&_td]:px-2 [&_td]:py-1.5 [&_td]:border-t [&_td]:border-border/50',\n '[&_a]:text-accent [&_a]:underline-offset-2 [&_a]:hover:text-accent/80',\n className,\n )}\n data-testid=\"response-message\"\n >\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[rehypeSanitize]}\n components={{\n script: () => null,\n iframe: () => null,\n p: ({ children }) => <p className=\"my-2\">{children}</p>,\n ul: ({ children }) => <ul className=\"my-2 list-disc pl-6\">{children}</ul>,\n ol: ({ children }) => <ol className=\"my-2 list-decimal pl-6\">{children}</ol>,\n li: ({ children, ...props }) => {\n let content = children\n // Strip leading \"N.\" or \"N)\" text that duplicates the ol counter\n if ((props as Record<string, unknown>).ordered) {\n content = React.Children.map(children, (child, i) => {\n if (i === 0 && typeof child === 'string') {\n return child.replace(/^\\d+[.)]\\s*/, '')\n }\n return child\n })\n }\n return <li className=\"my-1\">{content}</li>\n },\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n em: ({ children }) => <em className=\"italic text-text-secondary\">{children}</em>,\n h1: ({ children }) => <h1 className=\"text-base font-bold mt-4 mb-2\">{children}</h1>,\n h2: ({ children }) => <h2 className=\"text-sm font-bold mt-3 mb-1\">{children}</h2>,\n h3: ({ children }) => <h3 className=\"text-sm font-semibold mt-2 mb-1\">{children}</h3>,\n hr: () => <hr className=\"my-3 border-border\" />,\n code: ({ children }) => <code className=\"bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono\">{children}</code>,\n table: ({ children }) => (\n <div className=\"overflow-x-auto my-2\">\n <table className=\"w-full text-sm border-collapse\">{children}</table>\n </div>\n ),\n thead: ({ children }) => <thead className=\"border-b border-border\">{children}</thead>,\n th: ({ children }) => <th className=\"text-left px-2 py-1.5 font-semibold\">{children}</th>,\n td: ({ children }) => <td className=\"px-2 py-1.5 border-t border-border/50\">{children}</td>,\n }}\n >\n {normalizeMarkdownLists(content)}\n </ReactMarkdown>\n </div>\n )\n}\n\nexport { ResponseMessage }\nexport type { ResponseMessageProps }\n","import React from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport rehypeSanitize from 'rehype-sanitize'\nimport type { AgentResponse } from '../../types/agent'\n\ntype StructuredResponseProps = {\n uiHint: AgentResponse['ui_hint']\n data: Record<string, unknown> | null\n className?: string\n}\n\n/** Parse a value that may be a JSON-encoded string or already parsed. */\nfunction tryParse<T>(value: unknown): T | null {\n if (value === undefined || value === null) return null\n if (typeof value === 'string') {\n try {\n return JSON.parse(value) as T\n } catch {\n return null\n }\n }\n return value as T\n}\n\n/** Renders a string with inline markdown (bold, italic, links, code). */\nfunction InlineMarkdown({ text }: { text: string }) {\n return (\n <ReactMarkdown\n rehypePlugins={[rehypeSanitize]}\n components={{\n // Unwrap block-level <p> so content stays inline within its parent\n p: ({ children }) => <>{children}</>,\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\n em: ({ children }) => <em className=\"italic\">{children}</em>,\n code: ({ children }) => <code className=\"bg-surface-sunken rounded px-1 py-0.5 text-xs font-mono\">{children}</code>,\n // Prevent block elements that would break layout\n script: () => null,\n iframe: () => null,\n }}\n >\n {text}\n </ReactMarkdown>\n )\n}\n\nfunction renderSteps(data: Record<string, unknown>) {\n const steps = tryParse<string[]>(data.steps)\n if (!steps || !Array.isArray(steps)) return null\n return (\n <ol className=\"flex flex-col gap-2\" data-testid=\"structured-steps\">\n {steps.map((step, i) => (\n <li key={i} className=\"flex items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-accent text-[11px] font-semibold text-white\"\n aria-hidden=\"true\"\n >\n {i + 1}\n </span>\n <span className=\"text-sm text-text-primary leading-relaxed\">\n <InlineMarkdown text={step} />\n </span>\n </li>\n ))}\n </ol>\n )\n}\n\nfunction renderTable(data: Record<string, unknown>) {\n const columns = tryParse<string[]>(data.columns)\n // rows may be array-of-arrays or array-of-objects; normalise to array-of-arrays\n const rawRows = tryParse<unknown[]>(data.rows)\n\n if (columns && rawRows && Array.isArray(columns) && Array.isArray(rawRows)) {\n return (\n <div className=\"overflow-x-auto rounded-lg border border-border\" data-testid=\"structured-table\">\n <table role=\"table\" className=\"w-full border-collapse text-sm\">\n <thead className=\"bg-surface-raised\">\n <tr>\n {columns.map((col) => (\n <th\n key={col}\n className=\"text-left px-4 py-2.5 font-semibold text-text-primary border-b border-border\"\n >\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rawRows.map((row, i) => {\n const cells = Array.isArray(row)\n ? row\n : columns.map((col) => (row as Record<string, unknown>)[col])\n return (\n <tr key={i} className=\"even:bg-surface-raised/40\">\n {cells.map((cell, j) => (\n <td key={j} className=\"px-4 py-2 text-text-secondary border-b border-border\">\n {String(cell ?? '')}\n </td>\n ))}\n </tr>\n )\n })}\n </tbody>\n </table>\n </div>\n )\n }\n\n // Fallback: key-value table\n const entries = Object.entries(data)\n return (\n <div className=\"overflow-x-auto rounded-lg border border-border\" data-testid=\"structured-table\">\n <table role=\"table\" className=\"w-full border-collapse text-sm\">\n <tbody>\n {entries.map(([key, value]) => (\n <tr key={key} className=\"even:bg-surface-raised/40\">\n <td className=\"px-4 py-2 text-text-primary font-medium border-b border-border w-1/3\">\n {key}\n </td>\n <td className=\"px-4 py-2 text-text-secondary border-b border-border\">\n {typeof value === 'object' ? JSON.stringify(value) : String(value ?? '')}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )\n}\n\nfunction renderCard(data: Record<string, unknown>) {\n const title = typeof data.title === 'string' ? data.title : null\n const body = typeof data.body === 'string' ? data.body : null\n const link = typeof data.link === 'string' ? data.link : null\n const linkLabel = typeof data.link_label === 'string' ? data.link_label : 'Learn more'\n\n return (\n <div\n className=\"rounded-xl border border-border bg-surface-raised p-4 flex flex-col gap-2\"\n data-testid=\"structured-card\"\n >\n {title && <p className=\"text-sm font-semibold text-text-primary\">{title}</p>}\n {body && <p className=\"text-sm text-text-secondary leading-relaxed\">{body}</p>}\n {link && (\n <a\n href={link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-1 inline-flex items-center gap-1 text-xs font-medium text-accent hover:text-accent/80 underline-offset-2 hover:underline transition-colors\"\n >\n {linkLabel}\n <svg className=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\" />\n </svg>\n </a>\n )}\n </div>\n )\n}\n\nfunction renderList(data: Record<string, unknown>) {\n const items = tryParse<string[]>(data.items)\n const title = typeof data.title === 'string' ? data.title : null\n if (!items || !Array.isArray(items)) return null\n\n return (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"structured-list\">\n {title && (\n <p className=\"text-xs font-semibold uppercase tracking-wider text-text-secondary mb-1\">{title}</p>\n )}\n <ul className=\"flex flex-col gap-1.5\">\n {items.map((item, i) => (\n <li key={i} className=\"flex items-start gap-2.5\">\n <span className=\"mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-accent\" aria-hidden=\"true\" />\n <span className=\"text-sm text-text-primary leading-relaxed\">\n <InlineMarkdown text={item} />\n </span>\n </li>\n ))}\n </ul>\n </div>\n )\n}\n\nfunction renderWarning(data: Record<string, unknown>) {\n const severity = typeof data.severity === 'string' ? data.severity : 'medium'\n const action = typeof data.action === 'string' ? data.action : null\n const details = typeof data.details === 'string' ? data.details : null\n const isHigh = severity === 'high'\n\n return (\n <div\n role=\"alert\"\n className={`rounded-xl border p-4 flex gap-3 ${\n isHigh\n ? 'border-red-200 bg-red-50 dark:border-red-900/50 dark:bg-red-950/30'\n : 'border-amber-200 bg-amber-50 dark:border-amber-900/50 dark:bg-amber-950/30'\n }`}\n data-testid=\"structured-warning\"\n >\n <svg\n className={`mt-0.5 h-5 w-5 shrink-0 ${isHigh ? 'text-red-500' : 'text-amber-500'}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\" />\n </svg>\n <div className=\"flex flex-col gap-1\">\n {action && (\n <p className={`text-sm font-semibold ${isHigh ? 'text-red-700 dark:text-red-300' : 'text-amber-700 dark:text-amber-300'}`}>\n {action}\n </p>\n )}\n {details && (\n <p className={`text-sm ${isHigh ? 'text-red-600 dark:text-red-400' : 'text-amber-600 dark:text-amber-400'}`}>\n {details}\n </p>\n )}\n </div>\n </div>\n )\n}\n\nfunction StructuredResponse({ uiHint, data: rawData, className }: StructuredResponseProps) {\n // Defensive: data may arrive as a JSON string from the API instead of a parsed object.\n const data = typeof rawData === 'string'\n ? (() => { try { return JSON.parse(rawData) as Record<string, unknown> } catch { return null } })()\n : rawData\n if (!data) return null\n\n let content: React.ReactNode\n\n switch (uiHint) {\n case 'steps':\n content = renderSteps(data)\n break\n case 'table':\n content = renderTable(data)\n break\n case 'card':\n content = renderCard(data)\n break\n case 'list':\n content = renderList(data)\n break\n case 'warning':\n content = renderWarning(data)\n break\n case 'text':\n content = typeof data.text === 'string'\n ? <p data-testid=\"structured-text\">{data.text}</p>\n : null\n break\n default:\n content = null\n }\n\n if (!content) return null\n\n return (\n <div className={className} data-testid=\"structured-response\">\n {content}\n </div>\n )\n}\n\nexport { StructuredResponse }\nexport type { StructuredResponseProps }\n","'use client'\n\nimport React, { useState } from 'react'\nimport type { Source } from '../../types/agent'\nimport { SourceCard } from '../SourceCard'\n\ntype SourceListProps = {\n sources: Source[]\n variant?: 'compact' | 'expanded'\n collapsible?: boolean\n defaultExpanded?: boolean\n onNavigate?: (source: Source) => void\n className?: string\n}\n\nfunction SourceList({\n sources,\n variant = 'compact',\n collapsible = false,\n defaultExpanded = true,\n onNavigate,\n className,\n}: SourceListProps) {\n const [isExpanded, setIsExpanded] = useState(defaultExpanded)\n\n if (sources.length === 0) return null\n\n const content = (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"source-list-items\">\n {sources.map((source) => (\n <SourceCard\n key={source.document_id}\n source={source}\n variant={variant}\n onNavigate={onNavigate}\n />\n ))}\n </div>\n )\n\n if (!collapsible) {\n return (\n <div className={className} data-testid=\"source-list\">\n {content}\n </div>\n )\n }\n\n return (\n <div className={className} data-testid=\"source-list\">\n <button\n type=\"button\"\n onClick={() => setIsExpanded(prev => !prev)}\n aria-expanded={isExpanded}\n className=\"flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wider text-text-secondary hover:text-accent mb-2 transition-colors duration-200\"\n >\n <svg\n className={`w-4 h-4 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n Sources ({sources.length})\n </button>\n {isExpanded && content}\n </div>\n )\n}\n\nexport { SourceList }\nexport type { SourceListProps }\n","import React from 'react'\nimport { Badge } from '@surf-kit/core'\nimport { twMerge } from 'tailwind-merge'\nimport type { Source } from '../../types/agent'\n\ntype SourceCardProps = {\n source: Source\n variant?: 'compact' | 'expanded'\n onNavigate?: (source: Source) => void\n className?: string\n}\n\nfunction getConfidenceIntent(confidence: number) {\n if (confidence >= 0.8) return 'success' as const\n if (confidence >= 0.5) return 'warning' as const\n return 'error' as const\n}\n\nfunction getConfidenceLabel(confidence: number) {\n if (confidence >= 0.8) return 'High'\n if (confidence >= 0.5) return 'Medium'\n return 'Low'\n}\n\nfunction SourceCard({ source, variant = 'compact', onNavigate, className }: SourceCardProps) {\n const handleClick = () => {\n if (onNavigate) {\n onNavigate(source)\n }\n }\n\n const isCompact = variant === 'compact'\n\n return (\n <div\n className={twMerge(\n 'rounded-xl border transition-all duration-200',\n 'bg-surface border-border',\n onNavigate && 'cursor-pointer hover:border-border-strong',\n className,\n )}\n data-document-id={source.document_id}\n data-testid=\"source-card\"\n >\n <div\n className={isCompact ? 'px-4 py-3' : 'px-6 py-4'}\n onClick={handleClick}\n role={onNavigate ? 'button' : undefined}\n tabIndex={onNavigate ? 0 : undefined}\n onKeyDown={\n onNavigate\n ? (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick()\n }\n }\n : undefined\n }\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex-1 min-w-0\">\n {source.url ? (\n <a\n href={source.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm font-medium text-accent hover:underline truncate block\"\n onClick={(e) => e.stopPropagation()}\n >\n {source.title}\n <svg\n className=\"inline-block ml-1 w-3 h-3 opacity-60\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n </a>\n ) : (\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {source.title}\n </p>\n )}\n {source.section && (\n <p className=\"text-[11px] font-semibold uppercase tracking-wider text-text-secondary truncate mt-0.5\">\n {source.section}\n </p>\n )}\n </div>\n <Badge\n intent={getConfidenceIntent(source.confidence)}\n size=\"sm\"\n >\n {getConfidenceLabel(source.confidence)}\n </Badge>\n </div>\n {!isCompact && (\n <p className=\"text-xs text-text-secondary mt-2 line-clamp-3 leading-relaxed\">\n {source.snippet}\n </p>\n )}\n </div>\n </div>\n )\n}\n\nexport { SourceCard }\nexport type { SourceCardProps }\n","import React from 'react'\nimport { twMerge } from 'tailwind-merge'\n\ntype FollowUpChipsProps = {\n suggestions: string[]\n onSelect: (suggestion: string) => void\n className?: string\n}\n\nfunction FollowUpChips({ suggestions, onSelect, className }: FollowUpChipsProps) {\n if (suggestions.length === 0) return null\n\n return (\n <div\n className={twMerge('flex flex-wrap gap-2 py-1', className)}\n role=\"group\"\n aria-label=\"Follow-up suggestions\"\n data-testid=\"follow-up-chips\"\n >\n {suggestions.map(suggestion => (\n <button\n key={suggestion}\n type=\"button\"\n onClick={() => onSelect(suggestion)}\n className={twMerge(\n 'px-4 py-1.5 rounded-full text-sm whitespace-nowrap',\n 'border border-border bg-transparent text-text-secondary',\n 'hover:bg-accent/10 hover:border-interactive hover:text-text-primary',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'transition-all duration-200',\n )}\n >\n {suggestion}\n </button>\n ))}\n </div>\n )\n}\n\nexport { FollowUpChips }\nexport type { FollowUpChipsProps }\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useState, useRef, useCallback } from 'react'\nimport type { Attachment } from '../../types/chat'\n\nconst ALLOWED_TYPES = new Set([\n 'image/png',\n 'image/jpeg',\n 'image/gif',\n 'image/webp',\n 'application/pdf',\n])\nconst MAX_FILE_SIZE = 10 * 1024 * 1024 // 10 MB\nconst MAX_ATTACHMENTS = 5\n\nexport type MessageComposerProps = {\n onSend: (content: string, attachments?: Attachment[]) => void\n onStop?: () => void\n isLoading?: boolean\n placeholder?: string\n className?: string\n}\n\nfunction ArrowUpIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10 16V4\" />\n <path d=\"M4 10l6-6 6 6\" />\n </svg>\n )\n}\n\nfunction StopIcon() {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"currentColor\">\n <rect x=\"3\" y=\"3\" width=\"10\" height=\"10\" rx=\"2\" />\n </svg>\n )\n}\n\nfunction PaperclipIcon() {\n return (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48\" />\n </svg>\n )\n}\n\nfunction XIcon({ size = 14 }: { size?: number }) {\n return (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M18 6L6 18\" />\n <path d=\"M6 6l12 12\" />\n </svg>\n )\n}\n\nfunction DocumentIcon() {\n return (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\" />\n <polyline points=\"14 2 14 8 20 8\" />\n <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\" />\n <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\" />\n <polyline points=\"10 9 9 9 8 9\" />\n </svg>\n )\n}\n\nfunction fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n const result = reader.result as string\n // Strip data URL prefix (e.g. \"data:image/png;base64,\")\n const base64 = result.split(',')[1]\n resolve(base64)\n }\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n}\n\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction AttachmentPreview({\n attachment,\n onRemove,\n}: {\n attachment: Attachment\n onRemove: () => void\n}) {\n const isImage = attachment.content_type.startsWith('image/')\n\n return (\n <div className=\"relative group flex-shrink-0\">\n {isImage ? (\n <div className=\"w-16 h-16 rounded-lg overflow-hidden border border-border/60 bg-surface-alt\">\n <img\n src={attachment.preview_url ?? `data:${attachment.content_type};base64,${attachment.data}`}\n alt={attachment.filename}\n className=\"w-full h-full object-cover\"\n />\n </div>\n ) : (\n <div className=\"h-16 px-3 rounded-lg border border-border/60 bg-surface-alt flex items-center gap-2\">\n <div className=\"text-text-muted\">\n <DocumentIcon />\n </div>\n <div className=\"flex flex-col min-w-0\">\n <span className=\"text-xs text-text-primary truncate max-w-[120px]\">\n {attachment.filename}\n </span>\n <span className=\"text-[10px] text-text-muted\">PDF</span>\n </div>\n </div>\n )}\n <button\n type=\"button\"\n onClick={onRemove}\n className={twMerge(\n 'absolute -top-1.5 -right-1.5',\n 'w-5 h-5 rounded-full',\n 'bg-text-muted/80 text-white',\n 'flex items-center justify-center',\n 'opacity-0 group-hover:opacity-100',\n 'transition-opacity duration-150',\n 'hover:bg-text-primary',\n )}\n aria-label={`Remove ${attachment.filename}`}\n >\n <XIcon size={10} />\n </button>\n </div>\n )\n}\n\nfunction MessageComposer({\n onSend,\n onStop,\n isLoading = false,\n placeholder = 'Type a message...',\n className,\n}: MessageComposerProps) {\n const [value, setValue] = useState('')\n const [attachments, setAttachments] = useState<Attachment[]>([])\n const [dragOver, setDragOver] = useState(false)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const fileInputRef = useRef<HTMLInputElement>(null)\n\n const canSend = (value.trim().length > 0 || attachments.length > 0) && !isLoading\n\n const resetHeight = useCallback(() => {\n const el = textareaRef.current\n if (el) {\n el.style.height = 'auto'\n el.style.overflowY = 'hidden'\n }\n }, [])\n\n const handleSend = useCallback(() => {\n if (!canSend) return\n const message = value.trim() || (attachments.length > 0 ? 'Please analyse the attached file(s).' : '')\n if (!message && attachments.length === 0) return\n onSend(message, attachments.length > 0 ? attachments : undefined)\n setValue('')\n setAttachments([])\n resetHeight()\n textareaRef.current?.focus()\n }, [canSend, onSend, value, attachments, resetHeight])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSend()\n }\n },\n [handleSend],\n )\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setValue(e.target.value)\n const el = e.target\n el.style.height = 'auto'\n const capped = Math.min(el.scrollHeight, 200)\n el.style.height = `${capped}px`\n el.style.overflowY = el.scrollHeight > 200 ? 'auto' : 'hidden'\n },\n [],\n )\n\n const addFiles = useCallback(async (files: FileList | File[]) => {\n const fileArray = Array.from(files)\n\n for (const file of fileArray) {\n if (attachments.length >= MAX_ATTACHMENTS) break\n if (!ALLOWED_TYPES.has(file.type)) continue\n if (file.size > MAX_FILE_SIZE) continue\n\n try {\n const data = await fileToBase64(file)\n const previewUrl = file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined\n const attachment: Attachment = {\n filename: file.name,\n content_type: file.type,\n data,\n preview_url: previewUrl,\n }\n setAttachments(prev => {\n if (prev.length >= MAX_ATTACHMENTS) return prev\n return [...prev, attachment]\n })\n } catch {\n // Skip files that can't be read\n }\n }\n }, [attachments.length])\n\n const handleFileSelect = useCallback(() => {\n fileInputRef.current?.click()\n }, [])\n\n const handleFileInputChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n if (e.target.files) {\n void addFiles(e.target.files)\n e.target.value = '' // reset so the same file can be selected again\n }\n },\n [addFiles],\n )\n\n const removeAttachment = useCallback((index: number) => {\n setAttachments(prev => {\n const removed = prev[index]\n if (removed?.preview_url) URL.revokeObjectURL(removed.preview_url)\n return prev.filter((_, i) => i !== index)\n })\n }, [])\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent) => {\n const items = e.clipboardData.items\n const files: File[] = []\n for (const item of items) {\n if (item.kind === 'file' && ALLOWED_TYPES.has(item.type)) {\n const file = item.getAsFile()\n if (file) files.push(file)\n }\n }\n if (files.length > 0) {\n void addFiles(files)\n }\n },\n [addFiles],\n )\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOver(true)\n }, [])\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOver(false)\n }, [])\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setDragOver(false)\n if (e.dataTransfer.files.length > 0) {\n void addFiles(e.dataTransfer.files)\n }\n },\n [addFiles],\n )\n\n return (\n <div\n className={twMerge(\n 'relative shrink-0 rounded-3xl border bg-surface',\n 'shadow-lg shadow-black/10',\n 'transition-all duration-200',\n 'focus-within:border-accent/40 focus-within:shadow-accent/5',\n dragOver ? 'border-accent/60 bg-accent/5' : 'border-border/60',\n className,\n )}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n accept=\"image/png,image/jpeg,image/gif,image/webp,application/pdf\"\n onChange={handleFileInputChange}\n className=\"hidden\"\n aria-hidden=\"true\"\n />\n\n {/* Attachment previews */}\n {attachments.length > 0 && (\n <div className=\"flex gap-2 px-4 pt-3 pb-1 overflow-x-auto\">\n {attachments.map((att, i) => (\n <AttachmentPreview\n key={`${att.filename}-${i}`}\n attachment={att}\n onRemove={() => removeAttachment(i)}\n />\n ))}\n </div>\n )}\n\n {/* Drag overlay */}\n {dragOver && (\n <div className=\"absolute inset-0 rounded-3xl flex items-center justify-center bg-accent/10 border-2 border-dashed border-accent/40 z-10 pointer-events-none\">\n <span className=\"text-sm font-display font-semibold text-accent\">Drop files here</span>\n </div>\n )}\n\n <div className=\"flex items-end\">\n {/* Attach button */}\n <button\n type=\"button\"\n onClick={handleFileSelect}\n disabled={isLoading || attachments.length >= MAX_ATTACHMENTS}\n aria-label=\"Attach file\"\n className={twMerge(\n 'flex-shrink-0 ml-2 mb-3',\n 'inline-flex items-center justify-center',\n 'w-9 h-9 rounded-full',\n 'transition-all duration-200',\n 'text-text-muted/60 hover:text-text-secondary hover:bg-text-muted/10',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:bg-transparent',\n )}\n >\n <PaperclipIcon />\n </button>\n\n <textarea\n ref={textareaRef}\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n rows={1}\n disabled={isLoading}\n className={twMerge(\n 'flex-1 resize-none bg-transparent',\n 'pl-2 pr-14 pt-4 pb-4 text-[15px] leading-relaxed',\n 'text-text-primary placeholder:text-text-muted/70',\n 'focus:outline-none',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n 'overflow-hidden',\n )}\n style={{ colorScheme: 'dark' }}\n aria-label=\"Message input\"\n />\n\n <button\n type=\"button\"\n onClick={isLoading && onStop ? onStop : handleSend}\n disabled={!canSend && !isLoading}\n aria-label={isLoading ? 'Stop generating' : 'Send message'}\n className={twMerge(\n 'absolute bottom-3 right-3',\n 'inline-flex items-center justify-center',\n 'w-9 h-9 rounded-full',\n 'transition-all duration-200',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n canSend\n ? 'bg-accent text-white hover:bg-accent-hover active:scale-90 shadow-md shadow-accent/25'\n : isLoading\n ? 'bg-text-muted/20 text-text-secondary hover:bg-text-muted/30 cursor-pointer'\n : 'bg-transparent text-text-muted/40 cursor-default',\n )}\n >\n {isLoading ? <StopIcon /> : <ArrowUpIcon />}\n </button>\n </div>\n </div>\n )\n}\n\nexport { MessageComposer }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\n\nexport type WelcomeScreenProps = {\n title?: string\n message?: React.ReactNode\n icon?: React.ReactNode\n iconClassName?: string\n suggestedQuestions?: string[]\n onQuestionSelect?: (question: string) => void\n className?: string\n}\n\nfunction WelcomeScreen({\n title = 'Welcome',\n message = 'How can I help you today?',\n icon,\n iconClassName,\n suggestedQuestions = [],\n onQuestionSelect,\n className,\n}: WelcomeScreenProps) {\n return (\n <div\n className={twMerge(\n 'flex flex-1 flex-col items-center justify-center gap-8 p-8 text-center motion-safe:animate-fadeUp',\n className,\n )}\n >\n {/* Icon */}\n {icon ? (\n iconClassName ? (\n <div className={iconClassName} aria-hidden=\"true\">\n {icon}\n </div>\n ) : (\n icon\n )\n ) : (\n <div\n className={twMerge(\n 'w-14 h-14 rounded-2xl bg-accent/10 border border-border flex items-center justify-center pulse-glow',\n iconClassName,\n )}\n aria-hidden=\"true\"\n >\n <span className=\"text-2xl\">✦</span>\n </div>\n )}\n\n {/* Text */}\n <div className=\"flex flex-col gap-2\">\n {title && (\n <h2 className=\"text-3xl font-bold text-text-primary\">{title}</h2>\n )}\n <p className=\"text-text-secondary text-base leading-relaxed max-w-md\">{message}</p>\n </div>\n\n {/* Suggested question chips */}\n {suggestedQuestions.length > 0 && (\n <div\n className=\"flex flex-wrap justify-center gap-2 max-w-xl\"\n role=\"group\"\n aria-label=\"Suggested questions\"\n >\n {suggestedQuestions.map(question => (\n <button\n key={question}\n type=\"button\"\n onClick={() => onQuestionSelect?.(question)}\n className={twMerge(\n 'px-3.5 py-1.5 rounded-full text-[12px]',\n 'border border-border bg-transparent text-text-secondary',\n 'hover:bg-accent/10 hover:border-interactive hover:text-text-primary',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n 'transition-colors duration-200',\n )}\n >\n {question}\n </button>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nexport { WelcomeScreen }\n","'use client'\n\nimport React, { useEffect, useRef } from 'react'\nimport { twMerge } from 'tailwind-merge'\nimport { WaveLoader } from '@surf-kit/core'\nimport type { StreamState } from '../../types/streaming'\nimport { useCharacterDrain } from '../../hooks/useCharacterDrain'\nimport { ResponseMessage } from '../../response/ResponseMessage'\n\ntype StreamingMessageProps = {\n stream: StreamState\n onComplete?: () => void\n onDraining?: (isDraining: boolean) => void\n showPhases?: boolean\n className?: string\n}\n\nconst phaseLabels: Record<StreamState['phase'], string> = {\n idle: '',\n waiting: 'Waiting...',\n thinking: 'Thinking...',\n retrieving: 'Searching...',\n generating: 'Writing...',\n verifying: 'Verifying...',\n}\n\n// Cursor styles: a catch-all targets any last-child element, with overrides\n// for ul/ol (target last li) and blockquote (target last p) so the cursor\n// appears inline with the final text rather than on a new line.\n// Uses steps(1) for a crisp blink that won't smooth-fade to invisible.\nconst CURSOR_STYLES = `\n.sk-streaming-cursor > :not(ul,ol,blockquote,div:has(table)):last-child::after,\n.sk-streaming-cursor > :is(ul,ol):last-child > li:last-child::after,\n.sk-streaming-cursor > blockquote:last-child > p:last-child::after,\n.sk-streaming-cursor > div:has(table):last-child table tbody tr:last-child td:last-child::after {\n content: \"\";\n display: inline-block;\n width: 2px;\n height: 1em;\n background: var(--color-accent, #38bdf8);\n animation: sk-cursor-blink 0.8s steps(1) infinite;\n margin-left: 2px;\n vertical-align: text-bottom;\n}\n@keyframes sk-cursor-blink {\n 0%, 60% { opacity: 1; }\n 61%, 100% { opacity: 0; }\n}\n`\n\nfunction StreamingMessage({\n stream,\n onComplete,\n onDraining,\n showPhases = true,\n className,\n}: StreamingMessageProps) {\n const onCompleteRef = useRef(onComplete)\n onCompleteRef.current = onComplete\n const onDrainingRef = useRef(onDraining)\n onDrainingRef.current = onDraining\n const wasActiveRef = useRef(stream.active)\n\n useEffect(() => {\n if (wasActiveRef.current && !stream.active) {\n onCompleteRef.current?.()\n }\n wasActiveRef.current = stream.active\n }, [stream.active])\n\n const phaseLabel = phaseLabels[stream.phase]\n const { displayed: rawDisplayed, isDraining } = useCharacterDrain(stream.content)\n // Trim trailing whitespace so ReactMarkdown doesn't create empty trailing\n // block elements that the cursor would land inside.\n const displayedContent = (stream.active || isDraining) ? rawDisplayed.trimEnd() : rawDisplayed\n\n // Notify parent of draining state changes\n useEffect(() => {\n onDrainingRef.current?.(isDraining)\n }, [isDraining])\n\n // Format agent label from stream.agent (e.g. \"coordinator_agent\" → \"coordinator\")\n const agentLabel = stream.agent\n ? stream.agent.replace('_agent', '').replace('_', ' ')\n : null\n\n // Show phase indicator only when there's no displayed content yet\n const showPhaseIndicator = showPhases && stream.active && stream.phase !== 'idle' && !displayedContent\n const showCursor = (stream.active || isDraining) && !!displayedContent\n\n return (\n <div className={twMerge('flex w-full flex-col items-start', className)} data-testid=\"streaming-message\">\n {/* Screen reader announcements */}\n <div aria-live=\"assertive\" className=\"sr-only\">\n {stream.active && stream.phase !== 'idle' && 'Response started'}\n {!stream.active && stream.content && 'Response complete'}\n </div>\n\n {showCursor && <style>{CURSOR_STYLES}</style>}\n\n {/* Agent label */}\n {agentLabel && (\n <div className=\"text-[11px] font-display font-semibold uppercase tracking-[0.08em] text-text-muted px-1 mb-1.5\">\n {agentLabel}\n </div>\n )}\n\n <div className=\"max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft\">\n {showPhaseIndicator && (\n <div\n className=\"flex items-center gap-2 text-sm text-text-secondary\"\n data-testid=\"phase-indicator\"\n >\n <span aria-hidden=\"true\">\n <WaveLoader size=\"sm\" color=\"#38bdf8\" />\n </span>\n <span>{phaseLabel}</span>\n </div>\n )}\n\n {displayedContent && (\n <ResponseMessage\n content={displayedContent}\n className={showCursor ? 'sk-streaming-cursor' : undefined}\n />\n )}\n </div>\n </div>\n )\n}\n\nexport { StreamingMessage }\nexport type { StreamingMessageProps }\n","'use client'\n\nimport { useState, useRef, useEffect } from 'react'\n\nexport interface CharacterDrainResult {\n displayed: string\n isDraining: boolean\n}\n\n/**\n * Smoothly drains a growing `target` string character-by-character using\n * `requestAnimationFrame`, decoupling visual rendering from network packet\n * timing so text appears to type out instead of arriving in chunks.\n *\n * When `target` resets to empty (e.g. stream finished), the hook continues\n * draining the previous content to completion before resetting, so the\n * typing animation isn't cut short.\n *\n * Design: the RAF loop is long-lived — it does NOT restart on every delta.\n * The tick function is stored in a ref (updated each render) so the loop\n * always reads the latest drainTarget without being cancelled/restarted.\n * A separate kick-start effect re-fires the loop when it was idle and new\n * content arrives.\n */\nexport function useCharacterDrain(target: string, msPerChar = 15): CharacterDrainResult {\n const [displayed, setDisplayed] = useState('')\n const indexRef = useRef(0)\n const lastTimeRef = useRef(0)\n const rafRef = useRef<number | null>(null)\n // Holds the last non-empty target so we can finish draining after source resets\n const drainTargetRef = useRef('')\n const msPerCharRef = useRef(msPerChar)\n\n msPerCharRef.current = msPerChar\n\n // Update drain target when new content arrives; preserve old value on reset\n if (target !== '') {\n drainTargetRef.current = target\n }\n\n const drainTarget = drainTargetRef.current\n const isDraining = displayed.length < drainTarget.length\n\n // Tick function stored in ref so the long-lived RAF loop always reads the\n // latest drainTarget and msPerChar without being cancelled/recreated.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const tickRef = useRef<(now: number) => void>(() => {})\n tickRef.current = (now: number) => {\n const currentTarget = drainTargetRef.current\n if (currentTarget === '') {\n rafRef.current = null\n return\n }\n\n if (lastTimeRef.current === 0) lastTimeRef.current = now\n const elapsed = now - lastTimeRef.current\n const charsToAdvance = Math.floor(elapsed / msPerCharRef.current)\n\n if (charsToAdvance > 0 && indexRef.current < currentTarget.length) {\n let nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length)\n // When the slice would end with whitespace, advance past it to include\n // the next visible character. This prevents trimEnd() in the streaming\n // UI from stripping trailing newlines and causing ReactMarkdown to\n // \"jump\" between block structures in a single frame (e.g. a heading\n // suddenly gaining a following paragraph with no transition).\n while (\n nextIndex < currentTarget.length &&\n currentTarget[nextIndex - 1].trim() === ''\n ) {\n nextIndex++\n }\n indexRef.current = nextIndex\n lastTimeRef.current = now\n setDisplayed(currentTarget.slice(0, nextIndex))\n }\n\n if (indexRef.current < currentTarget.length) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n } else {\n rafRef.current = null\n }\n }\n\n // Kick-start the RAF loop when new content arrives and the loop is idle.\n // No cleanup here — we intentionally do NOT cancel the running loop when\n // drainTarget grows; the long-lived tick will pick up new chars automatically.\n useEffect(() => {\n if (\n drainTargetRef.current !== '' &&\n indexRef.current < drainTargetRef.current.length &&\n rafRef.current === null\n ) {\n rafRef.current = requestAnimationFrame((t) => tickRef.current(t))\n }\n }, [drainTarget]) // drainTarget change = new content; check if loop needs kicking\n\n // Once drain completes and source stream is already done, reset all state\n useEffect(() => {\n if (target === '' && !isDraining && displayed !== '') {\n indexRef.current = 0\n lastTimeRef.current = 0\n drainTargetRef.current = ''\n setDisplayed('')\n }\n }, [target, isDraining, displayed])\n\n // Cancel any pending RAF on unmount\n useEffect(() => {\n return () => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n }\n }, [])\n\n return { displayed, isDraining }\n}\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport type { ConversationSummary } from '../../types/chat'\n\nexport type ConversationListProps = {\n conversations: ConversationSummary[]\n activeId?: string\n onSelect: (id: string) => void\n onDelete?: (id: string) => void\n onNew?: () => void\n className?: string\n}\n\nfunction ConversationList({\n conversations,\n activeId,\n onSelect,\n onDelete,\n onNew,\n className,\n}: ConversationListProps) {\n return (\n <nav\n aria-label=\"Conversation list\"\n className={twMerge('flex flex-col flex-1 min-h-0', className)}\n >\n {onNew && (\n <div className=\"px-5 pt-1 pb-3 border-b border-border\">\n <button\n type=\"button\"\n onClick={onNew}\n className=\"w-full px-4 py-2 rounded-lg text-sm font-medium border border-border text-text-secondary hover:text-text-primary hover:bg-surface hover:border-border-strong transition-colors duration-150\"\n >\n New conversation\n </button>\n </div>\n )}\n\n <ul role=\"list\" className=\"flex-1 overflow-y-auto\">\n {conversations.map((conversation) => {\n const isActive = conversation.id === activeId\n return (\n <li\n key={conversation.id}\n className={twMerge(\n 'flex items-start transition-colors duration-150',\n 'hover:bg-surface-raised',\n isActive\n ? 'bg-accent-subtlest border-l-[3px] border-l-accent'\n : 'border-l-[3px] border-l-transparent',\n )}\n >\n <button\n type=\"button\"\n onClick={() => onSelect(conversation.id)}\n aria-current={isActive ? 'true' : undefined}\n className=\"flex-1 min-w-0 text-left px-5 py-2.5\"\n >\n <div className=\"text-sm font-medium text-text-primary truncate\">\n {conversation.title}\n </div>\n <div className=\"text-xs text-text-muted truncate mt-0.5 leading-relaxed\">\n {conversation.lastMessage}\n </div>\n </button>\n {onDelete && (\n <button\n type=\"button\"\n onClick={() => onDelete(conversation.id)}\n aria-label={`Delete ${conversation.title}`}\n className=\"shrink-0 p-1.5 m-2 rounded-lg text-text-muted hover:text-status-error hover:bg-status-error/10 transition-colors duration-150\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n </button>\n )}\n </li>\n )\n })}\n\n {conversations.length === 0 && (\n <li className=\"px-5 py-12 text-center\">\n <span className=\"text-sm text-text-muted font-body\">No conversations yet</span>\n </li>\n )}\n </ul>\n </nav>\n )\n}\n\nexport { ConversationList }\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useRef, useEffect } from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\n\nexport type AgentPanelProps = {\n endpoint: string\n isOpen: boolean\n onClose: () => void\n side?: 'left' | 'right'\n width?: string | number\n title?: string\n className?: string\n}\n\nfunction AgentPanel({\n endpoint,\n isOpen,\n onClose,\n side = 'right',\n width = 400,\n title = 'Chat',\n className,\n}: AgentPanelProps) {\n const panelRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!isOpen) return\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose()\n }\n document.addEventListener('keydown', handleKeyDown)\n return () => document.removeEventListener('keydown', handleKeyDown)\n }, [isOpen, onClose])\n\n const widthStyle = typeof width === 'number' ? `${width}px` : width\n\n return (\n <div\n className={twMerge('fixed inset-0 z-50', !isOpen && 'pointer-events-none')}\n aria-hidden={!isOpen}\n >\n {/* Backdrop */}\n <div\n className={twMerge(\n 'fixed inset-0 transition-opacity duration-300',\n isOpen\n ? 'opacity-100 bg-brand-dark/70 backdrop-blur-sm pointer-events-auto'\n : 'opacity-0 pointer-events-none',\n )}\n onClick={isOpen ? onClose : undefined}\n data-testid=\"panel-backdrop\"\n />\n\n {/* Panel */}\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-label={title}\n aria-modal={isOpen ? 'true' : undefined}\n style={{ width: widthStyle, maxWidth: '100vw' }}\n className={twMerge(\n 'fixed top-0 h-full flex flex-col z-50 bg-brand-dark shadow-card',\n 'transition-transform duration-300 ease-in-out',\n side === 'left'\n ? `left-0 border-r border-brand-gold/15 ${isOpen ? 'translate-x-0' : '-translate-x-full'}`\n : `right-0 border-l border-brand-gold/15 ${isOpen ? 'translate-x-0' : 'translate-x-full'}`,\n className,\n )}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between border-b border-brand-gold/15 px-5 py-3.5 bg-brand-dark-panel/60 backdrop-blur-sm shrink-0\">\n <h2 className=\"text-base font-display font-semibold text-brand-cream\">{title}</h2>\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close panel\"\n className=\"rounded-xl p-2 text-brand-cream/40 hover:text-brand-cream/80 hover:bg-brand-cream/5 transition-colors duration-200\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n {/* Chat */}\n <AgentChat\n endpoint={endpoint}\n title={title}\n showHeader={false}\n showWelcomeTitle={false}\n className=\"flex-1 rounded-none border-0\"\n />\n </div>\n </div>\n )\n}\n\nexport { AgentPanel }\n","'use client'\n\nimport { twMerge } from 'tailwind-merge'\nimport React, { useState, useCallback } from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\n\nexport type AgentWidgetProps = {\n endpoint: string\n position?: 'bottom-right' | 'bottom-left'\n triggerLabel?: string\n title?: string\n className?: string\n}\n\nfunction AgentWidget({\n endpoint,\n position = 'bottom-right',\n triggerLabel = 'Chat',\n title = 'Chat',\n className,\n}: AgentWidgetProps) {\n const [isOpen, setIsOpen] = useState(false)\n\n const toggle = useCallback(() => {\n setIsOpen((prev) => !prev)\n }, [])\n\n const positionClasses = position === 'bottom-left' ? 'left-4 bottom-4' : 'right-4 bottom-4'\n const popoverPositionClasses = position === 'bottom-left' ? 'left-4 bottom-20' : 'right-4 bottom-20'\n const popoverOrigin = position === 'bottom-left' ? 'origin-bottom-left' : 'origin-bottom-right'\n\n return (\n <div className={className}>\n {/* Popover — always rendered, animated with CSS */}\n <div\n role=\"dialog\"\n aria-label={title}\n aria-hidden={!isOpen}\n className={twMerge(\n 'fixed z-50 flex flex-col',\n 'w-[min(400px,calc(100vw-2rem))] h-[min(600px,calc(100vh-6rem))]',\n 'rounded-2xl overflow-hidden border border-brand-gold/15',\n 'bg-brand-dark/95 backdrop-blur-[12px] shadow-card',\n popoverPositionClasses,\n popoverOrigin,\n 'transition-all duration-200 ease-out',\n isOpen\n ? 'opacity-100 scale-100 pointer-events-auto translate-y-0'\n : 'opacity-0 scale-95 pointer-events-none translate-y-2',\n )}\n >\n {/* Popover header */}\n <div className=\"flex items-center justify-between px-4 py-2.5 bg-brand-dark-panel/80 border-b border-brand-gold/15 shrink-0\">\n <h2 className=\"text-sm font-display font-semibold text-brand-cream\">{title}</h2>\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n aria-label=\"Minimize chat\"\n className=\"rounded-lg p-1.5 text-brand-cream/40 hover:text-brand-cream/70 transition-colors duration-200\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n\n <AgentChat\n endpoint={endpoint}\n title={title}\n showHeader={false}\n showWelcomeTitle={false}\n className=\"flex-1 rounded-none border-0 min-h-0\"\n />\n </div>\n\n {/* FAB — gold glow */}\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={isOpen ? 'Close chat' : triggerLabel}\n aria-expanded={isOpen}\n className={twMerge(\n 'fixed z-50 flex items-center justify-center w-14 h-14 rounded-full',\n 'bg-brand-blue text-brand-cream shadow-glow-cyan',\n 'hover:bg-brand-cyan hover:shadow-glow-cyan hover:scale-105',\n 'active:scale-95',\n 'transition-all duration-200',\n positionClasses,\n )}\n >\n {isOpen ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n )}\n </button>\n </div>\n )\n}\n\nexport { AgentWidget }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport { AgentChat } from '../../chat/AgentChat'\n\nexport type AgentEmbedProps = {\n endpoint: string\n title?: string\n className?: string\n}\n\nfunction AgentEmbed({\n endpoint,\n title = 'Chat',\n className,\n}: AgentEmbedProps) {\n return (\n <div\n className={twMerge('w-full h-full min-h-0', className)}\n data-testid=\"agent-embed\"\n >\n <AgentChat\n endpoint={endpoint}\n title={title}\n className=\"h-full rounded-none border-0\"\n />\n </div>\n )\n}\n\nexport { AgentEmbed }\n"],"mappings":"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","names":["twMerge","useState","useCallback","twMerge","twMerge","useCallback","useRef","twMerge","Badge","content","ReactMarkdown","rehypeSanitize","jsx","twMerge","jsx","jsxs","jsx","jsxs","twMerge","jsx","jsx","jsxs","getConfidenceIntent","Badge","jsx","jsxs","twMerge","jsx","jsxs","useRef","useCallback","twMerge","twMerge","useState","useRef","useCallback","jsx","jsxs","DocumentIcon","jsxs","jsx","DocumentIcon","twMerge","useState","useRef","useCallback","twMerge","jsx","jsxs","useEffect","useRef","twMerge","useState","useRef","useEffect","jsx","jsxs","useRef","useEffect","twMerge","jsx","jsxs","twMerge","twMerge","jsx","jsxs","Fragment","jsx","jsxs","useState","useCallback","twMerge","twMerge","useRef","useEffect","jsx","jsxs","useRef","useEffect","twMerge","twMerge","useState","useCallback","jsx","jsxs","useState","useCallback","twMerge","twMerge","jsx","twMerge"]}