@contentgrowth/llm-service 1.0.0 → 1.0.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/react/components/index.ts","../../../../src/ui/react/components/ChatBubble.tsx","../../../../src/ui/react/components/MessageBubble.tsx","../../../../src/ui/react/context/ChatConfigContext.tsx","../../../../src/ui/react/components/ChatHeader.tsx","../../../../src/ui/react/components/ChatInputArea.tsx","../../../../src/ui/react/hooks/useAudioRecorder.ts","../../../../src/ui/react/hooks/useProactiveResize.ts","../../../../src/ui/react/components/TapToTalk.tsx","../../../../src/ui/react/components/ChatMessageList.tsx","../../../../src/ui/react/components/interactive/ConfirmInteraction.tsx","../../../../src/ui/react/components/interactive/SelectInteraction.tsx","../../../../src/ui/react/components/interactive/FormInteraction.tsx","../../../../src/ui/react/components/interactive/PresentInteraction.tsx","../../../../src/ui/react/components/interactive/InteractiveMessageHandler.tsx","../../../../src/ui/react/components/ConnectionStatus.tsx","../../../../src/ui/react/components/Spinner.tsx","../../../../src/ui/react/services/whisper-client.ts","../../../../src/ui/react/utils/voice-utils.ts"],"sourcesContent":["export * from './ChatBubble';\nexport * from './MessageBubble';\nexport * from './ChatHeader';\nexport * from './ChatInputArea';\nexport * from './TapToTalk';\nexport * from './ChatMessageList';\nexport * from './ConnectionStatus';\nexport * from './Spinner';\nexport * from '../hooks/useProactiveResize';\nexport * from '../hooks/useAudioRecorder';\nexport * from '../types/chat';\nexport * from '../types/interactive';\nexport * from '../context/ChatConfigContext';\nexport * from '../services/whisper-client';\nexport * from '../utils/voice-utils';\n","'use client';\n\nimport React from 'react';\n\ninterface ChatBubbleProps {\n onClick: () => void;\n}\n\nexport function ChatBubble({ onClick }: ChatBubbleProps) {\n return (\n <button\n onClick={onClick}\n className=\"bg-blue-500 hover:bg-blue-600 text-white rounded-full w-12 h-12 flex items-center justify-center shadow-lg animate-pulse\"\n aria-label=\"Open chat assistant\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z\" />\n </svg>\n </button>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { SparklesIcon } from '@heroicons/react/24/solid';\nimport { ChatMessage } from '../types/chat';\nimport { useChatConfig } from '../context/ChatConfigContext';\n\nexport interface MessageBubbleProps {\n message: ChatMessage;\n isUser: boolean;\n userAvatarUrl?: string; // Optional user avatar URL\n onViewChanges?: (diff: { oldContent: string; newContent: string }) => void;\n}\n\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({\n message,\n isUser,\n userAvatarUrl,\n onViewChanges\n}) => {\n const { user } = useChatConfig();\n const finalAvatarUrl = userAvatarUrl || user?.avatarUrl;\n const isSystem = message.role === 'system';\n\n if (isSystem) {\n return (\n <div className=\"text-center my-4\">\n <span className=\"text-xs text-gray-500 italic bg-gray-100 px-3 py-1 rounded-full\">\n {message.content}\n {message.diff && onViewChanges && (\n <button\n onClick={() => onViewChanges(message.diff!)}\n className=\"ml-2 font-semibold text-blue-600 hover:underline focus:outline-none\"\n >\n View Changes\n </button>\n )}\n </span>\n </div>\n );\n }\n\n return (\n <div className={`flex items-start gap-3 my-1 ${isUser ? 'justify-end' : 'justify-start'}`}>\n {/* Assistant Avatar */}\n {!isUser && (\n <div className=\"flex-shrink-0 h-8 w-8 rounded-full bg-blue-500 flex items-center justify-center text-white\">\n <SparklesIcon className=\"h-5 w-5\" />\n </div>\n )}\n\n {/* Content Bubble */}\n <div\n className={`max-w-[85%] px-4 py-3 rounded-2xl shadow-sm overflow-hidden ${isUser\n ? 'bg-blue-500 text-white rounded-br-none'\n : 'bg-gray-100 text-gray-800 rounded-bl-none'\n }`}>\n <div className={`text-sm ${!isUser ? 'prose prose-sm max-w-none' : ''}`}>\n {isUser ? (\n <p className=\"whitespace-pre-wrap\">{message.content}</p>\n ) : (\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n p: ({ node, ...props }) => <p className=\"mb-2 last:mb-0\" {...props} />,\n ul: ({ node, ...props }) => <ul className=\"list-disc ml-4 mb-2\" {...props} />,\n ol: ({ node, ...props }) => <ol className=\"list-decimal ml-4 mb-2\" {...props} />,\n li: ({ node, ...props }) => <li className=\"mb-0.5\" {...props} />,\n a: ({ node, ...props }) => <a className=\"text-blue-600 hover:underline\" {...props} />,\n code: ({ node, ...props }) => <code className=\"bg-gray-200 rounded px-1 py-0.5 text-xs font-mono\" {...props} />\n }}\n >\n {message.content}\n </ReactMarkdown>\n )}\n </div>\n {message.role === 'assistant' && message.diff && onViewChanges && (\n <button\n onClick={() => onViewChanges(message.diff!)}\n className=\"mt-2 text-sm text-blue-500 hover:underline block\"\n >\n View Changes\n </button>\n )}\n {message.actionResult && message.actionResult.type === 'link' && (\n <div className=\"mt-2 pt-2 border-t border-gray-300\">\n <a\n href={message.actionResult.url}\n target={message.actionResult.target || '_blank'}\n rel=\"noopener noreferrer\"\n onClick={(e) => {\n if (message.actionResult?.target && message.actionResult.target !== '_blank') {\n e.preventDefault();\n window.open(message.actionResult.url, message.actionResult.target);\n }\n }}\n className={`inline-flex items-center gap-1 text-sm font-medium hover:underline ${isUser\n ? 'text-blue-100 hover:text-white'\n : 'text-blue-600 hover:text-blue-800'\n }`}\n >\n {message.actionResult.label}\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} 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 </div>\n )}\n </div>\n\n {/* User Avatar */}\n {isUser && (\n <div className=\"flex-shrink-0 h-8 w-8 rounded-full bg-gray-200 overflow-hidden flex items-center justify-center text-gray-500\">\n {finalAvatarUrl ? (\n <img\n className=\"h-full w-full object-cover\"\n src={finalAvatarUrl}\n alt=\"User\"\n onError={(e) => {\n // Hide image and show fallback icon if load fails involves state, \n // but for a simple component we can just hide it or let the parent handle it.\n // For now, let's just render the icon if no url, \n // preventing the broken image icon requires state or a different approach (like standard Radix Avatar).\n // A simple hack: set src to a transparent pixel or hide display.\n (e.target as HTMLImageElement).style.display = 'none';\n (e.target as HTMLImageElement).parentElement?.classList.remove('bg-gray-200'); // Clean up?\n // Actually, better to just render the fallback SVG behind it?\n // Let's try separate conditional structure.\n }}\n />\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" className=\"w-5 h-5\">\n <path fillRule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clipRule=\"evenodd\" />\n </svg>\n )}\n </div>\n )}\n </div>\n );\n};\n","import React, { createContext, useContext, ReactNode } from 'react';\nimport { VoiceConfig } from '../types/chat';\n\nexport interface ChatConfig {\n user?: {\n avatarUrl?: string;\n name?: string;\n };\n voice?: {\n enabled: boolean;\n config?: VoiceConfig;\n };\n}\n\nconst ChatConfigContext = createContext<ChatConfig>({});\n\nexport const ChatConfigProvider: React.FC<{\n config: ChatConfig;\n children: ReactNode;\n}> = ({ config, children }) => {\n return (\n <ChatConfigContext.Provider value={config}>\n {children}\n </ChatConfigContext.Provider>\n );\n};\n\nexport const useChatConfig = () => useContext(ChatConfigContext);\n","'use client';\n\nimport React from 'react';\nimport { ChatTask } from '../types/chat';\n\ninterface ChatHeaderProps {\n contextTitle: string;\n currentTask: ChatTask | null;\n onClose: () => void;\n}\n\nexport function ChatHeader({\n contextTitle,\n currentTask,\n onClose\n}: ChatHeaderProps) {\n return (\n <div className=\"bg-blue-500 text-white px-4 py-4 flex justify-between items-center\">\n <h3 className=\"font-medium text-lg\">\n {currentTask\n ? `DoveText Virtual Assistant (${currentTask.currentStep}/${currentTask.steps})`\n : `DoveText Virtual Assistant (${contextTitle})`}\n </h3>\n <button\n onClick={onClose}\n className=\"bg-blue-600 hover:bg-blue-700 text-white rounded-full p-1.5 flex items-center justify-center transition-colors cursor-pointer\"\n aria-label=\"Close chat\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clipRule=\"evenodd\" />\n </svg>\n </button>\n </div>\n );\n}\n","'use client';\n\nimport React, { useState, useRef, FormEvent, useImperativeHandle, forwardRef, useEffect, useCallback, useLayoutEffect } from 'react';\nimport { MicrophoneIcon, StopIcon, PaperAirplaneIcon, XMarkIcon, Square2StackIcon } from '@heroicons/react/24/outline';\nimport { ChatMessage, ChatTask, VoiceConfig } from '../types/chat';\nimport { InteractiveFunction } from '../types/interactive';\nimport { useAudioRecorder } from '../hooks/useAudioRecorder';\nimport { useProactiveResize } from '../hooks/useProactiveResize';\nimport { useChatConfig } from '../context/ChatConfigContext';\n\n// VoiceConfig imported from types/chat\n\ninterface ChatInputAreaProps {\n onSubmit: (message: string) => void;\n isSending: boolean;\n showInputForm: boolean;\n currentTask: ChatTask | null;\n lastInteractiveMessage?: ChatMessage | null;\n voiceConfig?: VoiceConfig;\n onStop?: () => void;\n hintText?: string;\n placeholder?: string;\n // Controlled props\n value?: string;\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n defaultInputMode?: 'text' | 'voice'; // Deprecated but kept for compatibility\n}\n\n// Define the handle type for the forwarded ref\nexport interface ChatInputAreaHandle {\n focus: () => void;\n setValue: (value: string) => void;\n}\n\nexport const ChatInputArea = forwardRef<ChatInputAreaHandle, ChatInputAreaProps>(({\n onSubmit,\n isSending,\n showInputForm,\n currentTask,\n lastInteractiveMessage,\n voiceConfig: propVoiceConfig, // Rename to distinguish from context\n onStop,\n hintText,\n placeholder,\n value,\n onChange,\n defaultInputMode = 'text'\n}, ref) => {\n const [internalMessage, setInternalMessage] = useState('');\n const [voiceTrigger, setVoiceTrigger] = useState<'click' | 'space' | null>(null);\n const [isTranscribing, setIsTranscribing] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n // Debug Mode State\n const [showDebug, setShowDebug] = useState(false);\n const [logs, setLogs] = useState<string[]>([]);\n const tapCountRef = useRef<{ count: number, lastTap: number }>({ count: 0, lastTap: 0 });\n\n // Console Interceptor for Debug Mode\n useEffect(() => {\n const originalLog = console.log;\n const originalWarn = console.warn;\n const originalError = console.error;\n\n const addLog = (type: string, args: any[]) => {\n // Only keep logs if we are potentially debugging, to save memory? \n // Or just keep last 50 always. Let's keep last 50.\n try {\n const msg = args.map(arg => {\n if (arg instanceof Error) return `${arg.name}: ${arg.message}`;\n if (typeof arg === 'object') return JSON.stringify(arg);\n return String(arg);\n }).join(' ');\n setLogs(prev => [`[${type}] ${msg}`, ...prev].slice(0, 50));\n } catch (e) {\n // Ignore serialization errors\n }\n };\n\n console.log = (...args) => { originalLog(...args); addLog('LOG', args); };\n console.warn = (...args) => { originalWarn(...args); addLog('WRN', args); };\n console.error = (...args) => { originalError(...args); addLog('ERR', args); };\n\n return () => {\n console.log = originalLog;\n console.warn = originalWarn;\n console.error = originalError;\n };\n }, []);\n\n const copyLogs = useCallback(() => {\n navigator.clipboard.writeText(logs.join('\\n'))\n .then(() => alert('Logs copied to clipboard'))\n .catch(err => console.error('Failed to copy logs', err));\n }, [logs]);\n // The left button toggles recording, but input is always text.\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const measurementRef = useRef<HTMLSpanElement>(null);\n const pendingSelectionRef = useRef<{ start: number, end: number } | null>(null);\n\n // Determine if controlled or uncontrolled\n const isControlled = value !== undefined;\n const message = isControlled ? value : internalMessage;\n\n // Use refs to access latest state in stable callbacks\n const messageRef = useRef(message);\n messageRef.current = message;\n\n // Use useLayoutEffect to apply selection before browser paint\n useLayoutEffect(() => {\n if (pendingSelectionRef.current && textareaRef.current) {\n const { start, end } = pendingSelectionRef.current;\n textareaRef.current.focus();\n textareaRef.current.setSelectionRange(start, end);\n pendingSelectionRef.current = null;\n }\n }, [message]);\n\n const onChangeRef = useRef(onChange);\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n // Get global config\n const { voice: globalVoice } = useChatConfig();\n\n // Determine effective voice config\n const isVoiceEnabled = globalVoice?.enabled ?? (!!propVoiceConfig);\n const voiceConfig = isVoiceEnabled ? (propVoiceConfig || globalVoice?.config) : undefined;\n\n const voiceConfigRef = useRef(voiceConfig);\n useEffect(() => {\n voiceConfigRef.current = voiceConfig;\n }, [voiceConfig]);\n\n const triggerChange = useCallback((newValue: string) => {\n setVoiceError(null); // Clear any errors when content changes\n if (isControlled && onChangeRef.current) {\n const syntheticEvent = {\n target: { value: newValue },\n currentTarget: { value: newValue }\n } as React.ChangeEvent<HTMLTextAreaElement>;\n onChangeRef.current(syntheticEvent);\n } else {\n setInternalMessage(newValue);\n }\n }, [isControlled]);\n\n // Apply auto-resize\n const isInputDisabled = currentTask?.complete ||\n (lastInteractiveMessage?.interactive &&\n ((lastInteractiveMessage?.interactiveData?.function === 'form' && !lastInteractiveMessage?.isResponseSubmitted) ||\n (lastInteractiveMessage?.interactiveData?.function === 'confirm' && !lastInteractiveMessage?.isResponseSubmitted)));\n\n useProactiveResize(textareaRef, measurementRef, message, isInputDisabled || !!voiceTrigger);\n\n // Helper to insert text at cursor position\n const insertTextAtCursor = useCallback((text: string) => {\n const textarea = textareaRef.current;\n const currentVal = messageRef.current || '';\n\n if (!textarea) {\n triggerChange(currentVal + (currentVal ? ' ' : '') + text);\n return;\n }\n\n const start = textarea.selectionStart;\n const end = textarea.selectionEnd;\n\n const before = currentVal.substring(0, start);\n const after = currentVal.substring(end);\n\n // Add padding space if needed (e.g. not at start and previous char is not space)\n const prefix = (start > 0 && !/\\s$/.test(before)) ? ' ' : '';\n\n const newText = before + prefix + text + after;\n\n // Calculate and store pending selection so it can be applied after render\n const selectionStart = start + prefix.length;\n const selectionEnd = selectionStart + text.length;\n pendingSelectionRef.current = { start: selectionStart, end: selectionEnd };\n\n triggerChange(newText);\n }, [triggerChange]);\n\n // Stable Voice Callbacks\n const handleVoiceResult = useCallback((text: string, isFinal: boolean) => {\n if (isFinal) {\n insertTextAtCursor(text);\n }\n }, [insertTextAtCursor]);\n\n const handleVoiceEnd = useCallback(() => {\n setVoiceTrigger(null);\n voiceConfigRef.current?.onVoiceEnd?.();\n }, []);\n\n const customRecorder = useAudioRecorder(async (blob) => {\n setVoiceTrigger(null);\n setIsTranscribing(true);\n setVoiceError(null);\n voiceConfigRef.current?.onVoiceEnd?.();\n\n if (blob.type === 'audio/simulated') {\n console.log('[ChatInputArea] Handling simulated audio capture');\n // Mock delay for simulation\n await new Promise(resolve => setTimeout(resolve, 1500));\n insertTextAtCursor('This is a simulated transcription for development testing.');\n setIsTranscribing(false);\n return;\n }\n\n if (voiceConfigRef.current?.onAudioCapture) {\n try {\n const text = await voiceConfigRef.current.onAudioCapture(blob);\n if (text) insertTextAtCursor(text);\n } catch (e: any) {\n console.error('[ChatInputArea] Audio capture failed', e);\n setVoiceError(e.message || 'Transcription failed');\n } finally {\n setIsTranscribing(false);\n }\n } else {\n setIsTranscribing(false);\n }\n });\n\n // Expose the focus and setValue method\n useImperativeHandle(ref, () => ({\n focus: () => {\n textareaRef.current?.focus();\n },\n setValue: (newValue: string) => {\n triggerChange(newValue);\n }\n }));\n\n const handleSubmit = (e?: FormEvent) => {\n if (e) e.preventDefault();\n\n if (!message.trim()) {\n setTimeout(() => textareaRef.current?.focus(), 0);\n return;\n }\n\n const currentMessage = message;\n triggerChange(''); // Clear input\n setTimeout(() => textareaRef.current?.focus(), 0);\n onSubmit(currentMessage);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const startRecording = async (trigger: 'click' | 'space') => {\n if (voiceTrigger || isTranscribing) return;\n setVoiceTrigger(trigger);\n setVoiceError(null);\n voiceConfig?.onVoiceStart?.();\n\n try {\n await customRecorder.start();\n } catch (e: any) {\n console.error('[ChatInputArea] Failed to start recorder:', e);\n setVoiceError('Mic access denied');\n setVoiceTrigger(null);\n }\n\n // Re-focus textarea to preserve selection visibility\n setTimeout(() => textareaRef.current?.focus(), 0);\n };\n\n const stopRecording = () => {\n if (!voiceTrigger) return;\n customRecorder.stop();\n };\n\n // Determine placeholder text\n const getPlaceholder = () => {\n if (placeholder) return placeholder;\n if (voiceTrigger) return 'Listening...';\n if (currentTask?.complete) return 'Task completed!';\n\n if (lastInteractiveMessage?.interactive && lastInteractiveMessage?.interactiveData && !lastInteractiveMessage?.isResponseSubmitted) {\n const interactiveType = lastInteractiveMessage.interactiveData.function as InteractiveFunction;\n switch (interactiveType) {\n case 'chat': return 'Type your response...';\n case 'confirm': return 'Select Yes or No, or type your response...';\n case 'select': return 'Choose an option or type your response...';\n case 'form': return 'Fill out the form...';\n default: return 'Type your response...';\n }\n }\n return currentTask ? 'Continue your conversation...' : 'Ask me anything...';\n };\n\n const inputHint = (!isInputDisabled && !lastInteractiveMessage?.interactive) ? null :\n (lastInteractiveMessage?.interactiveData?.function === 'form' ? 'Please provide information by completing above form' : null);\n\n if (!showInputForm) {\n return null;\n }\n\n return (\n <div className=\"flex flex-col w-full relative\">\n {/* Debug Overlay */}\n {showDebug && (\n <div className=\"absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto\">\n <div className=\"flex justify-between items-center bg-gray-800 p-1 mb-1\">\n <span>Debug Logs</span>\n <div className=\"flex gap-2\">\n <button onClick={copyLogs} className=\"text-white hover:text-blue-400\" title=\"Copy Logs\">\n <Square2StackIcon className=\"w-4 h-4\" />\n </button>\n <button onClick={() => { copyLogs(); setShowDebug(false); }} className=\"text-white hover:text-red-400\" title=\"Copy & Close\">\n <XMarkIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n {logs.map((log, i) => (\n <div key={i} className=\"mb-0.5 border-b border-gray-700/50 pb-0.5 break-all\">\n {log}\n </div>\n ))}\n {logs.length === 0 && <div>No logs yet...</div>}\n </div>\n )}\n\n <div className=\"flex items-center gap-2\">\n {/* Voice Toggle Button (Replacing the Mode Switch) */}\n {voiceConfig && (\n <button\n type=\"button\"\n onClick={() => {\n // Debug Trigger: 5 rapid taps\n const now = Date.now();\n if (now - tapCountRef.current.lastTap < 500) {\n tapCountRef.current.count++;\n } else {\n tapCountRef.current.count = 1;\n }\n tapCountRef.current.lastTap = now;\n\n if (tapCountRef.current.count >= 5) {\n setShowDebug(prev => !prev);\n tapCountRef.current.count = 0;\n // Force stop recording if we accidentally triggered it while tapping\n stopRecording();\n return;\n }\n\n if (voiceTrigger) {\n stopRecording();\n } else if (!isTranscribing) {\n startRecording('click');\n }\n }}\n className={`mb-1 p-2 rounded-full transition-all duration-300 flex-shrink-0 border ${isTranscribing\n ? 'text-white border-indigo-500 bg-indigo-600 scale-110 shadow-lg'\n : voiceTrigger\n ? 'text-white border-orange-400 bg-orange-500 scale-110 shadow-lg'\n : 'text-gray-500 border-gray-300 bg-white hover:text-gray-700 hover:bg-gray-100'\n } ${voiceTrigger ? 'animate-pulse' : ''} ${isTranscribing ? 'cursor-wait' : ''}`}\n disabled={isTranscribing}\n title={isTranscribing ? \"Transcribing...\" : voiceTrigger ? \"Stop Recording\" : \"Start Voice Input\"}\n >\n {isTranscribing ? (\n <div className=\"animate-spin w-5 h-5 flex items-center justify-center\">\n <svg className=\"w-5 h-5 text-white\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" fill=\"none\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n </div>\n ) : (\n <MicrophoneIcon className=\"w-5 h-5\" />\n )}\n </button>\n )}\n\n {/* Main Input Area */}\n <div\n tabIndex={-1}\n className={`flex-1 flex items-center border border-gray-300 rounded-lg overflow-hidden outline-none bg-white min-h-[42px] mb-1 transition-all ${voiceTrigger ? 'ring-2 ring-orange-100 border-orange-300' : 'focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500'\n }`}\n >\n {/* Text Input (Always Visible) */}\n <span\n ref={measurementRef}\n className=\"absolute invisible whitespace-pre-wrap p-0 m-0 text-gray-700 leading-6\"\n style={{ fontSize: '1rem' }}\n />\n <textarea\n ref={textareaRef}\n value={message}\n onChange={(e) => {\n if (isControlled && onChange) {\n onChange(e);\n } else {\n setInternalMessage(e.target.value);\n }\n }}\n onKeyDown={handleKeyDown}\n onFocus={() => {\n setIsFocused(true);\n setVoiceError(null); // Clear error on focus\n }}\n onBlur={() => setIsFocused(false)}\n placeholder={getPlaceholder()}\n disabled={isInputDisabled}\n readOnly={!!voiceTrigger || isTranscribing}\n rows={1}\n className={`flex-grow px-4 py-2 outline-none text-gray-700 placeholder-gray-500 resize-none leading-6 w-full ${isInputDisabled ? 'bg-gray-100 cursor-not-allowed' : 'bg-transparent'\n } ${voiceTrigger || isTranscribing ? 'cursor-default' : ''}`}\n />\n\n {/* Send / Stop Button */}\n <div className=\"relative mx-2 flex-shrink-0\">\n {/* Spinner Overlay */}\n {isSending && (\n <div className=\"absolute -inset-1\">\n <svg\n className=\"animate-spin h-full w-full text-blue-500 opacity-75\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={(e) => {\n if (isSending && onStop) {\n e.preventDefault();\n onStop();\n } else {\n handleSubmit();\n }\n }}\n disabled={currentTask?.complete || (isSending && !onStop) || isInputDisabled}\n className={`relative z-10 text-white rounded-full p-2 transition-colors duration-200 disabled:bg-gray-400 disabled:cursor-not-allowed ${isSending && onStop\n ? 'bg-red-500 hover:bg-red-600'\n : 'bg-blue-600 hover:bg-blue-700'\n }`}\n title={isSending && onStop ? \"Stop generating\" : \"Send message\"}\n >\n {isSending ? (\n onStop ? <StopIcon className=\"h-5 w-5\" /> : <div className=\"w-5 h-5\" /> // Spinner handles the visual\n ) : (\n <PaperAirplaneIcon className=\"h-5 w-5\" />\n )}\n </button>\n </div>\n </div>\n </div>\n\n {/* Helper Hints */}\n {inputHint && (\n <div className=\"text-sm text-red-500 bg-red-50 py-1 px-4 rounded-lg mt-1\">\n {inputHint}\n </div>\n )}\n\n {/* Dynamic Interaction Hint */}\n <div className=\"ml-[46px] mb-2 mt-0.5 min-h-[0.75rem]\" style={{ marginLeft: '48px' }}>\n <p className={`text-[10px] leading-tight transition-all duration-200 ${voiceError\n ? 'text-red-500'\n : isTranscribing\n ? 'text-indigo-600 font-bold'\n : voiceTrigger\n ? 'text-orange-600 font-medium'\n : 'text-gray-400'\n }`}>\n {voiceError ? (\n <span className=\"flex items-center gap-1 font-semibold italic\">\n Error: {voiceError}\n </span>\n ) : isTranscribing ? (\n 'Transcribing... please wait'\n ) : voiceTrigger ? (\n 'Transcribing, please wait...'\n ) : voiceTrigger ? (\n 'Listening... tap mic icon again to stop'\n ) : (\n hintText || (voiceConfig ? 'Type in text or tap mic icon to talk' : 'Type your message...')\n )}\n </p>\n </div>\n </div>\n );\n});\n\nChatInputArea.displayName = 'ChatInputArea';\n","import { useState, useRef, useCallback } from 'react';\n\nexport interface AudioRecorderHook {\n isRecording: boolean;\n isSimulated: boolean;\n start: () => Promise<void>;\n stop: () => void;\n blob: Blob | null;\n error: string | null;\n}\n\nexport const useAudioRecorder = (\n onStop?: (blob: Blob) => void\n): AudioRecorderHook => {\n const [isRecording, setIsRecording] = useState(false);\n const [isSimulated, setIsSimulated] = useState(false);\n const [blob, setBlob] = useState<Blob | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n\n const start = useCallback(async () => {\n\n try {\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n // Dev mode fallback\n if (process.env.NODE_ENV === 'development') {\n console.warn('[useAudioRecorder] MediaDevices not available. Entering simulation mode...');\n setIsRecording(true);\n setIsSimulated(true);\n setError(null);\n return;\n }\n throw new Error('Media devices not available. Ensure you are using HTTPS or localhost.');\n }\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n noiseSuppression: true,\n echoCancellation: true\n }\n });\n\n const mediaRecorder = new MediaRecorder(stream);\n\n mediaRecorderRef.current = mediaRecorder;\n chunksRef.current = [];\n\n mediaRecorder.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunksRef.current.push(e.data);\n }\n };\n\n mediaRecorder.onstop = () => {\n const audioBlob = new Blob(chunksRef.current, { type: 'audio/webm' });\n setBlob(audioBlob);\n setIsRecording(false);\n if (onStop) onStop(audioBlob);\n\n // Stop all tracks\n stream.getTracks().forEach(track => {\n track.stop();\n });\n };\n\n mediaRecorder.start();\n setIsRecording(true);\n setError(null);\n } catch (e: any) {\n console.error('Failed to start audio recording:', e);\n setError(e.message || 'Microphone access denied');\n }\n }, [onStop]);\n\n const stop = useCallback(() => {\n if (isSimulated) {\n setIsRecording(false);\n setIsSimulated(false);\n // Return a special dummy blob that the receiver can recognize as \"simulated\"\n const simulatedBlob = new Blob(['simulated speech'], { type: 'audio/simulated' });\n setBlob(simulatedBlob);\n if (onStop) onStop(simulatedBlob);\n return;\n }\n\n if (mediaRecorderRef.current && mediaRecorderRef.current.state !== 'inactive') {\n mediaRecorderRef.current.stop();\n }\n }, [isSimulated, onStop]);\n\n return {\n isRecording,\n isSimulated,\n start,\n stop,\n blob,\n error\n };\n};\n","import { RefObject, useEffect } from 'react';\n\n/**\n * A hook that proactively resizes a textarea based on the content of a hidden measurement element.\n * This avoids the flickering often seen with standard \"height: auto\" approaches by measuring\n * the content in a hidden span first, then applying the height to the textarea.\n */\nexport function useProactiveResize(\n textareaRef: RefObject<HTMLTextAreaElement>,\n measurementRef: RefObject<HTMLSpanElement>,\n value: string,\n disabled: boolean\n) {\n useEffect(() => {\n if (!textareaRef.current || !measurementRef.current) return;\n\n // Copy styles from textarea to measurement span to ensure accurate sizing\n const styles = window.getComputedStyle(textareaRef.current);\n measurementRef.current.style.width = styles.width;\n measurementRef.current.style.font = styles.font; // Shorthand for font-style, font-variant, font-weight, font-size, line-height, font-family\n measurementRef.current.style.padding = styles.padding;\n measurementRef.current.style.border = styles.border;\n measurementRef.current.style.boxSizing = styles.boxSizing;\n measurementRef.current.style.whiteSpace = 'pre-wrap'; // Important for matching textarea behavior\n measurementRef.current.style.visibility = 'hidden';\n measurementRef.current.style.position = 'absolute';\n measurementRef.current.style.pointerEvents = 'none';\n\n // Set content to measurement span\n // Append a zero-width space to ensure empty lines are counted\n measurementRef.current.textContent = value + '\\u200B';\n\n // Calculate height\n const scrollHeight = measurementRef.current.offsetHeight;\n\n // Apply height to textarea\n // We add a small buffer (e.g., 2px) to prevent scrollbars from appearing due to sub-pixel rendering differences\n // But direct assignment is usually best.\n // Also respect min-height if set in CSS (typically handled by browser, but we set style.height)\n textareaRef.current.style.height = `${scrollHeight}px`;\n\n }, [value, disabled, textareaRef, measurementRef]);\n}\n","import React, { useState, useCallback, useRef } from 'react';\nimport { MicrophoneIcon, StopIcon, XMarkIcon, Square2StackIcon } from '@heroicons/react/24/outline';\nimport { useAudioRecorder } from '../hooks/useAudioRecorder';\nimport { VoiceConfig } from '../types/chat';\nimport { useChatConfig } from '../context/ChatConfigContext';\n\ninterface TapToTalkProps {\n onResult: (text: string) => void;\n voiceConfig?: VoiceConfig;\n className?: string;\n disabled?: boolean;\n tooltip?: string;\n onFocusTarget?: () => void;\n accentColor?: string;\n}\n\nexport const TapToTalk: React.FC<TapToTalkProps> = ({\n onResult,\n voiceConfig: propVoiceConfig,\n className = '',\n disabled = false,\n tooltip = 'Tap to speak',\n onFocusTarget,\n accentColor = 'bg-emerald-600'\n}) => {\n const globalConfig = useChatConfig();\n const voiceConfig = propVoiceConfig || globalConfig.voice?.config;\n\n const [isTranscribing, setIsTranscribing] = useState(false);\n const [voiceTrigger, setVoiceTrigger] = useState<'click' | null>(null);\n const [errorMsg, setErrorMsg] = useState<string | null>(null);\n\n // Debug Mode State\n const [showDebug, setShowDebug] = useState(false);\n const [logs, setLogs] = useState<string[]>([]);\n const tapCountRef = useRef<{ count: number, lastTap: number }>({ count: 0, lastTap: 0 });\n\n // Console Interceptor for Debug Mode\n React.useEffect(() => {\n const originalLog = console.log;\n const originalWarn = console.warn;\n const originalError = console.error;\n\n const addLog = (type: string, args: any[]) => {\n try {\n const msg = args.map(arg => {\n if (arg instanceof Error) return `${arg.name}: ${arg.message}`;\n if (typeof arg === 'object') return JSON.stringify(arg);\n return String(arg);\n }).join(' ');\n setLogs(prev => [`[${type}] ${msg}`, ...prev].slice(0, 50));\n } catch (e) {\n // Ignore serialization errors\n }\n };\n\n console.log = (...args) => { originalLog(...args); addLog('LOG', args); };\n console.warn = (...args) => { originalWarn(...args); addLog('WRN', args); };\n console.error = (...args) => { originalError(...args); addLog('ERR', args); };\n\n return () => {\n console.log = originalLog;\n console.warn = originalWarn;\n console.error = originalError;\n };\n }, []);\n\n const copyLogs = useCallback(() => {\n navigator.clipboard.writeText(logs.join('\\n'))\n .then(() => alert('Logs copied to clipboard'))\n .catch(err => console.error('Failed to copy logs', err));\n }, [logs]);\n\n const handleVoiceEnd = useCallback(() => {\n setVoiceTrigger(null);\n }, []);\n\n // Custom Audio Recorder Handler\n const customRecorder = useAudioRecorder(async (blob) => {\n setVoiceTrigger(null);\n setIsTranscribing(true);\n setErrorMsg(null);\n\n if (blob.type === 'audio/simulated') {\n console.log('[TapToTalk] Handling simulated audio capture');\n await new Promise(resolve => setTimeout(resolve, 1500));\n onResult('This is a simulated transcription for development testing.');\n setIsTranscribing(false);\n return;\n }\n\n if (voiceConfig?.onAudioCapture) {\n try {\n const text = await voiceConfig.onAudioCapture(blob);\n if (text) onResult(text);\n } catch (error: any) {\n console.error('[TapToTalk] Custom transcription failed:', error);\n setErrorMsg(error.message || 'Transcription failed');\n } finally {\n setIsTranscribing(false);\n }\n } else {\n setIsTranscribing(false);\n }\n });\n\n const isListening = !!voiceTrigger || customRecorder.isRecording;\n const isActive = isListening || isTranscribing;\n\n const processingRef = useRef(false);\n\n const toggleVoice = async () => {\n if (processingRef.current) {\n console.log('[TapToTalk] toggleVoice ignored - processing');\n return;\n }\n\n // Only set processing to true if we are potentially starting an async operation\n // or if we need to debounce rapid taps.\n processingRef.current = true;\n console.log('[TapToTalk] toggleVoice called. isActive:', isActive);\n\n try {\n // Debug Trigger: 5 rapid taps logic check first\n const now = Date.now();\n if (now - tapCountRef.current.lastTap < 500) {\n tapCountRef.current.count++;\n } else {\n tapCountRef.current.count = 1;\n }\n tapCountRef.current.lastTap = now;\n\n if (tapCountRef.current.count >= 5) {\n setShowDebug(prev => !prev);\n tapCountRef.current.count = 0;\n // Force stop if we accidentally triggered reading\n if (isActive) {\n console.log('[TapToTalk] Debug trigger force-stop');\n customRecorder.stop();\n setVoiceTrigger(null);\n }\n return;\n }\n\n if (isActive) {\n if (isTranscribing && !isListening) {\n console.log('[TapToTalk] Ignoring click during transcription');\n return; // Ignore clicks during transcription (unless forced stop)\n }\n console.log('[TapToTalk] Stopping voice...');\n customRecorder.stop();\n setVoiceTrigger(null);\n } else {\n console.log('[TapToTalk] Starting voice...');\n setErrorMsg(null);\n onFocusTarget?.();\n setVoiceTrigger('click');\n try {\n await customRecorder.start();\n } catch (e: any) {\n console.error('[TapToTalk] Custom recorder failed:', e);\n setErrorMsg('Mic access denied');\n setVoiceTrigger(null);\n }\n }\n } finally {\n // Small delay to prevent double-taps being registered immediately\n setTimeout(() => {\n processingRef.current = false;\n }, 300);\n }\n };\n\n // State determination for UI\n let bgColor = accentColor;\n let label = 'Tap to Talk';\n let Icon = <MicrophoneIcon className=\"h-5 w-5\" />;\n\n if (isListening) {\n bgColor = 'bg-orange-500';\n label = 'Listening ... Tap to stop';\n Icon = <MicrophoneIcon className=\"h-5 w-5 animate-pulse\" />;\n } else if (isTranscribing) {\n bgColor = 'bg-indigo-600';\n label = 'Transcribing ...';\n Icon = (\n <svg className=\"animate-spin h-5 w-5 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n );\n }\n\n return (\n <div className=\"flex flex-col w-full relative\">\n {/* Debug Overlay */}\n {showDebug && (\n <div className=\"absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto\">\n <div className=\"flex justify-between items-center bg-gray-800 p-1 mb-1\">\n <span>Debug Logs</span>\n <div className=\"flex gap-2\">\n <button onClick={(e) => { e.stopPropagation(); copyLogs(); }} className=\"text-white hover:text-blue-400\" title=\"Copy Logs\">\n <Square2StackIcon className=\"w-4 h-4\" />\n </button>\n <button onClick={(e) => { e.stopPropagation(); copyLogs(); setShowDebug(false); }} className=\"text-white hover:text-red-400\" title=\"Copy & Close\">\n <XMarkIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n {logs.map((log, i) => (\n <div key={i} className=\"mb-0.5 border-b border-gray-700/50 pb-0.5 break-all\">\n {log}\n </div>\n ))}\n {logs.length === 0 && <div>No logs yet...</div>}\n </div>\n )}\n <button\n onClick={toggleVoice}\n disabled={disabled || (isTranscribing && !isListening)}\n className={`flex items-center justify-center gap-3 px-6 py-3 rounded-xl transition-all duration-300 w-full font-medium shadow-md active:scale-[0.98]\n ${bgColor} text-white\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}\n ${className}`}\n title={label}\n >\n <div className=\"flex items-center justify-center shrink-0\">\n {Icon}\n </div>\n <span className=\"truncate\">{label}</span>\n {errorMsg && (\n <span className=\"text-[10px] bg-white/20 px-1.5 py-0.5 rounded text-red-100 animate-in fade-in slide-in-from-right-1\">\n {errorMsg}\n </span>\n )}\n </button>\n </div>\n );\n};\n","'use client';\n\nimport React, { useEffect, useRef } from 'react';\nimport { ChatMessage, ChatTask } from '../types/chat';\nimport InteractiveMessageHandler from './interactive/InteractiveMessageHandler';\nimport { InformationCircleIcon } from '@heroicons/react/24/outline';\nimport { MessageBubble } from './MessageBubble';\n\n// Define the props for the ChatMessageList component\ninterface ChatMessageListProps {\n chatHistory: ChatMessage[];\n isProcessing: boolean;\n processingHint: string;\n currentTask: ChatTask | null;\n getContextExample: () => string;\n onInteractiveResponse?: (messageId: string | number, response: any) => void;\n}\n\n/**\n * ChatMessageList component displays the chat messages and handles scrolling\n * Features:\n * - Displays user and system messages with different styling\n * - Shows a typing indicator when the system is processing\n * - Displays a welcome message when the chat is empty\n * - Auto-scrolls to the bottom when new messages arrive\n * - Handles interactive messages with different UI components\n */\nexport const ChatMessageList: React.FC<ChatMessageListProps> = ({\n chatHistory,\n isProcessing,\n processingHint,\n currentTask,\n getContextExample,\n onInteractiveResponse\n}) => {\n // Reference to the chat container for auto-scrolling\n const chatContainerRef = useRef<HTMLDivElement>(null);\n // Reference to the last message for scrolling into view\n const lastMessageRef = useRef<HTMLDivElement>(null);\n // Reference to the processing indicator\n const processingIndicatorRef = useRef<HTMLDivElement>(null);\n\n // Scroll to the bottom when chat history or processing state changes\n useEffect(() => {\n // If there's a processing indicator, scroll to it\n if (isProcessing && processingIndicatorRef.current) {\n processingIndicatorRef.current.scrollIntoView({ behavior: 'smooth' });\n return;\n }\n\n // If there's a last message, scroll to it\n if (lastMessageRef.current) {\n lastMessageRef.current.scrollIntoView({ behavior: 'smooth' });\n } else if (chatContainerRef.current) {\n // Fallback to scrolling the container\n chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;\n }\n }, [chatHistory, isProcessing]);\n\n // Handle interactive message responses\n const handleInteractiveResponse = (messageId: string | number, response: any) => {\n if (onInteractiveResponse) {\n onInteractiveResponse(messageId, response);\n }\n };\n\n return (\n <div\n ref={chatContainerRef}\n className=\"flex-1 overflow-y-auto p-4 space-y-8 bg-gray-50\"\n >\n {/* Welcome message when chat is empty */}\n {chatHistory.length === 0 && !isProcessing && (\n <div className=\"text-center py-8\">\n <h3 className=\"text-lg font-medium text-gray-700 mb-2\">How can I help you today?</h3>\n <p className=\"text-sm text-gray-500 mb-4\">\n Try asking me something like {getContextExample()}\n </p>\n </div>\n )}\n\n {/* Display chat messages */}\n {chatHistory.map((message, index) => {\n // Determine if this is the last message\n const isLastMessage = index === chatHistory.length - 1;\n const isUser = message.role === 'user';\n const isError = message.role === 'error';\n\n return (\n <div\n key={message.id || `message-${index}`}\n ref={isLastMessage ? lastMessageRef : undefined}\n className={`flex flex-col w-full ${isUser ? 'items-end' : 'items-start'}`}\n >\n {/* Timestamp display */}\n <div className=\"text-xs text-gray-400 mb-1 px-1\">\n {message.timestamp\n ? `${isUser ? 'Sent' : 'Received'} at ${new Date(message.timestamp).toLocaleString()}`\n : ''}\n </div>\n\n {/* Message Content */}\n <div className=\"w-full\">\n {message.interactive && message.interactiveData ? (\n <div className={`max-w-[85%] ${isUser ? 'ml-auto' : 'mr-auto'}`}>\n <InteractiveMessageHandler\n message={message.interactiveData}\n onResponse={(response: any) => {\n const messageId = message.id || `interactive-${index}-${Date.now()}`;\n message.responseValue = response;\n handleInteractiveResponse(messageId, response);\n }}\n isResponseSubmitted={!!message.isResponseSubmitted}\n parentMessage={message}\n />\n </div>\n ) : (\n <MessageBubble\n message={message}\n isUser={isUser}\n />\n )}\n </div>\n\n {isUser && message.interactive && (\n <div className=\"flex items-center mt-1 space-x-1 text-xs text-gray-500 italic\">\n <InformationCircleIcon className=\"h-3 w-3 text-blue-400\" />\n <span>\n {message.request === 'form' && 'Response to form submission'}\n {message.request === 'select' && 'Response to selection prompt'}\n {message.request === 'confirm' && 'Response to confirmation prompt'}\n </span>\n </div>\n )}\n </div>\n );\n })}\n\n {/* Show typing indicator when processing */}\n {isProcessing && (\n <div\n ref={processingIndicatorRef}\n className=\"flex justify-start my-4\"\n >\n <div className=\"bg-white text-gray-800 border border-gray-200 rounded-lg px-4 py-2 max-w-[85%]\">\n <div className=\"flex items-center\">\n <span className=\"text-sm\">{processingHint}</span>\n <span className=\"ml-2 flex space-x-1\">\n <span className=\"h-2 w-2 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '0ms' }}></span>\n <span className=\"h-2 w-2 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '150ms' }}></span>\n <span className=\"h-2 w-2 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '300ms' }}></span>\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Show task progress if available */}\n {currentTask && !currentTask.complete && (\n <div className=\"mt-4 bg-blue-50 border border-blue-100 rounded-lg p-3\">\n <div className=\"text-sm text-blue-800 mb-1\">\n Task in progress: Step {currentTask.currentStep} of {currentTask.steps}\n </div>\n <div className=\"w-full bg-blue-200 rounded-full h-2\">\n <div\n className=\"bg-blue-500 h-2 rounded-full\"\n style={{ width: `${(currentTask.currentStep / currentTask.steps) * 100}%` }}\n ></div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default ChatMessageList;\n","'use client';\n\nimport React, { useState } from 'react';\nimport { ConfirmInteractionParams } from '../../types/interactive';\n\ninterface ConfirmInteractionProps {\n parameters: Record<string, any>;\n onResponse: (response: boolean) => void;\n isResponseSubmitted: boolean;\n}\n\n/**\n * Component for handling confirm (yes/no) interactions\n */\nconst ConfirmInteraction: React.FC<ConfirmInteractionProps> = ({\n parameters,\n onResponse,\n isResponseSubmitted\n}) => {\n const [selectedOption, setSelectedOption] = useState<string | null>(null);\n const params = parameters as ConfirmInteractionParams;\n\n // Extract parameters\n const { yesPrompt, noPrompt } = params;\n\n console.log('[ConfirmInteraction] Parameters:', params);\n\n const handleOptionClick = (value: boolean, buttonText: string) => {\n if (isResponseSubmitted) return;\n\n // Use the button text (yesPrompt/noPrompt) as the selected option\n setSelectedOption(buttonText);\n onResponse(value);\n };\n\n return (\n <div className=\"mt-2 mb-4\">\n <div className=\"flex space-x-2\">\n <button\n onClick={() => handleOptionClick(true, yesPrompt)}\n disabled={isResponseSubmitted}\n className={`px-4 py-2 rounded-md text-sm transition-colors ${isResponseSubmitted\n ? selectedOption === yesPrompt\n ? 'bg-blue-500 text-white' // Selected and submitted\n : 'bg-gray-200 text-gray-500 cursor-not-allowed' // Not selected and submitted\n : 'bg-blue-100 text-blue-700 hover:bg-blue-200'}`}\n >\n {yesPrompt}\n </button>\n <button\n onClick={() => handleOptionClick(false, noPrompt)}\n disabled={isResponseSubmitted}\n className={`px-4 py-2 rounded-md text-sm transition-colors ${isResponseSubmitted\n ? selectedOption === noPrompt\n ? 'bg-blue-500 text-white' // Selected and submitted\n : 'bg-gray-200 text-gray-500 cursor-not-allowed' // Not selected and submitted\n : 'bg-gray-100 text-gray-700 hover:bg-gray-200'}`}\n >\n {noPrompt}\n </button>\n </div>\n </div>\n );\n};\n\nexport default ConfirmInteraction;\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { SelectInteractionParams } from '../../types/interactive';\n\ninterface SelectInteractionProps {\n parameters: Record<string, any>;\n onResponse: (response: string) => void;\n isResponseSubmitted: boolean;\n message?: any;\n}\n\n/**\n * Component for handling select interactions (choosing from multiple options)\n */\nconst SelectInteraction: React.FC<SelectInteractionProps> = ({\n parameters,\n onResponse,\n isResponseSubmitted,\n message\n}) => {\n const [selectedOption, setSelectedOption] = useState<string | null>(null);\n const [customOption, setCustomOption] = useState<string | null>(null);\n const params = parameters as SelectInteractionParams;\n\n const { question, options, placeholder } = params;\n\n // Effect to check if there's a responseValue to use\n useEffect(() => {\n if (isResponseSubmitted && message?.responseValue) {\n const responseValueStr = String(message.responseValue);\n setSelectedOption(responseValueStr);\n\n // Check if it's a custom option\n if (!options.includes(responseValueStr)) {\n setCustomOption(responseValueStr);\n }\n }\n }, [isResponseSubmitted, message, options]);\n\n const handleOptionClick = (option: string) => {\n if (isResponseSubmitted) return;\n\n setSelectedOption(option);\n setCustomOption(null); // Clear any custom option when selecting a predefined one\n onResponse(option);\n };\n\n return (\n <div className=\"mt-2 mb-4\">\n <div className=\"flex flex-wrap gap-2\">\n {options.map((option, index) => (\n <button\n key={index}\n onClick={() => handleOptionClick(option)}\n disabled={isResponseSubmitted}\n className={`px-4 py-2 rounded-md text-sm transition-colors ${isResponseSubmitted\n ? selectedOption === option\n ? 'bg-blue-500 text-white' // Selected and submitted\n : 'bg-gray-200 text-gray-500 cursor-not-allowed' // Not selected and submitted\n : 'bg-blue-100 text-blue-700 hover:bg-blue-200'}`}\n >\n {option}\n </button>\n ))}\n </div>\n\n {/* Show custom option message if applicable */}\n {customOption && isResponseSubmitted && (\n <div className=\"mt-2 text-sm text-amber-600 bg-amber-50 p-2 rounded\">\n User provided custom option: <span className=\"font-semibold\">\"{customOption}\"</span>\n </div>\n )}\n </div>\n );\n};\n\nexport default SelectInteraction;\n","'use client';\n\nimport React, { useState, useEffect, useRef } from 'react';\nimport { FormInteractionParams, FormField } from '../../types/interactive';\nimport { ChevronDownIcon, ChevronUpIcon } from 'lucide-react';\n\ninterface FormInteractionProps {\n parameters: Record<string, any>;\n onResponse: (response: Record<string, any>) => void;\n isResponseSubmitted: boolean;\n submittedValues?: Record<string, any>;\n}\n\n/**\n * Component for handling form interactions (collecting structured data)\n */\nconst FormInteraction: React.FC<FormInteractionProps> = ({\n parameters,\n onResponse,\n isResponseSubmitted,\n submittedValues\n}) => {\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [formValues, setFormValues] = useState<Record<string, any>>({});\n const [isExpanded, setIsExpanded] = useState(false);\n const [parsedFields, setParsedFields] = useState<FormField[]>([]);\n const formButtonsRef = useRef<HTMLDivElement>(null);\n\n // Parse parameters to handle both array and object-based fields\n const parseParameters = () => {\n const { prompt, description, submitText = 'Submit', cancelText = 'Cancel' } = parameters;\n\n // Handle fields that might come as an array of stringified JSON\n let fieldsArray: FormField[] = [];\n\n if (parameters.fields) {\n // If fields is an array, parse each item if it's a string\n if (Array.isArray(parameters.fields)) {\n fieldsArray = parameters.fields.map(field => {\n if (typeof field === 'string') {\n try {\n const fieldData = JSON.parse(field);\n\n const name = fieldData.name;\n\n return {\n name,\n label: fieldData.label || name,\n type: fieldData.type || 'string',\n required: fieldData.required || false,\n options: fieldData.options || [],\n placeholder: fieldData.description || fieldData.label || name,\n defaultValue: fieldData.defaultValue\n } as FormField;\n } catch (error) {\n console.error(`Error parsing field:`, error);\n return null;\n }\n }\n return field;\n }).filter((field): field is FormField => field !== null);\n }\n // If fields is an object with stringified JSON values\n else if (typeof parameters.fields === 'object') {\n fieldsArray = Object.entries(parameters.fields).map(([name, fieldDataStr]) => {\n let fieldData: Record<string, any> = {};\n\n // Try to parse the stringified JSON\n try {\n if (typeof fieldDataStr === 'string') {\n fieldData = JSON.parse(fieldDataStr);\n } else {\n fieldData = fieldDataStr as Record<string, any>;\n }\n } catch (error) {\n console.error(`Error parsing field data for ${name}:`, error);\n }\n\n return {\n name,\n label: fieldData.label || name,\n type: fieldData.type || 'string',\n required: fieldData.required || false,\n options: fieldData.options || [],\n placeholder: fieldData.description || fieldData.label || name,\n defaultValue: fieldData.defaultValue\n } as FormField;\n });\n\n console.log('Field arrays: ', fieldsArray)\n }\n }\n\n return {\n title: prompt || 'Please fill out this form',\n description,\n fields: fieldsArray,\n submitText,\n cancelText\n };\n };\n\n const params = parseParameters();\n\n // Initialize form values with default values\n useEffect(() => {\n const processedParams = parseParameters();\n setParsedFields(processedParams.fields);\n\n const initialValues: Record<string, any> = {};\n processedParams.fields.forEach(field => {\n if (field.defaultValue !== undefined) {\n initialValues[field.name] = field.defaultValue;\n } else if (field.type === 'checkbox') {\n initialValues[field.name] = false;\n } else {\n initialValues[field.name] = '';\n }\n });\n setFormValues(initialValues);\n\n // Automatically open the modal when the component mounts\n if (!isResponseSubmitted) {\n setIsModalOpen(true);\n }\n }, [parameters, isResponseSubmitted]);\n\n // Effect to scroll form buttons into view when modal is opened\n useEffect(() => {\n if (isModalOpen && formButtonsRef.current) {\n setTimeout(() => {\n formButtonsRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, 100); // Small delay to ensure form is rendered\n }\n }, [isModalOpen]);\n\n const handleInputChange = (field: FormField, value: any) => {\n setFormValues(prev => ({\n ...prev,\n [field.name]: value\n }));\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onResponse(formValues);\n setIsModalOpen(false);\n };\n\n const handleCancel = () => {\n onResponse({});\n setIsModalOpen(false);\n };\n\n const renderField = (field: FormField) => {\n const { name, label, type, required, options, placeholder } = field;\n\n switch (type) {\n case 'string':\n case 'email':\n case 'number':\n case 'password':\n return (\n <div className=\"mb-4 flex items-center space-x-4\" key={name}>\n <label htmlFor={name} className=\"text-sm font-medium text-gray-700 min-w-[120px]\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n <input\n type={type === 'string' ? 'text' : type}\n id={name}\n name={name}\n value={formValues[name] || ''}\n onChange={(e) => handleInputChange(field, e.target.value)}\n placeholder={placeholder}\n required={required}\n disabled={isResponseSubmitted}\n className=\"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n );\n\n case 'textarea':\n return (\n <div className=\"mb-4 flex items-start space-x-4\" key={name}>\n <label htmlFor={name} className=\"text-sm font-medium text-gray-700 min-w-[120px] pt-2\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n <textarea\n id={name}\n name={name}\n value={formValues[name] || ''}\n onChange={(e) => handleInputChange(field, e.target.value)}\n placeholder={placeholder}\n required={required}\n disabled={isResponseSubmitted}\n rows={4}\n className=\"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n );\n\n case 'select':\n return (\n <div className=\"mb-4 flex items-center space-x-4\" key={name}>\n <label htmlFor={name} className=\"text-sm font-medium text-gray-700 min-w-[120px]\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n <select\n id={name}\n name={name}\n value={formValues[name] || ''}\n onChange={(e) => handleInputChange(field, e.target.value)}\n required={required}\n disabled={isResponseSubmitted}\n className=\"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"\" disabled>{placeholder || 'Select an option'}</option>\n {options?.map((option, index) => (\n <option key={index} value={option}>{option}</option>\n ))}\n </select>\n </div>\n );\n\n case 'checkbox':\n return (\n <div className=\"mb-4 flex items-center space-x-4\" key={name}>\n <div className=\"min-w-[120px]\" />\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id={name}\n name={name}\n checked={!!formValues[name]}\n onChange={(e) => handleInputChange(field, e.target.checked)}\n required={required}\n disabled={isResponseSubmitted}\n className=\"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <label htmlFor={name} className=\"ml-2 text-sm text-gray-700\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n </div>\n </div>\n );\n\n case 'radio':\n return (\n <div className=\"mb-4 flex space-x-4\" key={name}>\n <div className=\"text-sm font-medium text-gray-700 min-w-[120px] pt-2\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </div>\n <div className=\"flex-1 space-y-2\">\n {options?.map((option, index) => (\n <div key={index} className=\"flex items-center\">\n <input\n id={`${name}-${index}`}\n name={name}\n type=\"radio\"\n value={option}\n checked={formValues[name] === option}\n onChange={() => handleInputChange(field, option)}\n required={required}\n disabled={isResponseSubmitted}\n className=\"h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500\"\n />\n <label htmlFor={`${name}-${index}`} className=\"ml-2 text-sm text-gray-700\">\n {option}\n </label>\n </div>\n ))}\n </div>\n </div>\n );\n\n default:\n return null;\n }\n };\n\n if (isResponseSubmitted) {\n // For submitted forms, show a summary of the responses\n return (\n <div className=\"mt-2 bg-gray-50 p-3 rounded-md border border-gray-200\">\n <div className=\"flex justify-between items-center cursor-pointer\" onClick={() => setIsExpanded(!isExpanded)}>\n <span className=\"font-medium text-gray-700\">{isExpanded ? 'Hide' : 'Show'} Form Responses</span>\n {isExpanded ?\n <ChevronUpIcon className=\"h-5 w-5 text-gray-500\" /> :\n <ChevronDownIcon className=\"h-5 w-5 text-gray-500\" />\n }\n </div>\n\n {isExpanded && (\n <div className=\"mt-2 space-y-2\">\n {parsedFields.map((field) => (\n <div key={field.name} className=\"flex\">\n <span className=\"text-sm font-medium text-gray-600 mr-2\">{field.label}:</span>\n <span className=\"text-sm text-gray-800\">\n {typeof submittedValues?.[field.name] === 'boolean'\n ? (submittedValues[field.name] ? 'Yes' : 'No')\n : submittedValues?.[field.name] || 'Not provided'}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n }\n\n // For new forms, show the modal\n return (\n <div className=\"mt-2\">\n {isModalOpen && (\n <div className=\"p-4\">\n <form onSubmit={handleSubmit} className=\"mt-4\">\n {parsedFields.map(field => renderField(field))}\n\n <div ref={formButtonsRef} className=\"flex justify-end mt-4 space-x-2\">\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={isResponseSubmitted}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 border border-gray-300 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {params.cancelText}\n </button>\n <button\n type=\"submit\"\n disabled={isResponseSubmitted}\n className=\"px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {params.submitText}\n </button>\n </div>\n </form>\n </div>\n )}\n </div>\n );\n};\n\nexport default FormInteraction;\n","'use client';\n\nimport React from 'react';\nimport { PresentInteractionParams } from '../../types/interactive';\n\n// Try to import ReactMarkdown, but provide a fallback if it's not available\nlet ReactMarkdown: any;\ntry {\n // Dynamic import for ReactMarkdown\n ReactMarkdown = require('react-markdown');\n} catch (error) {\n // Fallback if ReactMarkdown is not available\n ReactMarkdown = ({ children }: { children: string }) => (\n <div className=\"whitespace-pre-wrap\">{children}</div>\n );\n}\n\ninterface PresentInteractionProps {\n parameters: Record<string, any>;\n}\n\n/**\n * Component for handling present interactions (displaying information)\n */\nconst PresentInteraction: React.FC<PresentInteractionProps> = ({\n parameters\n}) => {\n const params = parameters as PresentInteractionParams;\n const { title, content, format = 'text', level = 'info' } = params;\n\n // Define styles based on level\n const getLevelStyles = () => {\n switch (level) {\n case 'error':\n return {\n container: 'bg-red-50 border-red-100',\n title: 'text-red-800',\n content: 'text-red-700'\n };\n case 'warn':\n case 'warning':\n return {\n container: 'bg-amber-50 border-amber-100',\n title: 'text-amber-800',\n content: 'text-amber-700'\n };\n case 'success':\n return {\n container: 'bg-green-50 border-green-100',\n title: 'text-green-800',\n content: 'text-green-700'\n };\n case 'info':\n default:\n return {\n container: 'bg-blue-50 border-blue-100',\n title: 'text-blue-800',\n content: 'text-blue-700'\n };\n }\n };\n\n const styles = getLevelStyles();\n\n return (\n <div className={`mt-2 mb-4 p-4 ${styles.container} border rounded-md`}>\n {title && (\n <div className={`font-medium ${styles.title} mb-2`}>{title}</div>\n )}\n <div className={`text-sm ${styles.content}`}>\n {format === 'markdown' ? (\n <ReactMarkdown className=\"prose prose-sm max-w-none\">\n {content}\n </ReactMarkdown>\n ) : format === 'html' ? (\n <div dangerouslySetInnerHTML={{ __html: content }} />\n ) : (\n <div className=\"whitespace-pre-wrap\">{content}</div>\n )}\n </div>\n </div>\n );\n};\n\nexport default PresentInteraction;\n","'use client';\n\nimport React from 'react';\nimport { InteractiveMessage } from '../../types/interactive';\nimport ConfirmInteraction from './ConfirmInteraction';\nimport SelectInteraction from './SelectInteraction';\nimport FormInteraction from './FormInteraction';\nimport PresentInteraction from './PresentInteraction';\n\ninterface InteractiveMessageHandlerProps {\n message: InteractiveMessage;\n onResponse: (response: any) => void;\n isResponseSubmitted: boolean;\n parentMessage?: any; // Add reference to the parent ChatMessage\n}\n\n/**\n * Component that handles rendering different types of interactive messages\n * based on the function type (chat, confirm, select, form, present)\n */\nconst InteractiveMessageHandler: React.FC<InteractiveMessageHandlerProps> = ({\n message,\n onResponse,\n isResponseSubmitted,\n parentMessage\n}) => {\n const { function: functionType, parameters } = message;\n\n // Extract submitted response from parent message if available\n const submittedResponse = parentMessage?.responseValue;\n\n // Render the appropriate interaction component based on the function type\n switch (functionType) {\n case 'confirm':\n return (\n <ConfirmInteraction\n parameters={parameters}\n onResponse={onResponse}\n isResponseSubmitted={isResponseSubmitted}\n />\n );\n\n case 'select':\n return (\n <SelectInteraction\n parameters={parameters}\n onResponse={onResponse}\n isResponseSubmitted={isResponseSubmitted}\n message={parentMessage}\n />\n );\n\n case 'form':\n return (\n <FormInteraction\n parameters={parameters}\n onResponse={onResponse}\n isResponseSubmitted={isResponseSubmitted}\n submittedValues={submittedResponse}\n />\n );\n\n case 'present':\n return (\n <PresentInteraction\n parameters={parameters}\n />\n );\n\n case 'chat':\n // Chat is handled by the main input form, so we don't need a special component\n return null;\n\n default:\n console.warn(`Unknown interactive function type: ${functionType}`);\n return null;\n }\n};\n\nexport default InteractiveMessageHandler;\n","'use client';\n\nimport React from 'react';\nimport { Wifi, WifiOff, RefreshCw } from 'lucide-react';\n\ninterface ConnectionStatusProps {\n connectionStatus: 'connected' | 'disconnected' | 'reconnecting';\n onReconnect: () => void;\n}\n\nexport const ConnectionStatus: React.FC<ConnectionStatusProps> = ({\n connectionStatus,\n onReconnect\n}) => {\n return (\n <div className=\"bg-amber-100 connection-status flex items-center justify-between px-4 py-1 text-xs\">\n <div className=\"text-gray-700 font-medium\">\n You are talking with your personal Content Strategist\n </div>\n {connectionStatus === 'connected' && (\n <div className=\"flex items-center text-green-600\">\n <Wifi className=\"w-3 h-3 mr-1\" />\n <span>Connected</span>\n </div>\n )}\n {connectionStatus === 'reconnecting' && (\n <div className=\"flex items-center text-amber-600\">\n <RefreshCw className=\"w-3 h-3 mr-1 animate-spin\" />\n <span>Reconnecting...</span>\n </div>\n )}\n {connectionStatus === 'disconnected' && (\n <div className=\"flex items-center gap-2\">\n <div className=\"text-red-600 flex items-center\">\n <WifiOff className=\"w-3 h-3 mr-1\" />\n <span>Disconnected</span>\n </div>\n <button\n onClick={onReconnect}\n className=\"text-blue-600 hover:text-blue-800 flex items-center\"\n >\n <RefreshCw className=\"w-3 h-3 mr-1\" />\n <span>Reconnect</span>\n </button>\n </div>\n )}\n </div>\n );\n}\n","import React from 'react';\n\ninterface SpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n color?: string;\n}\n\nexport const Spinner: React.FC<SpinnerProps> = ({\n size = 'md',\n className = '',\n color = 'text-blue-600'\n}) => {\n const sizeClasses = {\n sm: 'h-4 w-4',\n md: 'h-6 w-6',\n lg: 'h-8 w-8',\n xl: 'h-12 w-12'\n };\n\n return (\n <svg\n className={`animate-spin ${sizeClasses[size]} ${color} ${className}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n );\n};\n","/**\n * Lightweight client for sending audio to a backend transcription endpoint.\n * This keeps the API key secret on the server.\n */\n\nexport interface TranscriptionConfig {\n endpoint: string;\n language?: string;\n // No headers needed if using standard fetch or cookies\n // Add custom headers support if needed for token auth\n headers?: Record<string, string>;\n}\n\nexport interface TranscriptionResult {\n text: string;\n error?: string;\n}\n\n/**\n * Transcribe audio blob by sending it to the configured backend endpoint.\n */\nexport async function transcribeAudio(\n audioBlob: Blob,\n config: TranscriptionConfig\n): Promise<string> {\n const formData = new FormData();\n formData.append('audio', audioBlob, 'recording.webm');\n\n if (config.language) {\n formData.append('language', config.language);\n }\n\n try {\n const response = await fetch(config.endpoint, {\n method: 'POST',\n body: formData,\n headers: config.headers || {},\n credentials: 'same-origin', // Ensure cookies are sent for same-domain requests\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Transcription failed (${response.status}): ${errorText}`);\n }\n\n const data = await response.json();\n return data.text;\n } catch (error: any) {\n console.error('Transcription client error:', error);\n throw error;\n }\n}\n","import { VoiceConfig } from '../types/chat';\nimport { TranscriptionConfig, transcribeAudio } from '../services/whisper-client';\n\n/**\n * Helper to create a VoiceConfig that uses the backend Whisper transcription service.\n * \n * @param config - Configuration for the transcription endpoint\n * @param callbacks - Optional callbacks for voice events\n * @returns VoiceConfig ready to be used in ChatInputArea\n */\nexport function createWhisperVoiceConfig(\n config: TranscriptionConfig,\n callbacks?: {\n onVoiceStart?: () => void;\n onVoiceEnd?: () => void;\n }\n): VoiceConfig {\n return {\n mode: 'custom',\n onVoiceStart: callbacks?.onVoiceStart,\n onVoiceEnd: callbacks?.onVoiceEnd,\n /**\n * The core handler: takes the recorded blob and sends it to the server.\n */\n onAudioCapture: async (blob: Blob) => {\n return await transcribeAudio(blob, config);\n }\n };\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","ReactMarkdown","remarkGfm","import_jsx_runtime","import_react","import_react","import_react","import_jsx_runtime","_a","_b","_c","import_react","import_outline","import_jsx_runtime","React","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","ReactMarkdown","import_jsx_runtime","import_outline","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../../../src/ui/react/components/index.ts","../../../../src/ui/react/components/ChatBubble.tsx","../../../../src/ui/react/components/MessageBubble.tsx","../../../../src/ui/react/context/ChatConfigContext.tsx","../../../../src/ui/react/components/ChatHeader.tsx","../../../../src/ui/react/components/ChatInputArea.tsx","../../../../src/ui/react/hooks/useAudioRecorder.ts","../../../../src/ui/react/hooks/useProactiveResize.ts","../../../../src/ui/react/components/TapToTalk.tsx","../../../../src/ui/react/components/ChatMessageList.tsx","../../../../src/ui/react/components/interactive/ConfirmInteraction.tsx","../../../../src/ui/react/components/interactive/SelectInteraction.tsx","../../../../src/ui/react/components/interactive/FormInteraction.tsx","../../../../src/ui/react/components/interactive/PresentInteraction.tsx","../../../../src/ui/react/components/interactive/InteractiveMessageHandler.tsx","../../../../src/ui/react/components/ConnectionStatus.tsx","../../../../src/ui/react/components/Spinner.tsx","../../../../src/ui/react/services/whisper-client.ts","../../../../src/ui/react/utils/voice-utils.ts"],"sourcesContent":["export * from './ChatBubble';\nexport * from './MessageBubble';\nexport * from './ChatHeader';\nexport * from './ChatInputArea';\nexport * from './TapToTalk';\nexport * from './ChatMessageList';\nexport * from './ConnectionStatus';\nexport * from './Spinner';\nexport * from '../hooks/useProactiveResize';\nexport * from '../hooks/useAudioRecorder';\nexport * from '../types/chat';\nexport * from '../types/interactive';\nexport * from '../context/ChatConfigContext';\nexport * from '../services/whisper-client';\nexport * from '../utils/voice-utils';\n","'use client';\n\nimport React from 'react';\n\ninterface ChatBubbleProps {\n onClick: () => void;\n}\n\nexport function ChatBubble({ onClick }: ChatBubbleProps) {\n return (\n <button\n onClick={onClick}\n className=\"bg-blue-500 hover:bg-blue-600 text-white rounded-full w-12 h-12 flex items-center justify-center shadow-lg animate-pulse\"\n aria-label=\"Open chat assistant\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z\" />\n </svg>\n </button>\n );\n}\n","'use client';\n\nimport React from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport { SparklesIcon } from '@heroicons/react/24/solid';\nimport { ChatMessage } from '../types/chat';\nimport { useChatConfig } from '../context/ChatConfigContext';\n\nexport interface MessageBubbleProps {\n message: ChatMessage;\n isUser: boolean;\n userAvatarUrl?: string; // Optional user avatar URL\n onViewChanges?: (diff: { oldContent: string; newContent: string }) => void;\n}\n\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({\n message,\n isUser,\n userAvatarUrl,\n onViewChanges\n}) => {\n const { user } = useChatConfig();\n const finalAvatarUrl = userAvatarUrl || user?.avatarUrl;\n const isSystem = message.role === 'system';\n\n if (isSystem) {\n return (\n <div className=\"text-center my-4\">\n <span className=\"text-xs text-gray-500 italic bg-gray-100 px-3 py-1 rounded-full\">\n {message.content}\n {message.diff && onViewChanges && (\n <button\n onClick={() => onViewChanges(message.diff!)}\n className=\"ml-2 font-semibold text-blue-600 hover:underline focus:outline-none\"\n >\n View Changes\n </button>\n )}\n </span>\n </div>\n );\n }\n\n return (\n <div className={`flex items-start gap-3 my-1 ${isUser ? 'justify-end' : 'justify-start'}`}>\n {/* Assistant Avatar */}\n {!isUser && (\n <div className=\"flex-shrink-0 h-8 w-8 rounded-full bg-blue-500 flex items-center justify-center text-white\">\n <SparklesIcon className=\"h-5 w-5\" />\n </div>\n )}\n\n {/* Content Bubble */}\n <div\n className={`max-w-[85%] px-4 py-3 rounded-2xl shadow-sm overflow-hidden ${isUser\n ? 'bg-blue-500 text-white rounded-br-none'\n : 'bg-gray-100 text-gray-800 rounded-bl-none'\n }`}>\n <div className={`text-sm ${!isUser ? 'prose prose-sm max-w-none' : ''}`}>\n {isUser ? (\n <p className=\"whitespace-pre-wrap\">{message.content}</p>\n ) : (\n <ReactMarkdown\n remarkPlugins={[remarkGfm]}\n components={{\n p: ({ node, ...props }) => <p className=\"mb-2 last:mb-0\" {...props} />,\n ul: ({ node, ...props }) => <ul className=\"list-disc ml-4 mb-2\" {...props} />,\n ol: ({ node, ...props }) => <ol className=\"list-decimal ml-4 mb-2\" {...props} />,\n li: ({ node, ...props }) => <li className=\"mb-0.5\" {...props} />,\n a: ({ node, ...props }) => <a className=\"text-blue-600 hover:underline\" {...props} />,\n code: ({ node, ...props }) => <code className=\"bg-gray-200 rounded px-1 py-0.5 text-xs font-mono\" {...props} />\n }}\n >\n {message.content}\n </ReactMarkdown>\n )}\n </div>\n {message.role === 'assistant' && message.diff && onViewChanges && (\n <button\n onClick={() => onViewChanges(message.diff!)}\n className=\"mt-2 text-sm text-blue-500 hover:underline block\"\n >\n View Changes\n </button>\n )}\n {message.actionResult && message.actionResult.type === 'link' && (\n <div className=\"mt-2 pt-2 border-t border-gray-300\">\n <a\n href={message.actionResult.url}\n target={message.actionResult.target || '_blank'}\n rel=\"noopener noreferrer\"\n onClick={(e) => {\n if (message.actionResult?.target && message.actionResult.target !== '_blank') {\n e.preventDefault();\n window.open(message.actionResult.url, message.actionResult.target);\n }\n }}\n className={`inline-flex items-center gap-1 text-sm font-medium hover:underline ${isUser\n ? 'text-blue-100 hover:text-white'\n : 'text-blue-600 hover:text-blue-800'\n }`}\n >\n {message.actionResult.label}\n <svg className=\"w-3.5 h-3.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} 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 </div>\n )}\n </div>\n\n {/* User Avatar */}\n {isUser && (\n <div className=\"flex-shrink-0 h-8 w-8 rounded-full bg-gray-200 overflow-hidden flex items-center justify-center text-gray-500\">\n {finalAvatarUrl ? (\n <img\n className=\"h-full w-full object-cover\"\n src={finalAvatarUrl}\n alt=\"User\"\n onError={(e) => {\n // Hide image and show fallback icon if load fails involves state, \n // but for a simple component we can just hide it or let the parent handle it.\n // For now, let's just render the icon if no url, \n // preventing the broken image icon requires state or a different approach (like standard Radix Avatar).\n // A simple hack: set src to a transparent pixel or hide display.\n (e.target as HTMLImageElement).style.display = 'none';\n (e.target as HTMLImageElement).parentElement?.classList.remove('bg-gray-200'); // Clean up?\n // Actually, better to just render the fallback SVG behind it?\n // Let's try separate conditional structure.\n }}\n />\n ) : (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\" className=\"w-5 h-5\">\n <path fillRule=\"evenodd\" d=\"M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z\" clipRule=\"evenodd\" />\n </svg>\n )}\n </div>\n )}\n </div>\n );\n};\n","import React, { createContext, useContext, ReactNode } from 'react';\nimport { VoiceConfig } from '../types/chat';\n\nexport interface ChatConfig {\n user?: {\n avatarUrl?: string;\n name?: string;\n };\n voice?: {\n enabled: boolean;\n config?: VoiceConfig;\n };\n}\n\nconst ChatConfigContext = createContext<ChatConfig>({});\n\nexport const ChatConfigProvider: React.FC<{\n config: ChatConfig;\n children: ReactNode;\n}> = ({ config, children }) => {\n return (\n <ChatConfigContext.Provider value={config}>\n {children}\n </ChatConfigContext.Provider>\n );\n};\n\nexport const useChatConfig = () => useContext(ChatConfigContext);\n","'use client';\n\nimport React from 'react';\nimport { ChatTask } from '../types/chat';\n\ninterface ChatHeaderProps {\n contextTitle: string;\n currentTask: ChatTask | null;\n onClose: () => void;\n}\n\nexport function ChatHeader({\n contextTitle,\n currentTask,\n onClose\n}: ChatHeaderProps) {\n return (\n <div className=\"bg-blue-500 text-white px-4 py-4 flex justify-between items-center\">\n <h3 className=\"font-medium text-lg\">\n {currentTask\n ? `DoveText Virtual Assistant (${currentTask.currentStep}/${currentTask.steps})`\n : `DoveText Virtual Assistant (${contextTitle})`}\n </h3>\n <button\n onClick={onClose}\n className=\"bg-blue-600 hover:bg-blue-700 text-white rounded-full p-1.5 flex items-center justify-center transition-colors cursor-pointer\"\n aria-label=\"Close chat\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clipRule=\"evenodd\" />\n </svg>\n </button>\n </div>\n );\n}\n","'use client';\n\nimport React, { useState, useRef, FormEvent, useImperativeHandle, forwardRef, useEffect, useCallback, useLayoutEffect } from 'react';\nimport { MicrophoneIcon, StopIcon, PaperAirplaneIcon, XMarkIcon, Square2StackIcon } from '@heroicons/react/24/outline';\nimport { ChatMessage, ChatTask, VoiceConfig } from '../types/chat';\nimport { InteractiveFunction } from '../types/interactive';\nimport { useAudioRecorder } from '../hooks/useAudioRecorder';\nimport { useProactiveResize } from '../hooks/useProactiveResize';\nimport { useChatConfig } from '../context/ChatConfigContext';\n\n// VoiceConfig imported from types/chat\n\ninterface ChatInputAreaProps {\n onSubmit: (message: string) => void;\n isSending: boolean;\n showInputForm: boolean;\n currentTask: ChatTask | null;\n lastInteractiveMessage?: ChatMessage | null;\n voiceConfig?: VoiceConfig;\n onStop?: () => void;\n hintText?: string;\n placeholder?: string;\n // Controlled props\n value?: string;\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n defaultInputMode?: 'text' | 'voice'; // Deprecated but kept for compatibility\n}\n\n// Define the handle type for the forwarded ref\nexport interface ChatInputAreaHandle {\n focus: () => void;\n setValue: (value: string) => void;\n}\n\nexport const ChatInputArea = forwardRef<ChatInputAreaHandle, ChatInputAreaProps>(({\n onSubmit,\n isSending,\n showInputForm,\n currentTask,\n lastInteractiveMessage,\n voiceConfig: propVoiceConfig, // Rename to distinguish from context\n onStop,\n hintText,\n placeholder,\n value,\n onChange,\n defaultInputMode = 'text'\n}, ref) => {\n const [internalMessage, setInternalMessage] = useState('');\n const [voiceTrigger, setVoiceTrigger] = useState<'click' | 'space' | null>(null);\n const [isTranscribing, setIsTranscribing] = useState(false);\n const [voiceError, setVoiceError] = useState<string | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n // Debug Mode State\n const [showDebug, setShowDebug] = useState(false);\n const [logs, setLogs] = useState<string[]>([]);\n const tapCountRef = useRef<{ count: number, lastTap: number }>({ count: 0, lastTap: 0 });\n\n // Console Interceptor for Debug Mode\n useEffect(() => {\n const originalLog = console.log;\n const originalWarn = console.warn;\n const originalError = console.error;\n\n const addLog = (type: string, args: any[]) => {\n // Only keep logs if we are potentially debugging, to save memory? \n // Or just keep last 50 always. Let's keep last 50.\n try {\n const msg = args.map(arg => {\n if (arg instanceof Error) return `${arg.name}: ${arg.message}`;\n if (typeof arg === 'object') return JSON.stringify(arg);\n return String(arg);\n }).join(' ');\n setLogs(prev => [`[${type}] ${msg}`, ...prev].slice(0, 50));\n } catch (e) {\n // Ignore serialization errors\n }\n };\n\n console.log = (...args) => { originalLog(...args); addLog('LOG', args); };\n console.warn = (...args) => { originalWarn(...args); addLog('WRN', args); };\n console.error = (...args) => { originalError(...args); addLog('ERR', args); };\n\n return () => {\n console.log = originalLog;\n console.warn = originalWarn;\n console.error = originalError;\n };\n }, []);\n\n const copyLogs = useCallback(() => {\n navigator.clipboard.writeText(logs.join('\\n'))\n .then(() => alert('Logs copied to clipboard'))\n .catch(err => console.error('Failed to copy logs', err));\n }, [logs]);\n // The left button toggles recording, but input is always text.\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const measurementRef = useRef<HTMLSpanElement>(null);\n const pendingSelectionRef = useRef<{ start: number, end: number } | null>(null);\n\n // Determine if controlled or uncontrolled\n const isControlled = value !== undefined;\n const message = isControlled ? value : internalMessage;\n\n // Use refs to access latest state in stable callbacks\n const messageRef = useRef(message);\n messageRef.current = message;\n\n // Use useLayoutEffect to apply selection before browser paint\n useLayoutEffect(() => {\n if (pendingSelectionRef.current && textareaRef.current) {\n const { start, end } = pendingSelectionRef.current;\n textareaRef.current.focus();\n textareaRef.current.setSelectionRange(start, end);\n pendingSelectionRef.current = null;\n }\n }, [message]);\n\n const onChangeRef = useRef(onChange);\n useEffect(() => {\n onChangeRef.current = onChange;\n }, [onChange]);\n\n // Get global config\n const { voice: globalVoice } = useChatConfig();\n\n // Determine effective voice config\n const isVoiceEnabled = globalVoice?.enabled ?? (!!propVoiceConfig);\n const voiceConfig = isVoiceEnabled ? (propVoiceConfig || globalVoice?.config) : undefined;\n\n const voiceConfigRef = useRef(voiceConfig);\n useEffect(() => {\n voiceConfigRef.current = voiceConfig;\n }, [voiceConfig]);\n\n const triggerChange = useCallback((newValue: string) => {\n setVoiceError(null); // Clear any errors when content changes\n if (isControlled && onChangeRef.current) {\n const syntheticEvent = {\n target: { value: newValue },\n currentTarget: { value: newValue }\n } as React.ChangeEvent<HTMLTextAreaElement>;\n onChangeRef.current(syntheticEvent);\n } else {\n setInternalMessage(newValue);\n }\n }, [isControlled]);\n\n // Apply auto-resize\n const isInputDisabled = currentTask?.complete ||\n (lastInteractiveMessage?.interactive &&\n ((lastInteractiveMessage?.interactiveData?.function === 'form' && !lastInteractiveMessage?.isResponseSubmitted) ||\n (lastInteractiveMessage?.interactiveData?.function === 'confirm' && !lastInteractiveMessage?.isResponseSubmitted)));\n\n useProactiveResize(textareaRef, measurementRef, message, isInputDisabled || !!voiceTrigger);\n\n // Helper to insert text at cursor position\n const insertTextAtCursor = useCallback((text: string) => {\n const textarea = textareaRef.current;\n const currentVal = messageRef.current || '';\n\n if (!textarea) {\n triggerChange(currentVal + (currentVal ? ' ' : '') + text);\n return;\n }\n\n const start = textarea.selectionStart;\n const end = textarea.selectionEnd;\n\n const before = currentVal.substring(0, start);\n const after = currentVal.substring(end);\n\n // Add padding space if needed (e.g. not at start and previous char is not space)\n const prefix = (start > 0 && !/\\s$/.test(before)) ? ' ' : '';\n\n const newText = before + prefix + text + after;\n\n // Calculate and store pending selection so it can be applied after render\n const selectionStart = start + prefix.length;\n const selectionEnd = selectionStart + text.length;\n pendingSelectionRef.current = { start: selectionStart, end: selectionEnd };\n\n triggerChange(newText);\n }, [triggerChange]);\n\n // Stable Voice Callbacks\n const handleVoiceResult = useCallback((text: string, isFinal: boolean) => {\n if (isFinal) {\n insertTextAtCursor(text);\n }\n }, [insertTextAtCursor]);\n\n const handleVoiceEnd = useCallback(() => {\n setVoiceTrigger(null);\n voiceConfigRef.current?.onVoiceEnd?.();\n }, []);\n\n const customRecorder = useAudioRecorder(async (blob) => {\n setVoiceTrigger(null);\n setIsTranscribing(true);\n setVoiceError(null);\n voiceConfigRef.current?.onVoiceEnd?.();\n\n if (blob.type === 'audio/simulated') {\n console.log('[ChatInputArea] Handling simulated audio capture');\n // Mock delay for simulation\n await new Promise(resolve => setTimeout(resolve, 1500));\n insertTextAtCursor('This is a simulated transcription for development testing.');\n setIsTranscribing(false);\n return;\n }\n\n if (voiceConfigRef.current?.onAudioCapture) {\n try {\n const text = await voiceConfigRef.current.onAudioCapture(blob);\n if (text) insertTextAtCursor(text);\n } catch (e: any) {\n console.error('[ChatInputArea] Audio capture failed', e);\n setVoiceError(e.message || 'Transcription failed');\n } finally {\n setIsTranscribing(false);\n }\n } else {\n setIsTranscribing(false);\n }\n });\n\n // Expose the focus and setValue method\n useImperativeHandle(ref, () => ({\n focus: () => {\n textareaRef.current?.focus();\n },\n setValue: (newValue: string) => {\n triggerChange(newValue);\n }\n }));\n\n const handleSubmit = (e?: FormEvent) => {\n if (e) e.preventDefault();\n\n if (!message.trim()) {\n setTimeout(() => textareaRef.current?.focus(), 0);\n return;\n }\n\n const currentMessage = message;\n triggerChange(''); // Clear input\n setTimeout(() => textareaRef.current?.focus(), 0);\n onSubmit(currentMessage);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n const startRecording = async (trigger: 'click' | 'space') => {\n if (voiceTrigger || isTranscribing) return;\n setVoiceTrigger(trigger);\n setVoiceError(null);\n voiceConfig?.onVoiceStart?.();\n\n try {\n await customRecorder.start();\n } catch (e: any) {\n console.error('[ChatInputArea] Failed to start recorder:', e);\n setVoiceError('Mic access denied');\n setVoiceTrigger(null);\n }\n\n // Re-focus textarea to preserve selection visibility\n setTimeout(() => textareaRef.current?.focus(), 0);\n };\n\n const stopRecording = () => {\n if (!voiceTrigger) return;\n customRecorder.stop();\n };\n\n // Determine placeholder text\n const getPlaceholder = () => {\n if (placeholder) return placeholder;\n if (voiceTrigger) return 'Listening...';\n if (currentTask?.complete) return 'Task completed!';\n\n if (lastInteractiveMessage?.interactive && lastInteractiveMessage?.interactiveData && !lastInteractiveMessage?.isResponseSubmitted) {\n const interactiveType = lastInteractiveMessage.interactiveData.function as InteractiveFunction;\n switch (interactiveType) {\n case 'chat': return 'Type your response...';\n case 'confirm': return 'Select Yes or No, or type your response...';\n case 'select': return 'Choose an option or type your response...';\n case 'form': return 'Fill out the form...';\n default: return 'Type your response...';\n }\n }\n return currentTask ? 'Continue your conversation...' : 'Ask me anything...';\n };\n\n const inputHint = (!isInputDisabled && !lastInteractiveMessage?.interactive) ? null :\n (lastInteractiveMessage?.interactiveData?.function === 'form' ? 'Please provide information by completing above form' : null);\n\n if (!showInputForm) {\n return null;\n }\n\n return (\n <div className=\"flex flex-col w-full relative\">\n {/* Debug Overlay */}\n {showDebug && (\n <div className=\"absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto\">\n <div className=\"flex justify-between items-center bg-gray-800 p-1 mb-1\">\n <span>Debug Logs</span>\n <div className=\"flex gap-2\">\n <button onClick={copyLogs} className=\"text-white hover:text-blue-400\" title=\"Copy Logs\">\n <Square2StackIcon className=\"w-4 h-4\" />\n </button>\n <button onClick={() => { copyLogs(); setShowDebug(false); }} className=\"text-white hover:text-red-400\" title=\"Copy & Close\">\n <XMarkIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n {logs.map((log, i) => (\n <div key={i} className=\"mb-0.5 border-b border-gray-700/50 pb-0.5 break-all\">\n {log}\n </div>\n ))}\n {logs.length === 0 && <div>No logs yet...</div>}\n </div>\n )}\n\n <div className=\"flex items-center gap-2\">\n {/* Voice Toggle Button (Replacing the Mode Switch) */}\n {voiceConfig && (\n <button\n type=\"button\"\n onClick={() => {\n // Debug Trigger: 5 rapid taps\n const now = Date.now();\n if (now - tapCountRef.current.lastTap < 500) {\n tapCountRef.current.count++;\n } else {\n tapCountRef.current.count = 1;\n }\n tapCountRef.current.lastTap = now;\n\n if (tapCountRef.current.count >= 5) {\n setShowDebug(prev => !prev);\n tapCountRef.current.count = 0;\n // Force stop recording if we accidentally triggered it while tapping\n stopRecording();\n return;\n }\n\n if (voiceTrigger) {\n stopRecording();\n } else if (!isTranscribing) {\n startRecording('click');\n }\n }}\n className={`mb-1 p-2 rounded-full transition-all duration-300 flex-shrink-0 border ${isTranscribing\n ? 'text-white border-indigo-500 bg-indigo-600 scale-110 shadow-lg'\n : voiceTrigger\n ? 'text-white border-orange-400 bg-orange-500 scale-110 shadow-lg'\n : 'text-gray-500 border-gray-300 bg-white hover:text-gray-700 hover:bg-gray-100'\n } ${voiceTrigger ? 'animate-pulse' : ''} ${isTranscribing ? 'cursor-wait' : ''}`}\n disabled={isTranscribing}\n title={isTranscribing ? \"Transcribing...\" : voiceTrigger ? \"Stop Recording\" : \"Start Voice Input\"}\n >\n {isTranscribing ? (\n <div className=\"animate-spin w-5 h-5 flex items-center justify-center\">\n <svg className=\"w-5 h-5 text-white\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" fill=\"none\" />\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n </div>\n ) : (\n <MicrophoneIcon className=\"w-5 h-5\" />\n )}\n </button>\n )}\n\n {/* Main Input Area */}\n <div\n tabIndex={-1}\n className={`flex-1 flex items-center border border-gray-300 rounded-lg overflow-hidden outline-none bg-white min-h-[42px] mb-1 transition-all ${voiceTrigger ? 'ring-2 ring-orange-100 border-orange-300' : 'focus-within:ring-2 focus-within:ring-blue-500 focus-within:border-blue-500'\n }`}\n >\n {/* Text Input (Always Visible) */}\n <span\n ref={measurementRef}\n className=\"absolute invisible whitespace-pre-wrap p-0 m-0 text-gray-700 leading-6\"\n style={{ fontSize: '1rem' }}\n />\n <textarea\n ref={textareaRef}\n value={message}\n onChange={(e) => {\n if (isControlled && onChange) {\n onChange(e);\n } else {\n setInternalMessage(e.target.value);\n }\n }}\n onKeyDown={handleKeyDown}\n onFocus={() => {\n setIsFocused(true);\n setVoiceError(null); // Clear error on focus\n }}\n onBlur={() => setIsFocused(false)}\n placeholder={getPlaceholder()}\n disabled={isInputDisabled}\n readOnly={!!voiceTrigger || isTranscribing}\n rows={1}\n className={`flex-grow px-4 py-2 outline-none text-gray-700 placeholder-gray-500 resize-none leading-6 w-full ${isInputDisabled ? 'bg-gray-100 cursor-not-allowed' : 'bg-transparent'\n } ${voiceTrigger || isTranscribing ? 'cursor-default' : ''}`}\n />\n\n {/* Send / Stop Button */}\n <div className=\"relative mx-2 flex-shrink-0\">\n {/* Spinner Overlay */}\n {isSending && (\n <div className=\"absolute -inset-1\">\n <svg\n className=\"animate-spin h-full w-full text-blue-500 opacity-75\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n ></circle>\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={(e) => {\n if (isSending && onStop) {\n e.preventDefault();\n onStop();\n } else {\n handleSubmit();\n }\n }}\n disabled={currentTask?.complete || (isSending && !onStop) || isInputDisabled}\n className={`relative z-10 text-white rounded-full p-2 transition-colors duration-200 disabled:bg-gray-400 disabled:cursor-not-allowed ${isSending && onStop\n ? 'bg-red-500 hover:bg-red-600'\n : 'bg-blue-600 hover:bg-blue-700'\n }`}\n title={isSending && onStop ? \"Stop generating\" : \"Send message\"}\n >\n {isSending ? (\n onStop ? <StopIcon className=\"h-5 w-5\" /> : <div className=\"w-5 h-5\" /> // Spinner handles the visual\n ) : (\n <PaperAirplaneIcon className=\"h-5 w-5\" />\n )}\n </button>\n </div>\n </div>\n </div>\n\n {/* Helper Hints */}\n {inputHint && (\n <div className=\"text-sm text-red-500 bg-red-50 py-1 px-4 rounded-lg mt-1\">\n {inputHint}\n </div>\n )}\n\n {/* Dynamic Interaction Hint */}\n <div className=\"ml-[46px] mb-2 mt-0.5 min-h-[0.75rem]\" style={{ marginLeft: '48px' }}>\n <p className={`text-[10px] leading-tight transition-all duration-200 ${voiceError\n ? 'text-red-500'\n : isTranscribing\n ? 'text-indigo-600 font-bold'\n : voiceTrigger\n ? 'text-orange-600 font-medium'\n : 'text-gray-400'\n }`}>\n {voiceError ? (\n <span className=\"flex items-center gap-1 font-semibold italic\">\n Error: {voiceError}\n </span>\n ) : isTranscribing ? (\n 'Transcribing... please wait'\n ) : voiceTrigger ? (\n 'Transcribing, please wait...'\n ) : voiceTrigger ? (\n 'Listening... tap mic icon again to stop'\n ) : (\n hintText || (voiceConfig ? 'Type in text or tap mic icon to talk' : 'Type your message...')\n )}\n </p>\n </div>\n </div>\n );\n});\n\nChatInputArea.displayName = 'ChatInputArea';\n","import { useState, useRef, useCallback } from 'react';\n\nexport interface AudioRecorderHook {\n isRecording: boolean;\n isSimulated: boolean;\n start: () => Promise<void>;\n stop: () => void;\n blob: Blob | null;\n error: string | null;\n}\n\nexport const useAudioRecorder = (\n onStop?: (blob: Blob) => void\n): AudioRecorderHook => {\n const [isRecording, setIsRecording] = useState(false);\n const [isSimulated, setIsSimulated] = useState(false);\n const [blob, setBlob] = useState<Blob | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const chunksRef = useRef<Blob[]>([]);\n\n const start = useCallback(async () => {\n\n try {\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n // Dev mode fallback\n if (process.env.NODE_ENV === 'development') {\n console.warn('[useAudioRecorder] MediaDevices not available. Entering simulation mode...');\n setIsRecording(true);\n setIsSimulated(true);\n setError(null);\n return;\n }\n throw new Error('Media devices not available. Ensure you are using HTTPS or localhost.');\n }\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: {\n noiseSuppression: true,\n echoCancellation: true\n }\n });\n\n const mediaRecorder = new MediaRecorder(stream);\n\n mediaRecorderRef.current = mediaRecorder;\n chunksRef.current = [];\n\n mediaRecorder.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunksRef.current.push(e.data);\n }\n };\n\n mediaRecorder.onstop = () => {\n const audioBlob = new Blob(chunksRef.current, { type: 'audio/webm' });\n setBlob(audioBlob);\n setIsRecording(false);\n if (onStop) onStop(audioBlob);\n\n // Stop all tracks\n stream.getTracks().forEach(track => {\n track.stop();\n });\n };\n\n mediaRecorder.start();\n setIsRecording(true);\n setError(null);\n } catch (e: any) {\n console.error('Failed to start audio recording:', e);\n setError(e.message || 'Microphone access denied');\n }\n }, [onStop]);\n\n const stop = useCallback(() => {\n if (isSimulated) {\n setIsRecording(false);\n setIsSimulated(false);\n // Return a special dummy blob that the receiver can recognize as \"simulated\"\n const simulatedBlob = new Blob(['simulated speech'], { type: 'audio/simulated' });\n setBlob(simulatedBlob);\n if (onStop) onStop(simulatedBlob);\n return;\n }\n\n if (mediaRecorderRef.current && mediaRecorderRef.current.state !== 'inactive') {\n mediaRecorderRef.current.stop();\n }\n }, [isSimulated, onStop]);\n\n return {\n isRecording,\n isSimulated,\n start,\n stop,\n blob,\n error\n };\n};\n","import { RefObject, useEffect } from 'react';\n\n/**\n * A hook that proactively resizes a textarea based on the content of a hidden measurement element.\n * This avoids the flickering often seen with standard \"height: auto\" approaches by measuring\n * the content in a hidden span first, then applying the height to the textarea.\n */\nexport function useProactiveResize(\n textareaRef: RefObject<HTMLTextAreaElement>,\n measurementRef: RefObject<HTMLSpanElement>,\n value: string,\n disabled: boolean\n) {\n useEffect(() => {\n if (!textareaRef.current || !measurementRef.current) return;\n\n // Copy styles from textarea to measurement span to ensure accurate sizing\n const styles = window.getComputedStyle(textareaRef.current);\n measurementRef.current.style.width = styles.width;\n measurementRef.current.style.font = styles.font; // Shorthand for font-style, font-variant, font-weight, font-size, line-height, font-family\n measurementRef.current.style.padding = styles.padding;\n measurementRef.current.style.border = styles.border;\n measurementRef.current.style.boxSizing = styles.boxSizing;\n measurementRef.current.style.whiteSpace = 'pre-wrap'; // Important for matching textarea behavior\n measurementRef.current.style.visibility = 'hidden';\n measurementRef.current.style.position = 'absolute';\n measurementRef.current.style.pointerEvents = 'none';\n\n // Set content to measurement span\n // Append a zero-width space to ensure empty lines are counted\n measurementRef.current.textContent = value + '\\u200B';\n\n // Calculate height\n const scrollHeight = measurementRef.current.offsetHeight;\n\n // Apply height to textarea\n // We add a small buffer (e.g., 2px) to prevent scrollbars from appearing due to sub-pixel rendering differences\n // But direct assignment is usually best.\n // Also respect min-height if set in CSS (typically handled by browser, but we set style.height)\n textareaRef.current.style.height = `${scrollHeight}px`;\n\n }, [value, disabled, textareaRef, measurementRef]);\n}\n","import React, { useState, useCallback, useRef } from 'react';\nimport { MicrophoneIcon, StopIcon, XMarkIcon, Square2StackIcon } from '@heroicons/react/24/outline';\nimport { useAudioRecorder } from '../hooks/useAudioRecorder';\nimport { VoiceConfig } from '../types/chat';\nimport { useChatConfig } from '../context/ChatConfigContext';\n\ninterface TapToTalkProps {\n onResult: (text: string) => void;\n voiceConfig?: VoiceConfig;\n className?: string;\n disabled?: boolean;\n tooltip?: string;\n onFocusTarget?: () => void;\n accentColor?: string;\n}\n\nexport const TapToTalk: React.FC<TapToTalkProps> = ({\n onResult,\n voiceConfig: propVoiceConfig,\n className = '',\n disabled = false,\n tooltip = 'Tap to speak',\n onFocusTarget,\n accentColor = 'bg-emerald-600'\n}) => {\n const globalConfig = useChatConfig();\n const voiceConfig = propVoiceConfig || globalConfig.voice?.config;\n\n const [isTranscribing, setIsTranscribing] = useState(false);\n const [voiceTrigger, setVoiceTrigger] = useState<'click' | null>(null);\n const [errorMsg, setErrorMsg] = useState<string | null>(null);\n\n // Debug Mode State\n const [showDebug, setShowDebug] = useState(false);\n const [logs, setLogs] = useState<string[]>([]);\n const tapCountRef = useRef<{ count: number, lastTap: number }>({ count: 0, lastTap: 0 });\n\n // Console Interceptor for Debug Mode\n React.useEffect(() => {\n const originalLog = console.log;\n const originalWarn = console.warn;\n const originalError = console.error;\n\n const addLog = (type: string, args: any[]) => {\n try {\n const msg = args.map(arg => {\n if (arg instanceof Error) return `${arg.name}: ${arg.message}`;\n if (typeof arg === 'object') return JSON.stringify(arg);\n return String(arg);\n }).join(' ');\n setLogs(prev => [`[${type}] ${msg}`, ...prev].slice(0, 50));\n } catch (e) {\n // Ignore serialization errors\n }\n };\n\n console.log = (...args) => { originalLog(...args); addLog('LOG', args); };\n console.warn = (...args) => { originalWarn(...args); addLog('WRN', args); };\n console.error = (...args) => { originalError(...args); addLog('ERR', args); };\n\n return () => {\n console.log = originalLog;\n console.warn = originalWarn;\n console.error = originalError;\n };\n }, []);\n\n const copyLogs = useCallback(() => {\n navigator.clipboard.writeText(logs.join('\\n'))\n .then(() => alert('Logs copied to clipboard'))\n .catch(err => console.error('Failed to copy logs', err));\n }, [logs]);\n\n const handleVoiceEnd = useCallback(() => {\n setVoiceTrigger(null);\n }, []);\n\n // Custom Audio Recorder Handler\n const customRecorder = useAudioRecorder(async (blob) => {\n setVoiceTrigger(null);\n setIsTranscribing(true);\n setErrorMsg(null);\n\n if (blob.type === 'audio/simulated') {\n console.log('[TapToTalk] Handling simulated audio capture');\n await new Promise(resolve => setTimeout(resolve, 1500));\n onResult('This is a simulated transcription for development testing.');\n setIsTranscribing(false);\n return;\n }\n\n if (voiceConfig?.onAudioCapture) {\n try {\n const text = await voiceConfig.onAudioCapture(blob);\n if (text) onResult(text);\n } catch (error: any) {\n console.error('[TapToTalk] Custom transcription failed:', error);\n setErrorMsg(error.message || 'Transcription failed');\n } finally {\n setIsTranscribing(false);\n }\n } else {\n setIsTranscribing(false);\n }\n voiceConfig?.onVoiceEnd?.();\n });\n\n const isListening = !!voiceTrigger || customRecorder.isRecording;\n const isActive = isListening || isTranscribing;\n\n const processingRef = useRef(false);\n\n const toggleVoice = async () => {\n if (processingRef.current) {\n console.log('[TapToTalk] toggleVoice ignored - processing');\n return;\n }\n\n // Only set processing to true if we are potentially starting an async operation\n // or if we need to debounce rapid taps.\n processingRef.current = true;\n console.log('[TapToTalk] toggleVoice called. isActive:', isActive);\n\n try {\n // Debug Trigger: 5 rapid taps logic check first\n const now = Date.now();\n if (now - tapCountRef.current.lastTap < 500) {\n tapCountRef.current.count++;\n } else {\n tapCountRef.current.count = 1;\n }\n tapCountRef.current.lastTap = now;\n\n if (tapCountRef.current.count >= 5) {\n setShowDebug(prev => !prev);\n tapCountRef.current.count = 0;\n // Force stop if we accidentally triggered reading\n if (isActive) {\n console.log('[TapToTalk] Debug trigger force-stop');\n customRecorder.stop();\n setVoiceTrigger(null);\n }\n return;\n }\n\n if (isActive) {\n if (isTranscribing && !isListening) {\n console.log('[TapToTalk] Ignoring click during transcription');\n return; // Ignore clicks during transcription (unless forced stop)\n }\n console.log('[TapToTalk] Stopping voice...');\n customRecorder.stop();\n setVoiceTrigger(null);\n voiceConfig?.onVoiceEnd?.();\n } else {\n console.log('[TapToTalk] Starting voice...');\n setErrorMsg(null);\n onFocusTarget?.();\n setVoiceTrigger('click');\n voiceConfig?.onVoiceStart?.();\n try {\n await customRecorder.start();\n } catch (e: any) {\n console.error('[TapToTalk] Custom recorder failed:', e);\n setErrorMsg('Mic access denied');\n setVoiceTrigger(null);\n voiceConfig?.onVoiceEnd?.();\n }\n }\n } finally {\n // Small delay to prevent double-taps being registered immediately\n setTimeout(() => {\n processingRef.current = false;\n }, 300);\n }\n };\n\n // State determination for UI\n let bgColor = accentColor;\n let label = 'Tap to Talk';\n let Icon = <MicrophoneIcon className=\"h-5 w-5\" />;\n\n if (isListening) {\n bgColor = 'bg-orange-500';\n label = 'Listening ... Tap to stop';\n Icon = <MicrophoneIcon className=\"h-5 w-5 animate-pulse\" />;\n } else if (isTranscribing) {\n bgColor = 'bg-indigo-600';\n label = 'Transcribing ...';\n Icon = (\n <svg className=\"animate-spin h-5 w-5 text-white\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n );\n }\n\n return (\n <div className=\"flex flex-col w-full relative\">\n {/* Debug Overlay */}\n {showDebug && (\n <div className=\"absolute bottom-full left-0 right-0 mb-2 p-2 bg-black/80 text-green-400 text-xs font-mono h-48 overflow-y-auto rounded z-50 pointer-events-auto\">\n <div className=\"flex justify-between items-center bg-gray-800 p-1 mb-1\">\n <span>Debug Logs</span>\n <div className=\"flex gap-2\">\n <button onClick={(e) => { e.stopPropagation(); copyLogs(); }} className=\"text-white hover:text-blue-400\" title=\"Copy Logs\">\n <Square2StackIcon className=\"w-4 h-4\" />\n </button>\n <button onClick={(e) => { e.stopPropagation(); copyLogs(); setShowDebug(false); }} className=\"text-white hover:text-red-400\" title=\"Copy & Close\">\n <XMarkIcon className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n {logs.map((log, i) => (\n <div key={i} className=\"mb-0.5 border-b border-gray-700/50 pb-0.5 break-all\">\n {log}\n </div>\n ))}\n {logs.length === 0 && <div>No logs yet...</div>}\n </div>\n )}\n <button\n onClick={toggleVoice}\n disabled={disabled || (isTranscribing && !isListening)}\n className={`flex items-center justify-center gap-3 px-6 py-3 rounded-xl transition-all duration-300 w-full font-medium shadow-md active:scale-[0.98]\n ${bgColor} text-white\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}\n ${className}`}\n title={label}\n >\n <div className=\"flex items-center justify-center shrink-0\">\n {Icon}\n </div>\n <span className=\"truncate\">{label}</span>\n {errorMsg && (\n <span className=\"text-[10px] bg-white/20 px-1.5 py-0.5 rounded text-red-100 animate-in fade-in slide-in-from-right-1\">\n {errorMsg}\n </span>\n )}\n </button>\n </div>\n );\n};\n","'use client';\n\nimport React, { useEffect, useRef } from 'react';\nimport { ChatMessage, ChatTask } from '../types/chat';\nimport InteractiveMessageHandler from './interactive/InteractiveMessageHandler';\nimport { InformationCircleIcon } from '@heroicons/react/24/outline';\nimport { MessageBubble } from './MessageBubble';\n\n// Define the props for the ChatMessageList component\ninterface ChatMessageListProps {\n chatHistory: ChatMessage[];\n isProcessing: boolean;\n processingHint: string;\n currentTask: ChatTask | null;\n getContextExample: () => string;\n onInteractiveResponse?: (messageId: string | number, response: any) => void;\n}\n\n/**\n * ChatMessageList component displays the chat messages and handles scrolling\n * Features:\n * - Displays user and system messages with different styling\n * - Shows a typing indicator when the system is processing\n * - Displays a welcome message when the chat is empty\n * - Auto-scrolls to the bottom when new messages arrive\n * - Handles interactive messages with different UI components\n */\nexport const ChatMessageList: React.FC<ChatMessageListProps> = ({\n chatHistory,\n isProcessing,\n processingHint,\n currentTask,\n getContextExample,\n onInteractiveResponse\n}) => {\n // Reference to the chat container for auto-scrolling\n const chatContainerRef = useRef<HTMLDivElement>(null);\n // Reference to the last message for scrolling into view\n const lastMessageRef = useRef<HTMLDivElement>(null);\n // Reference to the processing indicator\n const processingIndicatorRef = useRef<HTMLDivElement>(null);\n\n // Scroll to the bottom when chat history or processing state changes\n useEffect(() => {\n // If there's a processing indicator, scroll to it\n if (isProcessing && processingIndicatorRef.current) {\n processingIndicatorRef.current.scrollIntoView({ behavior: 'smooth' });\n return;\n }\n\n // If there's a last message, scroll to it\n if (lastMessageRef.current) {\n lastMessageRef.current.scrollIntoView({ behavior: 'smooth' });\n } else if (chatContainerRef.current) {\n // Fallback to scrolling the container\n chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight;\n }\n }, [chatHistory, isProcessing]);\n\n // Handle interactive message responses\n const handleInteractiveResponse = (messageId: string | number, response: any) => {\n if (onInteractiveResponse) {\n onInteractiveResponse(messageId, response);\n }\n };\n\n return (\n <div\n ref={chatContainerRef}\n className=\"flex-1 overflow-y-auto p-4 space-y-8 bg-gray-50\"\n >\n {/* Welcome message when chat is empty */}\n {chatHistory.length === 0 && !isProcessing && (\n <div className=\"text-center py-8\">\n <h3 className=\"text-lg font-medium text-gray-700 mb-2\">How can I help you today?</h3>\n <p className=\"text-sm text-gray-500 mb-4\">\n Try asking me something like {getContextExample()}\n </p>\n </div>\n )}\n\n {/* Display chat messages */}\n {chatHistory.map((message, index) => {\n // Determine if this is the last message\n const isLastMessage = index === chatHistory.length - 1;\n const isUser = message.role === 'user';\n const isError = message.role === 'error';\n\n return (\n <div\n key={message.id || `message-${index}`}\n ref={isLastMessage ? lastMessageRef : undefined}\n className={`flex flex-col w-full ${isUser ? 'items-end' : 'items-start'}`}\n >\n {/* Timestamp display */}\n <div className=\"text-xs text-gray-400 mb-1 px-1\">\n {message.timestamp\n ? `${isUser ? 'Sent' : 'Received'} at ${new Date(message.timestamp).toLocaleString()}`\n : ''}\n </div>\n\n {/* Message Content */}\n <div className=\"w-full\">\n {message.interactive && message.interactiveData ? (\n <div className={`max-w-[85%] ${isUser ? 'ml-auto' : 'mr-auto'}`}>\n <InteractiveMessageHandler\n message={message.interactiveData}\n onResponse={(response: any) => {\n const messageId = message.id || `interactive-${index}-${Date.now()}`;\n message.responseValue = response;\n handleInteractiveResponse(messageId, response);\n }}\n isResponseSubmitted={!!message.isResponseSubmitted}\n parentMessage={message}\n />\n </div>\n ) : (\n <MessageBubble\n message={message}\n isUser={isUser}\n />\n )}\n </div>\n\n {isUser && message.interactive && (\n <div className=\"flex items-center mt-1 space-x-1 text-xs text-gray-500 italic\">\n <InformationCircleIcon className=\"h-3 w-3 text-blue-400\" />\n <span>\n {message.request === 'form' && 'Response to form submission'}\n {message.request === 'select' && 'Response to selection prompt'}\n {message.request === 'confirm' && 'Response to confirmation prompt'}\n </span>\n </div>\n )}\n </div>\n );\n })}\n\n {/* Show typing indicator when processing */}\n {isProcessing && (\n <div\n ref={processingIndicatorRef}\n className=\"flex justify-start my-4\"\n >\n <div className=\"bg-white text-gray-800 border border-gray-200 rounded-lg px-4 py-2 max-w-[85%]\">\n <div className=\"flex items-center\">\n <span className=\"text-sm\">{processingHint}</span>\n <span className=\"ml-2 flex space-x-1\">\n <span className=\"h-2 w-2 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '0ms' }}></span>\n <span className=\"h-2 w-2 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '150ms' }}></span>\n <span className=\"h-2 w-2 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: '300ms' }}></span>\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Show task progress if available */}\n {currentTask && !currentTask.complete && (\n <div className=\"mt-4 bg-blue-50 border border-blue-100 rounded-lg p-3\">\n <div className=\"text-sm text-blue-800 mb-1\">\n Task in progress: Step {currentTask.currentStep} of {currentTask.steps}\n </div>\n <div className=\"w-full bg-blue-200 rounded-full h-2\">\n <div\n className=\"bg-blue-500 h-2 rounded-full\"\n style={{ width: `${(currentTask.currentStep / currentTask.steps) * 100}%` }}\n ></div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default ChatMessageList;\n","'use client';\n\nimport React, { useState } from 'react';\nimport { ConfirmInteractionParams } from '../../types/interactive';\n\ninterface ConfirmInteractionProps {\n parameters: Record<string, any>;\n onResponse: (response: boolean) => void;\n isResponseSubmitted: boolean;\n}\n\n/**\n * Component for handling confirm (yes/no) interactions\n */\nconst ConfirmInteraction: React.FC<ConfirmInteractionProps> = ({\n parameters,\n onResponse,\n isResponseSubmitted\n}) => {\n const [selectedOption, setSelectedOption] = useState<string | null>(null);\n const params = parameters as ConfirmInteractionParams;\n\n // Extract parameters\n const { yesPrompt, noPrompt } = params;\n\n console.log('[ConfirmInteraction] Parameters:', params);\n\n const handleOptionClick = (value: boolean, buttonText: string) => {\n if (isResponseSubmitted) return;\n\n // Use the button text (yesPrompt/noPrompt) as the selected option\n setSelectedOption(buttonText);\n onResponse(value);\n };\n\n return (\n <div className=\"mt-2 mb-4\">\n <div className=\"flex space-x-2\">\n <button\n onClick={() => handleOptionClick(true, yesPrompt)}\n disabled={isResponseSubmitted}\n className={`px-4 py-2 rounded-md text-sm transition-colors ${isResponseSubmitted\n ? selectedOption === yesPrompt\n ? 'bg-blue-500 text-white' // Selected and submitted\n : 'bg-gray-200 text-gray-500 cursor-not-allowed' // Not selected and submitted\n : 'bg-blue-100 text-blue-700 hover:bg-blue-200'}`}\n >\n {yesPrompt}\n </button>\n <button\n onClick={() => handleOptionClick(false, noPrompt)}\n disabled={isResponseSubmitted}\n className={`px-4 py-2 rounded-md text-sm transition-colors ${isResponseSubmitted\n ? selectedOption === noPrompt\n ? 'bg-blue-500 text-white' // Selected and submitted\n : 'bg-gray-200 text-gray-500 cursor-not-allowed' // Not selected and submitted\n : 'bg-gray-100 text-gray-700 hover:bg-gray-200'}`}\n >\n {noPrompt}\n </button>\n </div>\n </div>\n );\n};\n\nexport default ConfirmInteraction;\n","'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { SelectInteractionParams } from '../../types/interactive';\n\ninterface SelectInteractionProps {\n parameters: Record<string, any>;\n onResponse: (response: string) => void;\n isResponseSubmitted: boolean;\n message?: any;\n}\n\n/**\n * Component for handling select interactions (choosing from multiple options)\n */\nconst SelectInteraction: React.FC<SelectInteractionProps> = ({\n parameters,\n onResponse,\n isResponseSubmitted,\n message\n}) => {\n const [selectedOption, setSelectedOption] = useState<string | null>(null);\n const [customOption, setCustomOption] = useState<string | null>(null);\n const params = parameters as SelectInteractionParams;\n\n const { question, options, placeholder } = params;\n\n // Effect to check if there's a responseValue to use\n useEffect(() => {\n if (isResponseSubmitted && message?.responseValue) {\n const responseValueStr = String(message.responseValue);\n setSelectedOption(responseValueStr);\n\n // Check if it's a custom option\n if (!options.includes(responseValueStr)) {\n setCustomOption(responseValueStr);\n }\n }\n }, [isResponseSubmitted, message, options]);\n\n const handleOptionClick = (option: string) => {\n if (isResponseSubmitted) return;\n\n setSelectedOption(option);\n setCustomOption(null); // Clear any custom option when selecting a predefined one\n onResponse(option);\n };\n\n return (\n <div className=\"mt-2 mb-4\">\n <div className=\"flex flex-wrap gap-2\">\n {options.map((option, index) => (\n <button\n key={index}\n onClick={() => handleOptionClick(option)}\n disabled={isResponseSubmitted}\n className={`px-4 py-2 rounded-md text-sm transition-colors ${isResponseSubmitted\n ? selectedOption === option\n ? 'bg-blue-500 text-white' // Selected and submitted\n : 'bg-gray-200 text-gray-500 cursor-not-allowed' // Not selected and submitted\n : 'bg-blue-100 text-blue-700 hover:bg-blue-200'}`}\n >\n {option}\n </button>\n ))}\n </div>\n\n {/* Show custom option message if applicable */}\n {customOption && isResponseSubmitted && (\n <div className=\"mt-2 text-sm text-amber-600 bg-amber-50 p-2 rounded\">\n User provided custom option: <span className=\"font-semibold\">\"{customOption}\"</span>\n </div>\n )}\n </div>\n );\n};\n\nexport default SelectInteraction;\n","'use client';\n\nimport React, { useState, useEffect, useRef } from 'react';\nimport { FormInteractionParams, FormField } from '../../types/interactive';\nimport { ChevronDownIcon, ChevronUpIcon } from 'lucide-react';\n\ninterface FormInteractionProps {\n parameters: Record<string, any>;\n onResponse: (response: Record<string, any>) => void;\n isResponseSubmitted: boolean;\n submittedValues?: Record<string, any>;\n}\n\n/**\n * Component for handling form interactions (collecting structured data)\n */\nconst FormInteraction: React.FC<FormInteractionProps> = ({\n parameters,\n onResponse,\n isResponseSubmitted,\n submittedValues\n}) => {\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [formValues, setFormValues] = useState<Record<string, any>>({});\n const [isExpanded, setIsExpanded] = useState(false);\n const [parsedFields, setParsedFields] = useState<FormField[]>([]);\n const formButtonsRef = useRef<HTMLDivElement>(null);\n\n // Parse parameters to handle both array and object-based fields\n const parseParameters = () => {\n const { prompt, description, submitText = 'Submit', cancelText = 'Cancel' } = parameters;\n\n // Handle fields that might come as an array of stringified JSON\n let fieldsArray: FormField[] = [];\n\n if (parameters.fields) {\n // If fields is an array, parse each item if it's a string\n if (Array.isArray(parameters.fields)) {\n fieldsArray = parameters.fields.map(field => {\n if (typeof field === 'string') {\n try {\n const fieldData = JSON.parse(field);\n\n const name = fieldData.name;\n\n return {\n name,\n label: fieldData.label || name,\n type: fieldData.type || 'string',\n required: fieldData.required || false,\n options: fieldData.options || [],\n placeholder: fieldData.description || fieldData.label || name,\n defaultValue: fieldData.defaultValue\n } as FormField;\n } catch (error) {\n console.error(`Error parsing field:`, error);\n return null;\n }\n }\n return field;\n }).filter((field): field is FormField => field !== null);\n }\n // If fields is an object with stringified JSON values\n else if (typeof parameters.fields === 'object') {\n fieldsArray = Object.entries(parameters.fields).map(([name, fieldDataStr]) => {\n let fieldData: Record<string, any> = {};\n\n // Try to parse the stringified JSON\n try {\n if (typeof fieldDataStr === 'string') {\n fieldData = JSON.parse(fieldDataStr);\n } else {\n fieldData = fieldDataStr as Record<string, any>;\n }\n } catch (error) {\n console.error(`Error parsing field data for ${name}:`, error);\n }\n\n return {\n name,\n label: fieldData.label || name,\n type: fieldData.type || 'string',\n required: fieldData.required || false,\n options: fieldData.options || [],\n placeholder: fieldData.description || fieldData.label || name,\n defaultValue: fieldData.defaultValue\n } as FormField;\n });\n\n console.log('Field arrays: ', fieldsArray)\n }\n }\n\n return {\n title: prompt || 'Please fill out this form',\n description,\n fields: fieldsArray,\n submitText,\n cancelText\n };\n };\n\n const params = parseParameters();\n\n // Initialize form values with default values\n useEffect(() => {\n const processedParams = parseParameters();\n setParsedFields(processedParams.fields);\n\n const initialValues: Record<string, any> = {};\n processedParams.fields.forEach(field => {\n if (field.defaultValue !== undefined) {\n initialValues[field.name] = field.defaultValue;\n } else if (field.type === 'checkbox') {\n initialValues[field.name] = false;\n } else {\n initialValues[field.name] = '';\n }\n });\n setFormValues(initialValues);\n\n // Automatically open the modal when the component mounts\n if (!isResponseSubmitted) {\n setIsModalOpen(true);\n }\n }, [parameters, isResponseSubmitted]);\n\n // Effect to scroll form buttons into view when modal is opened\n useEffect(() => {\n if (isModalOpen && formButtonsRef.current) {\n setTimeout(() => {\n formButtonsRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, 100); // Small delay to ensure form is rendered\n }\n }, [isModalOpen]);\n\n const handleInputChange = (field: FormField, value: any) => {\n setFormValues(prev => ({\n ...prev,\n [field.name]: value\n }));\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n onResponse(formValues);\n setIsModalOpen(false);\n };\n\n const handleCancel = () => {\n onResponse({});\n setIsModalOpen(false);\n };\n\n const renderField = (field: FormField) => {\n const { name, label, type, required, options, placeholder } = field;\n\n switch (type) {\n case 'string':\n case 'email':\n case 'number':\n case 'password':\n return (\n <div className=\"mb-4 flex items-center space-x-4\" key={name}>\n <label htmlFor={name} className=\"text-sm font-medium text-gray-700 min-w-[120px]\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n <input\n type={type === 'string' ? 'text' : type}\n id={name}\n name={name}\n value={formValues[name] || ''}\n onChange={(e) => handleInputChange(field, e.target.value)}\n placeholder={placeholder}\n required={required}\n disabled={isResponseSubmitted}\n className=\"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n );\n\n case 'textarea':\n return (\n <div className=\"mb-4 flex items-start space-x-4\" key={name}>\n <label htmlFor={name} className=\"text-sm font-medium text-gray-700 min-w-[120px] pt-2\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n <textarea\n id={name}\n name={name}\n value={formValues[name] || ''}\n onChange={(e) => handleInputChange(field, e.target.value)}\n placeholder={placeholder}\n required={required}\n disabled={isResponseSubmitted}\n rows={4}\n className=\"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n />\n </div>\n );\n\n case 'select':\n return (\n <div className=\"mb-4 flex items-center space-x-4\" key={name}>\n <label htmlFor={name} className=\"text-sm font-medium text-gray-700 min-w-[120px]\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n <select\n id={name}\n name={name}\n value={formValues[name] || ''}\n onChange={(e) => handleInputChange(field, e.target.value)}\n required={required}\n disabled={isResponseSubmitted}\n className=\"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n <option value=\"\" disabled>{placeholder || 'Select an option'}</option>\n {options?.map((option, index) => (\n <option key={index} value={option}>{option}</option>\n ))}\n </select>\n </div>\n );\n\n case 'checkbox':\n return (\n <div className=\"mb-4 flex items-center space-x-4\" key={name}>\n <div className=\"min-w-[120px]\" />\n <div className=\"flex items-center\">\n <input\n type=\"checkbox\"\n id={name}\n name={name}\n checked={!!formValues[name]}\n onChange={(e) => handleInputChange(field, e.target.checked)}\n required={required}\n disabled={isResponseSubmitted}\n className=\"h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500\"\n />\n <label htmlFor={name} className=\"ml-2 text-sm text-gray-700\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </label>\n </div>\n </div>\n );\n\n case 'radio':\n return (\n <div className=\"mb-4 flex space-x-4\" key={name}>\n <div className=\"text-sm font-medium text-gray-700 min-w-[120px] pt-2\">\n {label}{required && <span className=\"text-red-500\">*</span>}\n </div>\n <div className=\"flex-1 space-y-2\">\n {options?.map((option, index) => (\n <div key={index} className=\"flex items-center\">\n <input\n id={`${name}-${index}`}\n name={name}\n type=\"radio\"\n value={option}\n checked={formValues[name] === option}\n onChange={() => handleInputChange(field, option)}\n required={required}\n disabled={isResponseSubmitted}\n className=\"h-4 w-4 text-blue-600 border-gray-300 focus:ring-blue-500\"\n />\n <label htmlFor={`${name}-${index}`} className=\"ml-2 text-sm text-gray-700\">\n {option}\n </label>\n </div>\n ))}\n </div>\n </div>\n );\n\n default:\n return null;\n }\n };\n\n if (isResponseSubmitted) {\n // For submitted forms, show a summary of the responses\n return (\n <div className=\"mt-2 bg-gray-50 p-3 rounded-md border border-gray-200\">\n <div className=\"flex justify-between items-center cursor-pointer\" onClick={() => setIsExpanded(!isExpanded)}>\n <span className=\"font-medium text-gray-700\">{isExpanded ? 'Hide' : 'Show'} Form Responses</span>\n {isExpanded ?\n <ChevronUpIcon className=\"h-5 w-5 text-gray-500\" /> :\n <ChevronDownIcon className=\"h-5 w-5 text-gray-500\" />\n }\n </div>\n\n {isExpanded && (\n <div className=\"mt-2 space-y-2\">\n {parsedFields.map((field) => (\n <div key={field.name} className=\"flex\">\n <span className=\"text-sm font-medium text-gray-600 mr-2\">{field.label}:</span>\n <span className=\"text-sm text-gray-800\">\n {typeof submittedValues?.[field.name] === 'boolean'\n ? (submittedValues[field.name] ? 'Yes' : 'No')\n : submittedValues?.[field.name] || 'Not provided'}\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n }\n\n // For new forms, show the modal\n return (\n <div className=\"mt-2\">\n {isModalOpen && (\n <div className=\"p-4\">\n <form onSubmit={handleSubmit} className=\"mt-4\">\n {parsedFields.map(field => renderField(field))}\n\n <div ref={formButtonsRef} className=\"flex justify-end mt-4 space-x-2\">\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={isResponseSubmitted}\n className=\"px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 border border-gray-300 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {params.cancelText}\n </button>\n <button\n type=\"submit\"\n disabled={isResponseSubmitted}\n className=\"px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500\"\n >\n {params.submitText}\n </button>\n </div>\n </form>\n </div>\n )}\n </div>\n );\n};\n\nexport default FormInteraction;\n","'use client';\n\nimport React from 'react';\nimport { PresentInteractionParams } from '../../types/interactive';\n\n// Try to import ReactMarkdown, but provide a fallback if it's not available\nlet ReactMarkdown: any;\ntry {\n // Dynamic import for ReactMarkdown\n ReactMarkdown = require('react-markdown');\n} catch (error) {\n // Fallback if ReactMarkdown is not available\n ReactMarkdown = ({ children }: { children: string }) => (\n <div className=\"whitespace-pre-wrap\">{children}</div>\n );\n}\n\ninterface PresentInteractionProps {\n parameters: Record<string, any>;\n}\n\n/**\n * Component for handling present interactions (displaying information)\n */\nconst PresentInteraction: React.FC<PresentInteractionProps> = ({\n parameters\n}) => {\n const params = parameters as PresentInteractionParams;\n const { title, content, format = 'text', level = 'info' } = params;\n\n // Define styles based on level\n const getLevelStyles = () => {\n switch (level) {\n case 'error':\n return {\n container: 'bg-red-50 border-red-100',\n title: 'text-red-800',\n content: 'text-red-700'\n };\n case 'warn':\n case 'warning':\n return {\n container: 'bg-amber-50 border-amber-100',\n title: 'text-amber-800',\n content: 'text-amber-700'\n };\n case 'success':\n return {\n container: 'bg-green-50 border-green-100',\n title: 'text-green-800',\n content: 'text-green-700'\n };\n case 'info':\n default:\n return {\n container: 'bg-blue-50 border-blue-100',\n title: 'text-blue-800',\n content: 'text-blue-700'\n };\n }\n };\n\n const styles = getLevelStyles();\n\n return (\n <div className={`mt-2 mb-4 p-4 ${styles.container} border rounded-md`}>\n {title && (\n <div className={`font-medium ${styles.title} mb-2`}>{title}</div>\n )}\n <div className={`text-sm ${styles.content}`}>\n {format === 'markdown' ? (\n <ReactMarkdown className=\"prose prose-sm max-w-none\">\n {content}\n </ReactMarkdown>\n ) : format === 'html' ? (\n <div dangerouslySetInnerHTML={{ __html: content }} />\n ) : (\n <div className=\"whitespace-pre-wrap\">{content}</div>\n )}\n </div>\n </div>\n );\n};\n\nexport default PresentInteraction;\n","'use client';\n\nimport React from 'react';\nimport { InteractiveMessage } from '../../types/interactive';\nimport ConfirmInteraction from './ConfirmInteraction';\nimport SelectInteraction from './SelectInteraction';\nimport FormInteraction from './FormInteraction';\nimport PresentInteraction from './PresentInteraction';\n\ninterface InteractiveMessageHandlerProps {\n message: InteractiveMessage;\n onResponse: (response: any) => void;\n isResponseSubmitted: boolean;\n parentMessage?: any; // Add reference to the parent ChatMessage\n}\n\n/**\n * Component that handles rendering different types of interactive messages\n * based on the function type (chat, confirm, select, form, present)\n */\nconst InteractiveMessageHandler: React.FC<InteractiveMessageHandlerProps> = ({\n message,\n onResponse,\n isResponseSubmitted,\n parentMessage\n}) => {\n const { function: functionType, parameters } = message;\n\n // Extract submitted response from parent message if available\n const submittedResponse = parentMessage?.responseValue;\n\n // Render the appropriate interaction component based on the function type\n switch (functionType) {\n case 'confirm':\n return (\n <ConfirmInteraction\n parameters={parameters}\n onResponse={onResponse}\n isResponseSubmitted={isResponseSubmitted}\n />\n );\n\n case 'select':\n return (\n <SelectInteraction\n parameters={parameters}\n onResponse={onResponse}\n isResponseSubmitted={isResponseSubmitted}\n message={parentMessage}\n />\n );\n\n case 'form':\n return (\n <FormInteraction\n parameters={parameters}\n onResponse={onResponse}\n isResponseSubmitted={isResponseSubmitted}\n submittedValues={submittedResponse}\n />\n );\n\n case 'present':\n return (\n <PresentInteraction\n parameters={parameters}\n />\n );\n\n case 'chat':\n // Chat is handled by the main input form, so we don't need a special component\n return null;\n\n default:\n console.warn(`Unknown interactive function type: ${functionType}`);\n return null;\n }\n};\n\nexport default InteractiveMessageHandler;\n","'use client';\n\nimport React from 'react';\nimport { Wifi, WifiOff, RefreshCw } from 'lucide-react';\n\ninterface ConnectionStatusProps {\n connectionStatus: 'connected' | 'disconnected' | 'reconnecting';\n onReconnect: () => void;\n}\n\nexport const ConnectionStatus: React.FC<ConnectionStatusProps> = ({\n connectionStatus,\n onReconnect\n}) => {\n return (\n <div className=\"bg-amber-100 connection-status flex items-center justify-between px-4 py-1 text-xs\">\n <div className=\"text-gray-700 font-medium\">\n You are talking with your personal Content Strategist\n </div>\n {connectionStatus === 'connected' && (\n <div className=\"flex items-center text-green-600\">\n <Wifi className=\"w-3 h-3 mr-1\" />\n <span>Connected</span>\n </div>\n )}\n {connectionStatus === 'reconnecting' && (\n <div className=\"flex items-center text-amber-600\">\n <RefreshCw className=\"w-3 h-3 mr-1 animate-spin\" />\n <span>Reconnecting...</span>\n </div>\n )}\n {connectionStatus === 'disconnected' && (\n <div className=\"flex items-center gap-2\">\n <div className=\"text-red-600 flex items-center\">\n <WifiOff className=\"w-3 h-3 mr-1\" />\n <span>Disconnected</span>\n </div>\n <button\n onClick={onReconnect}\n className=\"text-blue-600 hover:text-blue-800 flex items-center\"\n >\n <RefreshCw className=\"w-3 h-3 mr-1\" />\n <span>Reconnect</span>\n </button>\n </div>\n )}\n </div>\n );\n}\n","import React from 'react';\n\ninterface SpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n color?: string;\n}\n\nexport const Spinner: React.FC<SpinnerProps> = ({\n size = 'md',\n className = '',\n color = 'text-blue-600'\n}) => {\n const sizeClasses = {\n sm: 'h-4 w-4',\n md: 'h-6 w-6',\n lg: 'h-8 w-8',\n xl: 'h-12 w-12'\n };\n\n return (\n <svg\n className={`animate-spin ${sizeClasses[size]} ${color} ${className}`}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n />\n </svg>\n );\n};\n","/**\n * Lightweight client for sending audio to a backend transcription endpoint.\n * This keeps the API key secret on the server.\n */\n\nexport interface TranscriptionConfig {\n endpoint: string;\n language?: string;\n // No headers needed if using standard fetch or cookies\n // Add custom headers support if needed for token auth\n headers?: Record<string, string>;\n}\n\nexport interface TranscriptionResult {\n text: string;\n error?: string;\n}\n\n/**\n * Transcribe audio blob by sending it to the configured backend endpoint.\n */\nexport async function transcribeAudio(\n audioBlob: Blob,\n config: TranscriptionConfig\n): Promise<string> {\n const formData = new FormData();\n formData.append('audio', audioBlob, 'recording.webm');\n\n if (config.language) {\n formData.append('language', config.language);\n }\n\n try {\n const response = await fetch(config.endpoint, {\n method: 'POST',\n body: formData,\n headers: config.headers || {},\n credentials: 'same-origin', // Ensure cookies are sent for same-domain requests\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Transcription failed (${response.status}): ${errorText}`);\n }\n\n const data = await response.json();\n return data.text;\n } catch (error: any) {\n console.error('Transcription client error:', error);\n throw error;\n }\n}\n","import { VoiceConfig } from '../types/chat';\nimport { TranscriptionConfig, transcribeAudio } from '../services/whisper-client';\n\n/**\n * Helper to create a VoiceConfig that uses the backend Whisper transcription service.\n * \n * @param config - Configuration for the transcription endpoint\n * @param callbacks - Optional callbacks for voice events\n * @returns VoiceConfig ready to be used in ChatInputArea\n */\nexport function createWhisperVoiceConfig(\n config: TranscriptionConfig,\n callbacks?: {\n onVoiceStart?: () => void;\n onVoiceEnd?: () => void;\n }\n): VoiceConfig {\n return {\n mode: 'custom',\n onVoiceStart: callbacks?.onVoiceStart,\n onVoiceEnd: callbacks?.onVoiceEnd,\n /**\n * The core handler: takes the recorded blob and sends it to the server.\n */\n onAudioCapture: async (blob: Blob) => {\n return await transcribeAudio(blob, config);\n }\n };\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","ReactMarkdown","remarkGfm","import_jsx_runtime","import_react","import_react","import_react","import_jsx_runtime","_a","_b","_c","import_react","import_outline","import_jsx_runtime","React","_a","import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","ReactMarkdown","import_jsx_runtime","import_outline","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime"]}