@surf-kit/agent 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +184 -12
- package/README.md +1 -1
- package/dist/agent-identity/index.cjs +1 -0
- package/dist/agent-identity/index.cjs.map +1 -1
- package/dist/agent-identity/index.js +2 -0
- package/dist/agent-identity/index.js.map +1 -1
- package/dist/chat/index.cjs +1 -0
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.js +2 -0
- package/dist/chat/index.js.map +1 -1
- package/dist/confidence/index.cjs +1 -0
- package/dist/confidence/index.cjs.map +1 -1
- package/dist/confidence/index.js +2 -0
- package/dist/confidence/index.js.map +1 -1
- package/dist/feedback/index.cjs +1 -0
- package/dist/feedback/index.cjs.map +1 -1
- package/dist/feedback/index.js +2 -0
- package/dist/feedback/index.js.map +1 -1
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/layouts/index.cjs +1 -0
- package/dist/layouts/index.cjs.map +1 -1
- package/dist/layouts/index.js +2 -0
- package/dist/layouts/index.js.map +1 -1
- package/dist/mcp/index.cjs +1 -0
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/response/index.cjs +1 -0
- package/dist/response/index.cjs.map +1 -1
- package/dist/response/index.js +2 -0
- package/dist/response/index.js.map +1 -1
- package/dist/sources/index.cjs +1 -0
- package/dist/sources/index.cjs.map +1 -1
- package/dist/sources/index.js +2 -0
- package/dist/sources/index.js.map +1 -1
- package/dist/streaming/index.cjs +1 -0
- package/dist/streaming/index.cjs.map +1 -1
- package/dist/streaming/index.js +2 -0
- package/dist/streaming/index.js.map +1 -1
- package/package.json +6 -6
package/dist/layouts/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/layouts/index.ts","../../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":["export { AgentFullPage } from './AgentFullPage'\nexport type { AgentFullPageProps } from './AgentFullPage'\n\nexport { AgentPanel } from './AgentPanel'\nexport type { AgentPanelProps } from './AgentPanel'\n\nexport { AgentWidget } from './AgentWidget'\nexport type { AgentWidgetProps } from './AgentWidget'\n\nexport { AgentEmbed } from './AgentEmbed'\nexport type { AgentEmbedProps } from './AgentEmbed'\n","import { 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","import { useReducer, useCallback, useRef } from 'react'\nimport type { ChatMessage, ChatError } 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}\n\nconst initialState: AgentChatState = {\n messages: [],\n conversationId: null,\n isLoading: false,\n error: null,\n inputValue: '',\n streamPhase: 'idle',\n streamingContent: '',\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: '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 }\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 '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 }\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) => 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\n const sendMessage = useCallback(\n async (content: string) => {\n const { apiUrl, streamPath = '/chat/stream', headers = {}, timeout = 30000 } = configRef.current\n\n lastUserMessageRef.current = content\n\n const userMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'user',\n content,\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 response = await fetch(`${apiUrl}${streamPath}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n },\n body: JSON.stringify({\n message: content,\n conversation_id: state.conversationId,\n }),\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 let accumulatedContent = ''\n let agentResponse: AgentResponse | null = null\n let capturedAgent: string | null = null\n let capturedConversationId: string | null = null\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 switch (event.type) {\n case 'agent':\n capturedAgent = event.agent as string\n break\n case 'phase':\n dispatch({ type: 'STREAM_PHASE', phase: event.phase })\n break\n case 'delta':\n accumulatedContent += event.content\n dispatch({ type: 'STREAM_CONTENT', content: event.content as string })\n break\n case 'done':\n agentResponse = event.response\n capturedConversationId = (event.conversation_id as string) ?? null\n break\n case 'error':\n dispatch({ type: 'SEND_ERROR', error: event.error })\n return\n }\n } catch {\n // Skip malformed events\n }\n }\n }\n\n const assistantMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: agentResponse?.message ?? accumulatedContent,\n response: agentResponse ?? undefined,\n agent: capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n\n dispatch({\n type: 'SEND_SUCCESS',\n message: assistantMessage,\n streamingContent: accumulatedContent,\n conversationId: 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 = {} } = configRef.current\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)\n }\n }, [sendMessage])\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' })\n lastUserMessageRef.current = null\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","import { twMerge } from 'tailwind-merge'\nimport React, { 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 showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n className?: string\n}\n\nfunction MessageThread({ messages, streamingSlot, showSources, showConfidence, showVerification, className }: MessageThreadProps) {\n const bottomRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView?.({ behavior: 'smooth' })\n }, [messages.length, streamingSlot])\n\n return (\n <div\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Message thread\"\n className={twMerge(\n 'flex flex-col gap-4 overflow-y-auto flex-1 px-4 py-6',\n className,\n )}\n >\n {messages.map((message) => (\n <MessageBubble\n key={message.id}\n message={message}\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n />\n ))}\n {streamingSlot}\n <div ref={bottomRef} />\n </div>\n )\n}\n\nexport { MessageThread }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport type { ChatMessage } from '../../types/chat'\nimport { AgentResponse } from '../../response/AgentResponse'\nimport { ResponseMessage } from '../../response/ResponseMessage'\n\nexport type MessageBubbleProps = {\n message: ChatMessage\n showAgent?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n animated?: boolean\n className?: string\n}\n\nfunction MessageBubble({\n message,\n showAgent,\n showSources = true,\n showConfidence = true,\n showVerification = true,\n animated = true,\n className,\n}: MessageBubbleProps) {\n const isUser = message.role === 'user'\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-accent text-brand-cream break-words whitespace-pre-wrap text-sm leading-relaxed',\n animated && 'motion-safe:animate-slideFromRight',\n )}\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-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 <StructuredResponse\n uiHint={response.ui_hint}\n data={response.structured_data as Record<string, unknown>}\n />\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 '[&_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 }) => <li className=\"my-1\">{children}</li>,\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\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 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, className }: StructuredResponseProps) {\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","import 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 <p className=\"text-sm font-medium text-text-primary truncate\">\n {source.title}\n </p>\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","import { twMerge } from 'tailwind-merge'\nimport React, { useState, useRef, useCallback } from 'react'\n\nexport type MessageComposerProps = {\n onSend: (content: string) => void\n isLoading?: boolean\n placeholder?: string\n className?: string\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 textareaRef = useRef<HTMLTextAreaElement>(null)\n\n const canSend = value.trim().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 onSend(value.trim())\n setValue('')\n resetHeight()\n textareaRef.current?.focus()\n }, [canSend, onSend, value, 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, 128)\n el.style.height = `${capped}px`\n el.style.overflowY = el.scrollHeight > 128 ? 'auto' : 'hidden'\n },\n [],\n )\n\n return (\n <div\n className={twMerge(\n 'flex items-end gap-3 shrink-0 border-t border-border px-4 py-3',\n className,\n )}\n >\n <textarea\n ref={textareaRef}\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n disabled={isLoading}\n className={twMerge(\n 'flex-1 resize-none rounded-xl border border-border bg-surface/80',\n 'px-4 py-2.5 text-sm text-text-primary placeholder:text-text-muted',\n 'focus:border-transparent focus:ring-2 focus:ring-accent/40 focus:outline-none',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n 'overflow-hidden',\n 'transition-all duration-200',\n )}\n style={{ colorScheme: 'dark' }}\n aria-label=\"Message input\"\n />\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!value.trim() || isLoading}\n aria-label=\"Send message\"\n className={twMerge(\n 'inline-flex items-center justify-center rounded-xl px-5 py-2.5',\n 'text-sm font-semibold text-white shrink-0',\n 'transition-all duration-200',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n value.trim() && !isLoading\n ? 'bg-accent hover:bg-accent-hover hover:scale-[1.02] hover:shadow-glow-cyan active:scale-[0.98]'\n : 'bg-accent/30 text-text-muted cursor-not-allowed',\n )}\n >\n Send\n </button>\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?: string\n icon?: React.ReactNode\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 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 <div\n className=\"w-14 h-14 rounded-2xl bg-accent/10 border border-border flex items-center justify-center pulse-glow\"\n aria-hidden=\"true\"\n >\n {icon ?? <span className=\"text-2xl\">✦</span>}\n </div>\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-md\"\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-4 py-2 rounded-full text-sm',\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","import React, { useEffect, useRef } from 'react'\nimport { Spinner } from '@surf-kit/core'\nimport type { StreamState } from '../../types/streaming'\nimport { useCharacterDrain } from '../../hooks/useCharacterDrain'\n\ntype StreamingMessageProps = {\n stream: StreamState\n onComplete?: () => 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\nfunction StreamingMessage({\n stream,\n onComplete,\n showPhases = true,\n className,\n}: StreamingMessageProps) {\n const onCompleteRef = useRef(onComplete)\n onCompleteRef.current = onComplete\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: displayedContent } = useCharacterDrain(stream.content)\n\n return (\n <div className={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 <div className=\"max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft\">\n {showPhases && stream.active && stream.phase !== 'idle' && (\n <div\n className=\"flex items-center gap-2 mb-2 text-sm text-text-secondary\"\n data-testid=\"phase-indicator\"\n >\n <span aria-hidden=\"true\">\n <Spinner size=\"sm\" />\n </span>\n <span>{phaseLabel}</span>\n </div>\n )}\n\n <div className=\"text-sm leading-relaxed text-text-primary whitespace-pre-wrap\">\n {displayedContent}\n {stream.active && (\n <span\n className=\"inline-block w-0.5 h-4 bg-accent align-text-bottom animate-pulse ml-0.5\"\n aria-hidden=\"true\"\n data-testid=\"streaming-cursor\"\n />\n )}\n </div>\n </div>\n </div>\n )\n}\n\nexport { StreamingMessage }\nexport type { StreamingMessageProps }\n","import { 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 const nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length)\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","import { 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","import { 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":["import_tailwind_merge","import_react","import_tailwind_merge","import_tailwind_merge","import_react","import_tailwind_merge","import_core","ReactMarkdown","rehypeSanitize","import_jsx_runtime","import_react","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","getConfidenceIntent","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_react","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_react","import_core","import_react","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_react","import_jsx_runtime","import_tailwind_merge","import_react","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../../src/layouts/index.ts","../../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":["export { AgentFullPage } from './AgentFullPage'\nexport type { AgentFullPageProps } from './AgentFullPage'\n\nexport { AgentPanel } from './AgentPanel'\nexport type { AgentPanelProps } from './AgentPanel'\n\nexport { AgentWidget } from './AgentWidget'\nexport type { AgentWidgetProps } from './AgentWidget'\n\nexport { AgentEmbed } from './AgentEmbed'\nexport type { AgentEmbedProps } from './AgentEmbed'\n","'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 } 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}\n\nconst initialState: AgentChatState = {\n messages: [],\n conversationId: null,\n isLoading: false,\n error: null,\n inputValue: '',\n streamPhase: 'idle',\n streamingContent: '',\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: '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 }\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 '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 }\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) => 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\n const sendMessage = useCallback(\n async (content: string) => {\n const { apiUrl, streamPath = '/chat/stream', headers = {}, timeout = 30000 } = configRef.current\n\n lastUserMessageRef.current = content\n\n const userMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'user',\n content,\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 response = await fetch(`${apiUrl}${streamPath}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'text/event-stream',\n ...headers,\n },\n body: JSON.stringify({\n message: content,\n conversation_id: state.conversationId,\n }),\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 let accumulatedContent = ''\n let agentResponse: AgentResponse | null = null\n let capturedAgent: string | null = null\n let capturedConversationId: string | null = null\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 switch (event.type) {\n case 'agent':\n capturedAgent = event.agent as string\n break\n case 'phase':\n dispatch({ type: 'STREAM_PHASE', phase: event.phase })\n break\n case 'delta':\n accumulatedContent += event.content\n dispatch({ type: 'STREAM_CONTENT', content: event.content as string })\n break\n case 'done':\n agentResponse = event.response\n capturedConversationId = (event.conversation_id as string) ?? null\n break\n case 'error':\n dispatch({ type: 'SEND_ERROR', error: event.error })\n return\n }\n } catch {\n // Skip malformed events\n }\n }\n }\n\n const assistantMessage: ChatMessage = {\n id: generateMessageId(),\n role: 'assistant',\n content: agentResponse?.message ?? accumulatedContent,\n response: agentResponse ?? undefined,\n agent: capturedAgent ?? undefined,\n timestamp: new Date(),\n }\n\n dispatch({\n type: 'SEND_SUCCESS',\n message: assistantMessage,\n streamingContent: accumulatedContent,\n conversationId: 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 = {} } = configRef.current\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)\n }\n }, [sendMessage])\n\n const reset = useCallback(() => {\n dispatch({ type: 'RESET' })\n lastUserMessageRef.current = null\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, { 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 showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n className?: string\n}\n\nfunction MessageThread({ messages, streamingSlot, showSources, showConfidence, showVerification, className }: MessageThreadProps) {\n const bottomRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n bottomRef.current?.scrollIntoView?.({ behavior: 'smooth' })\n }, [messages.length, streamingSlot])\n\n return (\n <div\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Message thread\"\n className={twMerge(\n 'flex flex-col gap-4 overflow-y-auto flex-1 px-4 py-6',\n className,\n )}\n >\n {messages.map((message) => (\n <MessageBubble\n key={message.id}\n message={message}\n showSources={showSources}\n showConfidence={showConfidence}\n showVerification={showVerification}\n />\n ))}\n {streamingSlot}\n <div ref={bottomRef} />\n </div>\n )\n}\n\nexport { MessageThread }\n","import { twMerge } from 'tailwind-merge'\nimport React from 'react'\nimport type { ChatMessage } from '../../types/chat'\nimport { AgentResponse } from '../../response/AgentResponse'\nimport { ResponseMessage } from '../../response/ResponseMessage'\n\nexport type MessageBubbleProps = {\n message: ChatMessage\n showAgent?: boolean\n showSources?: boolean\n showConfidence?: boolean\n showVerification?: boolean\n animated?: boolean\n className?: string\n}\n\nfunction MessageBubble({\n message,\n showAgent,\n showSources = true,\n showConfidence = true,\n showVerification = true,\n animated = true,\n className,\n}: MessageBubbleProps) {\n const isUser = message.role === 'user'\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-accent text-brand-cream break-words whitespace-pre-wrap text-sm leading-relaxed',\n animated && 'motion-safe:animate-slideFromRight',\n )}\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-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 <StructuredResponse\n uiHint={response.ui_hint}\n data={response.structured_data as Record<string, unknown>}\n />\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 '[&_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 }) => <li className=\"my-1\">{children}</li>,\n strong: ({ children }) => <strong className=\"font-semibold\">{children}</strong>,\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 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, className }: StructuredResponseProps) {\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 <p className=\"text-sm font-medium text-text-primary truncate\">\n {source.title}\n </p>\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'\n\nexport type MessageComposerProps = {\n onSend: (content: string) => void\n isLoading?: boolean\n placeholder?: string\n className?: string\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 textareaRef = useRef<HTMLTextAreaElement>(null)\n\n const canSend = value.trim().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 onSend(value.trim())\n setValue('')\n resetHeight()\n textareaRef.current?.focus()\n }, [canSend, onSend, value, 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, 128)\n el.style.height = `${capped}px`\n el.style.overflowY = el.scrollHeight > 128 ? 'auto' : 'hidden'\n },\n [],\n )\n\n return (\n <div\n className={twMerge(\n 'flex items-end gap-3 shrink-0 border-t border-border px-4 py-3',\n className,\n )}\n >\n <textarea\n ref={textareaRef}\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n rows={1}\n disabled={isLoading}\n className={twMerge(\n 'flex-1 resize-none rounded-xl border border-border bg-surface/80',\n 'px-4 py-2.5 text-sm text-text-primary placeholder:text-text-muted',\n 'focus:border-transparent focus:ring-2 focus:ring-accent/40 focus:outline-none',\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n 'overflow-hidden',\n 'transition-all duration-200',\n )}\n style={{ colorScheme: 'dark' }}\n aria-label=\"Message input\"\n />\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!value.trim() || isLoading}\n aria-label=\"Send message\"\n className={twMerge(\n 'inline-flex items-center justify-center rounded-xl px-5 py-2.5',\n 'text-sm font-semibold text-white shrink-0',\n 'transition-all duration-200',\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent',\n value.trim() && !isLoading\n ? 'bg-accent hover:bg-accent-hover hover:scale-[1.02] hover:shadow-glow-cyan active:scale-[0.98]'\n : 'bg-accent/30 text-text-muted cursor-not-allowed',\n )}\n >\n Send\n </button>\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?: string\n icon?: React.ReactNode\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 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 <div\n className=\"w-14 h-14 rounded-2xl bg-accent/10 border border-border flex items-center justify-center pulse-glow\"\n aria-hidden=\"true\"\n >\n {icon ?? <span className=\"text-2xl\">✦</span>}\n </div>\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-md\"\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-4 py-2 rounded-full text-sm',\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 { Spinner } from '@surf-kit/core'\nimport type { StreamState } from '../../types/streaming'\nimport { useCharacterDrain } from '../../hooks/useCharacterDrain'\n\ntype StreamingMessageProps = {\n stream: StreamState\n onComplete?: () => 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\nfunction StreamingMessage({\n stream,\n onComplete,\n showPhases = true,\n className,\n}: StreamingMessageProps) {\n const onCompleteRef = useRef(onComplete)\n onCompleteRef.current = onComplete\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: displayedContent } = useCharacterDrain(stream.content)\n\n return (\n <div className={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 <div className=\"max-w-[88%] px-4 py-3 rounded-[18px] rounded-tl-[4px] bg-surface border border-border motion-safe:animate-springFromLeft\">\n {showPhases && stream.active && stream.phase !== 'idle' && (\n <div\n className=\"flex items-center gap-2 mb-2 text-sm text-text-secondary\"\n data-testid=\"phase-indicator\"\n >\n <span aria-hidden=\"true\">\n <Spinner size=\"sm\" />\n </span>\n <span>{phaseLabel}</span>\n </div>\n )}\n\n <div className=\"text-sm leading-relaxed text-text-primary whitespace-pre-wrap\">\n {displayedContent}\n {stream.active && (\n <span\n className=\"inline-block w-0.5 h-4 bg-accent align-text-bottom animate-pulse ml-0.5\"\n aria-hidden=\"true\"\n data-testid=\"streaming-cursor\"\n />\n )}\n </div>\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 const nextIndex = Math.min(indexRef.current + charsToAdvance, currentTarget.length)\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":["import_tailwind_merge","import_react","import_tailwind_merge","import_tailwind_merge","import_react","import_tailwind_merge","import_core","ReactMarkdown","rehypeSanitize","import_jsx_runtime","import_react","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","getConfidenceIntent","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_react","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_react","import_core","import_react","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","import_tailwind_merge","import_react","import_jsx_runtime","import_tailwind_merge","import_react","import_jsx_runtime","import_tailwind_merge","import_jsx_runtime"]}
|