@mcp-b/embedded-agent 1.2.0 → 1.2.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,"file":"web-component.js","names":["GESTURE_CONFIG","dragActivationDistance","swipe","minDistance","minVelocity","velocityOnlyThreshold","const","PILL_CONTAINER_SIZES","collapsed","width","min","vw","max","height","hovered","composing","active","expanded","clampSize","config","AUTO_COLLAPSE_TIMEOUT_MS","COMPOSER_MAX_CHARS","PILL_BORDER_RADIUS","pill","rounded","inner","small","PILL_SPACING","xs","sm","md","lg","xl","PILL_MAX_HEIGHTS","tools","mobile","desktop","summary","composer","MAX_PROMPT_BUBBLES","UI_TIMING","hoverDebounce","collapseDelay","copyFeedback","KEYBOARD_VISIBILITY_THRESHOLD_PX","KEYBOARD_GAP_PX","DRAG_OPACITY","dragging","normal","FULL_SCREEN_CONFIG","maxWidth","widthPercent","heightPercent","padding","PINCH_GESTURE_CONFIG","threshold","minInitialDistance","ARIA_IDS","pillTitle","pillDescription","liveRegion","ARIA_LABELS","openAssistant","closeAssistant","endVoiceSession","dragHandle","sendMessage","voiceInput","expandFullScreen","collapseFullScreen","WEBMCP_PRODUCTION_API_BASE","MCP_MAX_RECONNECT_ATTEMPTS","MCP_BASE_RECONNECT_DELAY_MS","MCP_MAX_RECONNECT_DELAY_MS","MCP_TAB_CONNECT_DELAY_MS","AUDIO_FREQUENCY_BINS","REALTIME_DEFAULT_MODEL","REALTIME_DEFAULT_VOICE","REALTIME_DEFAULT_API_URL","AUDIO_VISUALIZATION_INTERVAL_MS","RESPONSE_REQUEST_DELAY_MS","TOOL_CALL_DISPLAY_DURATION_MS","TOOL_CALL_ERROR_DISPLAY_DURATION_MS","VOICE_ACTIONS_RETENTION_MS","VOICE_SUMMARY_RETENTION_MS","VOICE_APPROVAL_TIMEOUT_MS","VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS","VOICE_APPROVAL_KEYWORDS","approve","deny","VOICE_TOOL_RESULT_MESSAGES","handled","sessionEnded","WAVEFORM_HISTORY_SIZE","WAVEFORM_UPDATE_RATE_MS","WEBSOCKET_OPEN","DEBUG_LOGGING_ENABLED","window","__WEBMCP_DEBUG__","debugLog","component","message","data","isDebugEnabled","undefined","console","log","clsx","twMerge","ClassValue","cn","inputs","c","_c","memo","ReactMarkdown","remarkGfm","cn","FC","HTMLAttributes","Components","PillMarkdownProps","content","className","compact","ElementProps","HTMLElement","PillMarkdown","t0","$","t1","t2","t3","t4","t5","t6","t7","t8","cn_","props","t9","cn__0","props_0","t10","cn__1","props_1","t11","cn__2","props_2","t12","cn__3","props_3","t13","cn__4","props_4","t14","cn__5","props_5","cn__7","props_7","cn__8","props_8","isInline","includes","cn__9","props_9","h1","h2","h3","p","a","ul","ol","li","_temp","blockquote","code","pre","hr","_temp2","strong","_temp3","em","_temp4","components","Symbol","for","t15","t16","displayName","cn__6","props_6","cn__10","props_10","cn__11","props_11","cn__12","props_12","c","_c","useThread","AlertCircle","Check","CheckCircle2","Copy","useCallback","useMemo","useState","UI_TIMING","cn","PillMarkdown","FC","ReactNode","SummaryBlockProps","summary","isSuccess","isError","actions","QuickAction","className","isFullScreen","label","onClick","variant","SummaryBlock","t0","$","t1","undefined","copied","setCopied","t2","navigator","clipboard","writeText","setTimeout","copyFeedback","handleCopy","t3","t4","e","stopPropagation","t5","Symbol","for","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","length","map","_temp","t16","TextPart","type","text","useLatestSummary","messages","_temp2","bb0","lastAssistantMessage","reverse","find","_temp3","textParts","content","filter","_temp4","lastText","at","m","role","thread","WelcomeMessage","ThreadContent","empty","running","complete","_temp5","lastMessage","isRunning","status","action","i","e_0","humanizeToolName","name","progressive","words","replace","toLowerCase","split","length","verb","progressiveVerb","endsWith","slice","charAt","toUpperCase","join","formatArgs","args","Record","entries","Object","map","key","value","displayValue","JSON","stringify","TOOL_DENIED_MESSAGE","formatToolDenialWithReason","reason","useThread","useMemo","humanizeToolName","ToolCallMetadata","Action","id","label","toolName","status","args","result","error","startedAt","duration","sourceId","wasAborted","ToolCallPart","type","toolCallId","artifact","isError","isToolCallMetadata","a","Record","useActions","$","_c","messages","_temp","t0","bb0","length","t1","Symbol","for","actions","message","role","part","content","toolPart","isComplete","undefined","hasError","requiresAction","metadata","push","String","thread","useCurrentAction","find","_temp2","useRecentActions","limit","filter","_temp3","slice","useLastCompletedAction","completed","_temp4","at","TabClientTransport","SSEClientTransport","StreamableHTTPClientTransport","MCPSourceConfig","Transport","TransportType","createMCPTransport","config","transportType","type","targetOrigin","window","location","origin","channelId","serverUrl","URL","url","headers","Record","Accept","customHeaders","authToken","Authorization","transportOptions","requestInit","shouldFallbackToSSE","error","Error","message","includes","calculateReconnectDelay","attempt","baseDelay","maxDelay","Math","min","pow","Client","PromptListChangedNotificationSchema","ToolListChangedNotificationSchema","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","MCP_TAB_CONNECT_DELAY_MS","createMCPTransport","CallToolResult","GetPromptResult","MCPSource","MCPSourceConfig","Prompt","Resource","ResourceTemplate","ToolWithSource","Transport","ReactNode","SOURCE_LOCAL","SOURCE_REMOTE","SourceState","Omit","client","transport","resources","resourceTemplates","prompts","InflightToolCall","toolName","sourceId","abortController","AbortController","MCPToolsContextValue","tools","sources","Map","addSource","id","config","Promise","removeSource","getSource","isConnected","callTool","name","args","Record","callToolOnSource","getPrompt","MCPToolsContext","MCPToolsProviderProps","children","autoConnectLocal","onToolsChange","onPromptsChange","MCPToolsProvider","sourcesRef","inflightCallsRef","callIdCounterRef","forceUpdate","toolsList","setToolsList","promptsList","setPromptsList","abortOrphanedCalls","currentTools","currentToolNames","Set","map","t","current","forEach","call","callId","has","console","warn","abort","Error","delete","rebuildTools","allTools","source","tool","push","_sourceId","rebuildPrompts","allPrompts","prompt","getPublicSource","state","error","sourceState","set","version","connect","listTools","listPrompts","err","setNotificationHandler","updated","String","get","close","undefined","abortPromise","_","reject","signal","aborted","reason","addEventListener","once","result","race","arguments","content","type","const","text","message","isError","find","values","hasPrompt","some","p","publicSources","timer","setTimeout","clearTimeout","inflightCalls","clear","catch","value","useMCPTools","context","useOptionalMCPTools","ThreadAssistantMessage","ThreadRuntime","PendingToolCallInfo","messageId","toolCallId","toolName","args","Record","getPendingToolCalls","threadRuntime","messages","getState","result","msg","role","assistantMsg","status","type","part","content","undefined","push","id","getPendingToolCallsByName","filter","tc","resolvePendingToolCall","messageRuntime","getMessageById","partRuntime","getMessagePartByToolCallId","addToolResult","resolveAllPendingToolCallsByName","pendingCalls","resolved","call","resolveAllPendingToolCalls","createContext","useCallback","useContext","useEffect","useMemo","useState","Tool","ToolApprovalMode","ToolApprovalSettings","ReactNode","STORAGE_KEY","DEFAULT_MODE","ToolApprovalContextValue","setMode","mode","toggleMode","requiresApproval","tool","isDestructive","ToolApprovalContext","ToolApprovalProviderProps","children","defaultMode","disablePersistence","onModeChange","checkIsDestructive","annotations","readOnlyHint","destructiveHint","ToolApprovalProvider","setModeState","stored","localStorage","getItem","setItem","newMode","value","useToolApproval","context","Error","useOptionalToolApproval","debugLog","AudioAnalyzer","audioContext","AudioContext","analyser","AnalyserNode","source","MediaStreamAudioSourceNode","dataArray","Uint8Array","ArrayBuffer","animationId","initialize","stream","MediaStream","Promise","audioTracks","getAudioTracks","streamId","id","length","trackInfo","map","t","label","enabled","muted","readyState","state","resume","err","console","warn","createAnalyser","fftSize","smoothingTimeConstant","createMediaStreamSource","connect","bufferLength","frequencyBinCount","sampleRate","contextState","getAudioLevel","getByteFrequencyData","sum","i","average","Math","min","getFrequencyData","bins","Array","fill","result","samplesPerBin","floor","j","push","startAnalysis","callback","level","frequencies","analyze","requestAnimationFrame","stopAnalysis","cancelAnimationFrame","destroy","disconnect","close","EventCallback","IEventEmitter","EventEmitter","listeners","Map","Set","on","event","callback","has","set","get","add","off","delete","emit","data","forEach","error","console","removeAllListeners","clear","listenerCount","size","RESPONSE_REQUEST_DELAY_MS","EventEmitter","ToolManager","FunctionCall","RealtimeMessage","ResponseOutputItem","type","status","name","call_id","arguments","isCompletedFunctionCall","item","MessageHandler","isProcessingResponse","pendingFunctionCalls","Set","responseRequestTimer","ReturnType","setTimeout","hasRequestedResponse","constructor","toolManager","eventEmitter","handleMessage","data","dataChannel","RTCDataChannel","Promise","msg","JSON","parse","error","console","handleResponseCreated","handleResponseDone","handleFunctionCallArguments","handleSpeechEvents","handleAudioEvents","handleTranscriptEvents","handleUserTranscript","handleError","handleSessionEvents","_msg","outputItems","extractResponseOutput","response","hasFunctionCalls","some","length","functionCalls","filter","map","functionCall","has","add","executeFunctionCall","warn","size","requestResponseIfNeeded","r","Record","Array","isArray","output","eventType","emit","log","hasAudio","delta","eventMap","text","transcript","clearTimeout","result","executeToolCall","readyState","stringify","success","send","undefined","sendToolError","String","delete","errorResponse","reset","clear","jsonrepair","FunctionCall","OpenAITool","ToolExecutionResult","RegisteredTool","name","description","inputSchema","Record","ToolExecutor","args","Promise","ToolManager","tools","executor","lastSentToolSignature","setTools","setExecutor","resetSession","console","log","getToolSignature","map","t","sort","join","hasToolsChanged","currentSignature","markToolsSent","formatToolsForOpenAI","builtInTools","type","parameters","properties","required","registeredTools","tool","const","validateToolSchema","schema","result","validateNestedSchemas","Object","entries","filter","prop","p","optional","nullable","key","validated","value","propType","items","warn","executeToolCall","functionCall","arguments","argsString","executeListTools","error","success","repaired","JSON","parse","slice","data","String","toolList","count","length","message","getChangesSummary","added","removed","total","prevTools","split","Boolean","currTools","prevSet","Set","currSet","has","debugLog","REALTIME_DEFAULT_API_URL","REALTIME_DEFAULT_MODEL","REALTIME_DEFAULT_VOICE","RealtimeConfig","RealtimeSession","EphemeralTokenResponse","client_secret","value","hasClientSecret","response","secret","WebRTCManager","tokenEndpoint","constructor","createSession","config","Promise","model","voice","apiUrl","ephemeralKey","getEphemeralToken","pc","RTCPeerConnection","audioElement","createAudioElement","remoteStream","MediaStream","ontrack","e","streams","srcObject","streamId","id","tracks","getTracks","length","localStream","getUserMedia","map","t","kind","enabled","muted","readyState","forEach","track","addTrack","dataChannel","createDataChannel","offer","createOffer","setLocalDescription","sdp","Error","answer","connectToOpenAI","setRemoteDescription","cleanup","stop","remove","close","fetch","method","headers","body","JSON","stringify","ok","errorText","text","console","error","statusText","data","json","HTMLAudioElement","document","createElement","autoplay","style","display","appendChild","navigator","mediaDevices","audio","echoCancellation","noiseSuppression","autoGainControl","baseUrl","RTCSessionDescriptionInit","Authorization","answerSdp","type","const","AUDIO_FREQUENCY_BINS","AUDIO_VISUALIZATION_INTERVAL_MS","debugLog","AudioAnalyzer","EventEmitter","MessageHandler","ToolManager","WebRTCManager","RegisteredTool","ToolExecutor","EventCallback","RealtimeConfig","RealtimeSession","SessionConfig","EMPTY_FREQUENCY_TEMPLATE","Object","freeze","Array","fill","createZeroFrequencyArray","OpenAIRealtimeService","session","webrtcManager","toolManager","messageHandler","eventEmitter","muted","lastState","localAnalyzer","remoteAnalyzer","visualizationInterval","ReturnType","setInterval","sessionStartTime","onToolsChangedCallback","constructor","tokenEndpoint","setTools","tools","isSessionActive","updateSessionTools","setToolExecutor","executor","setExecutor","onToolsChanged","callback","startSession","config","Promise","stopSession","Date","now","emitSessionState","createSession","setupDataChannel","dataChannel","setupPeerConnectionMonitoring","pc","localStream","initializeLocalAnalyzer","remoteStream","initializeRemoteAnalyzer","originalOntrack","ontrack","e","call","streams","console","warn","error","handleSessionError","durationSeconds","Math","floor","clearInterval","destroy","cleanup","reset","resetSession","sendUserMessage","text","Error","message","type","item","role","content","send","JSON","stringify","readyState","getLocalStream","MediaStream","getRemoteStream","toggleMute","audioElement","isMuted","pauseAudio","pause","resumeAudio","play","catch","on","event","off","getSessionStatus","state","isActive","RTCDataChannel","addEventListener","configureSession","MessageEvent","handleMessage","data","emit","RTCPeerConnection","connectionState","iceConnectionState","formatToolsForOpenAI","markToolsSent","sessionConfig","modalities","instructions","getSessionInstructions","voice","tool_choice","turn_detection","threshold","prefix_padding_ms","silence_duration_ms","input_audio_transcription","model","sessionUpdate","changesSummary","getChangesSummary","log","total","added","length","slice","join","removed","String","stream","clonedStream","getAudioTracks","map","t","clone","initialize","startAudioVisualization","logCounter","micLevel","getAudioLevel","micFrequency","getFrequencyData","speakerLevel","speakerFrequency","mic","toFixed","speaker","extra","Record","payload","RealtimeConfig","model","voice","apiUrl","tokenEndpoint","RealtimeSession","pc","RTCPeerConnection","dataChannel","RTCDataChannel","audioElement","HTMLAudioElement","localStream","MediaStream","remoteStream","cleanup","OpenAITool","type","name","description","parameters","properties","Record","required","SessionConfig","modalities","instructions","tools","tool_choice","turn_detection","threshold","prefix_padding_ms","silence_duration_ms","input_audio_transcription","FunctionCall","arguments","call_id","status","ConversationItem","role","content","output","RealtimeMessage","key","ToolExecutionResult","success","data","error","EventCallback","IEventEmitter","on","event","callback","off","emit","AudioLevelData","micLevel","micFrequency","speakerLevel","speakerFrequency","TranscriptData","text","isDone","ToolCallData","toolName","VoiceModeState","isActive","isConnecting","isMuted","isError","connectionState","audioLevel","transcript","toolCall","SessionStateEventData","state","durationSeconds","UserTranscriptEventData","AssistantTranscriptEventData","delta","ToolCallStartedEventData","ToolCallCompletedEventData","NestedErrorObject","code","message","param","event_id","ErrorEventData","isSessionStateEventData","d","includes","isUserTranscriptEventData","isAssistantTranscriptEventData","undefined","isToolCallStartedEventData","isToolCallCompletedEventData","isErrorEventData","hasError","extractErrorMessage","nestedError","isAudioLevelData","Array","isArray","useCallback","useEffect","useMemo","useRef","useState","TOOL_CALL_DISPLAY_DURATION_MS","TOOL_CALL_ERROR_DISPLAY_DURATION_MS","extractErrorMessage","isAssistantTranscriptEventData","isAudioLevelData","isErrorEventData","isSessionStateEventData","isToolCallCompletedEventData","isToolCallStartedEventData","isUserTranscriptEventData","OpenAIRealtimeService","AudioLevelData","RealtimeConfig","RegisteredTool","ToolCallData","ToolExecutor","TranscriptData","VoiceModeState","UseVoiceModeOptions","tokenEndpoint","tools","toolExecutor","onConnect","onDisconnect","durationSeconds","onError","error","onUserTranscript","text","onAssistantTranscript","UseVoiceModeReturn","startSession","config","Promise","stopSession","toggleMute","muted","sendMessage","pauseAudio","resumeAudio","useVoiceMode","options","$","_c","isActive","setIsActive","isConnecting","setIsConnecting","isMuted","setIsMuted","isError","setIsError","connectionState","setConnectionState","audioLevel","setAudioLevel","transcript","setTranscript","toolCall","setToolCall","setError","serviceRef","onConnectRef","onDisconnectRef","onErrorRef","onUserTranscriptRef","onAssistantTranscriptRef","t0","t1","current","t2","getService","t3","t4","service","setTools","t5","t6","service_0","setToolExecutor","t7","t8","service_1","handleSessionState","data","console","warn","state","handleAudioLevel","data_0","handleUserTranscript","data_1","type","isDone","handleAssistantTranscript","data_2","delta","prev","handleAssistantTranscriptDone","data_3","text_0","handleToolCallStarted","data_4","status","toolName","name","handleToolCallCompleted","data_5","setTimeout","undefined","handleError","data_6","errorMsg","on","off","t9","service_2","t10","err","errorMsg_0","Error","message","service_3","t11","service_4","newMuted","t12","text_1","service_5","isSessionActive","sendUserMessage","t13","service_6","t14","service_7","t15","createContext","useContext","useMemo","useVoiceMode","ReactNode","UseVoiceModeReturn","RegisteredTool","ToolExecutor","VoiceModeContextValue","isSupported","VoiceModeContext","VoiceModeProviderProps","children","tokenEndpoint","tools","toolExecutor","onConnect","onDisconnect","durationSeconds","onError","error","onUserTranscript","text","onAssistantTranscript","checkVoiceModeSupport","window","RTCPeerConnection","navigator","mediaDevices","getUserMedia","VoiceModeProvider","t0","$","_c","t1","voiceMode","t2","Symbol","for","t3","value","t4","useVoiceModeContext","context","Error","useOptionalVoiceModeContext","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS","VOICE_APPROVAL_TIMEOUT_MS","FC","ReactNode","VoicePendingApproval","callId","toolName","args","Record","timestamp","VoiceToolApprovalContextValue","pendingApproval","approve","deny","timeoutRemaining","isWaitingForApproval","requestApproval","Promise","clearPendingApproval","VoiceToolApprovalContext","VoiceToolApprovalProviderProps","children","timeout","onTimeout","onApprove","onDeny","VoiceToolApprovalProvider","setPendingApproval","setTimeoutRemaining","resolveRef","approved","timeoutIdRef","ReturnType","setTimeout","countdownIdRef","setInterval","onTimeoutRef","onApproveRef","onDenyRef","current","clearTimers","clearTimeout","clearInterval","resolveApproval","reason","resolve","Date","now","timeoutSeconds","Math","ceil","prev","value","useVoiceToolApproval","context","Error","useOptionalVoiceToolApproval","useThreadRuntime","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","VOICE_TOOL_RESULT_MESSAGES","TOOL_DENIED_MESSAGE","resolveAllPendingToolCalls","resolveAllPendingToolCallsByName","useOptionalMCPTools","useOptionalToolApproval","useOptionalVoiceModeContext","VoiceModeProvider","useOptionalVoiceToolApproval","VoiceToolApprovalProvider","ToolCallMetadata","ToolWithSource","FC","MutableRefObject","ReactNode","RegisteredTool","ToolExecutor","VoiceToolCallData","toolCallId","toolName","args","Record","result","isError","artifact","AddToolCallToThread","data","VoiceMessageMetadata","source","voiceSessionId","timestamp","VoiceThreadContextValue","isActive","isConnecting","isMuted","isSupported","error","sessionId","start","Promise","stop","toggleMute","muted","sendMessage","text","pauseAudio","resumeAudio","audioLevel","micLevel","speakerLevel","transcript","type","isDone","toolCall","status","VoiceThreadContext","generateSessionId","Date","now","Math","random","toString","slice","convertToRegisteredTool","tool","name","description","inputSchema","properties","VoiceThreadBridgeProps","children","tokenEndpoint","onConnect","onDisconnect","durationSeconds","onError","VoiceThreadIntegrator","setSessionId","id","addToolCallRef","threadRuntime","voiceMode","lastUserTranscriptRef","lastAssistantTranscriptRef","wasActiveRef","onConnectRef","onDisconnectRef","onErrorRef","current","console","warn","append","role","content","argsText","JSON","stringify","metadata","custom","addUserMessage","trim","addAssistantMessage","newSessionId","sessionEnded","ApprovalAwareVoiceBridge","voiceTools","t0","$","_c","mcpTools","toolApproval","voiceToolApproval","t1","callTool","Error","tools","find","t","needsApproval","requiresApproval","callId","approved","requestApproval","resultMessage","handled","textContent","_temp","toolExecutor","t2","t3","t4","VoiceThreadBridge","map","VoiceThreadContextProvider","bb0","undefined","t5","startSession","stopSession","contextValue","useVoiceThread","context","useOptionalVoiceThread","useIsVoiceActive","c","useThread","useMemo","useLatestSummary","useActions","useCurrentAction","useLastCompletedAction","useRecentActions","useOptionalMCPTools","useOptionalVoiceThread","CallToolResult","Prompt","ToolWithSource","GetPromptResult","Action","AgentVoice","isActive","isConnecting","isError","isMuted","isSupported","error","sessionId","audioLevel","micLevel","speakerLevel","transcript","type","text","isDone","start","Promise","stop","toggleMute","muted","sendMessage","AgentTools","list","call","name","args","Record","prompts","getPrompt","AgentMessage","id","role","content","status","metadata","AgentState","messages","isRunning","hasMessages","actions","currentAction","recentActions","lastCompletedAction","summary","voice","tools","isVoiceActive","useAgent","$","_c","threadMessages","_temp","_temp2","voiceThread","mcpContext","length","t0","bb0","t1","bb1","t2","t3","callTool","t4","thread_0","thread","createContext","useCallback","useContext","useMemo","useRef","useState","FC","ReactNode","PillMode","Position","x","y","AgentUIState","isOpen","userMode","position","hasUnread","isVoiceActive","isFullScreen","AgentUIContextValue","setOpen","open","toggleOpen","setUserMode","mode","setPosition","resetPosition","markRead","markUnread","setVoiceActive","active","collapse","expand","enterFullScreen","exitFullScreen","toggleFullScreen","AgentUIContext","DEFAULT_POSITION","AgentUIProviderProps","children","defaultOpen","defaultMode","onOpenChange","onModeChange","AgentUIProvider","setIsOpenState","setUserModeState","setPositionState","setHasUnread","setIsVoiceActiveState","setIsFullScreen","onOpenChangeRef","onModeChangeRef","current","prev","next","pos","value","useAgentUI","context","Error","useOptionalAgentUI","usePillMode","useHasUnread","c","_c","useCallback","useEffect","useState","KEYBOARD_VISIBILITY_THRESHOLD_PX","KeyboardState","isKeyboardVisible","keyboardHeight","visibleHeight","useKeyboardAware","$","t0","Symbol","for","window","innerHeight","state","setState","t1","visualViewport","windowHeight","viewportHeight","height","heightDiff","updateKeyboardState","t2","t3","visualViewport_0","addEventListener","removeEventListener","getKeyboardOffset","additionalOffset","c","_c","useEffect","useState","useMobileDetect","$","isMobile","setIsMobile","isTouchDevice","setIsTouchDevice","isCoarsePointer","setIsCoarsePointer","t0","t1","Symbol","for","hasTouch","window","navigator","maxTouchPoints","hoverNone","matchMedia","pointerCoarse","updateState","matches","handleHoverChange","handlePointerChange","addEventListener","removeEventListener","t2","checkIsMobileSSR","useThread","useThreadRuntime","useMemo","ThreadAssistantMessage","PendingToolCallInfo","PendingToolCall","usePendingToolCalls","$","_c","messages","_temp","result","msg","role","assistantMsg","status","type","part","content","undefined","push","messageId","id","toolCallId","toolName","args","Record","t","useHasPendingToolCalls","_temp2","t0","bb0","c","_c","useCallback","useRef","PINCH_GESTURE_CONFIG","TouchEvent","ReactTouchEvent","PinchGestureOptions","onPinchOut","onPinchIn","enabled","threshold","PinchState","initialDistance","lastDistance","isActive","TouchPoint","clientX","clientY","getTouchDistance","touch1","touch2","dx","dy","Math","sqrt","usePinchGesture","t0","$","t1","t2","undefined","t3","Symbol","for","stateRef","t4","e","touches","length","distance","minInitialDistance","current","handleTouchStart","t5","e_0","currentDistance","handleTouchMove","t6","e_1","scaleDelta","handleTouchEnd","t7","handlers","onTouchStart","onTouchMove","onTouchEnd","c","_c","useThread","Camera","FileText","Loader2","MousePointer","Navigation","PenLine","Search","Trash2","Wrench","useMemo","humanizeToolName","cn","LucideIcon","FC","getToolIcon","toolName","name","toLowerCase","includes","ActivityState","type","label","icon","toolNames","streamingText","useActivityState","$","messages","_temp","isRunning","_temp2","t0","bb0","lastAssistantMessage","reverse","find","_temp3","t1","Symbol","for","runningToolNames","lastText","part","content","toolPart","status","push","textPart","text","length","t2","m","role","thread_0","thread","ActivityIndicatorProps","className","ActivityIndicator","activity","Icon","isSpinning","t3","t4","t5","t6","slice","map","_temp4","t7","i","ToolIcon","Shield","ShieldOff","cn","useOptionalToolApproval","FC","ApprovalModeToggleProps","className","ApprovalModeToggle","t0","$","_c","toolApproval","mode","toggleMode","isAskMode","t1","t2","t3","t4","t5","ApprovalModeIndicator","c","_c","AlertCircle","CheckCircle2","Circle","Loader2","cn","FC","Action","CurrentActivityProps","currentAction","recentActions","showRecent","className","CurrentActivity","t0","$","t1","t2","t3","undefined","t4","t5","status","label","t6","length","map","_temp","t7","ActionStatusIconProps","size","ActionStatusIcon","sizeClass","IdleIndicator","Symbol","for","action","id","useAssistantTool","ToolResponse","useMCPTools","useOptionalToolApproval","CallToolResult","ToolCallMetadata","ToolWithSource","ReadonlyJSONValue","FC","formatToolResult","result","textContent","content","map","c","type","text","JSON","stringify","join","ToolBridge","tool","callTool","name","args","Record","Promise","t0","$","_c","t1","description","t2","inputSchema","t3","t4","_sourceId","startedAt","Date","now","isError","wasAborted","some","_temp","metadata_0","duration","sourceId","artifact","metadata","t5","error","console","Error","message","String","toolName","parameters","execute","DestructiveToolBridge","MCPToolRegistry","tools","toolApproval","needsApproval","requiresApproval","includes","useThreadRuntime","AlertTriangle","Check","Loader2","X","useState","usePendingToolCalls","formatArgs","humanizeToolName","TOOL_DENIED_MESSAGE","resolveAllPendingToolCalls","cn","useMCPTools","formatToolResult","FC","ElicitationButtonBarProps","className","ElicitationButtonBar","isExecuting","setIsExecuting","pendingToolCalls","threadRuntime","callTool","tools","length","firstTool","humanizedName","toolName","toolDescription","find","t","name","description","hasArgs","Object","keys","args","formattedArgs","getPartRuntime","messageRuntime","getMessageById","messageId","getMessagePartByToolCallId","toolCallId","handleAccept","toolResult","partRuntime","addToolResult","error","errorMessage","Error","message","String","handleDeny","cancelRun","c","_c","ComposerPrimitive","ThreadPrimitive","useComposer","useComposerRuntime","Mic","Send","Square","useCallback","useRef","useMobileDetect","COMPOSER_MAX_CHARS","cn","FC","PillComposerProps","placeholder","showVoiceButton","isVoiceActive","onVoiceToggle","showCharCount","className","isEliciting","onElicitationSubmit","reason","CharacterCount","$","composer","_temp","charCount","length","isOver","remaining","t0","t1","t2","PillComposer","t3","t4","t5","undefined","isMobile","inputRef","composerRuntime","effectivePlaceholder","t6","current","blur","handleSubmit","t7","text","getState","trim","setText","handleElicitationSubmit","t8","e","key","shiftKey","preventDefault","handleKeyDown","t9","t10","t11","Symbol","for","touchAction","t12","t13","_temp2","t14","t15","t16","t17","t18","t19","e_0","stopPropagation","c","_c","useEffect","useRef","useAriaHidden","isActive","containerRef","$","t0","Symbol","for","Map","modifiedElementsRef","t1","t2","current","forEach","_temp","clear","container","dialogRoot","parentElement","document","body","bodyChildren","Array","from","children","child","tagName","originalValue_0","getAttribute","set","originalValue","setAttribute","_temp2","originalValue_1","element_0","element","removeAttribute","c","_c","useCallback","useEffect","useRef","FOCUSABLE_SELECTOR","join","UseFocusTrapOptions","isActive","onEscape","autoFocus","returnFocus","skipInputFocusReturn","UseFocusTrapReturn","containerRef","React","RefObject","HTMLDivElement","storeTrigger","useFocusTrap","t0","$","t1","t2","t3","undefined","triggerRef","previouslyFocusedRef","t4","Symbol","for","current","document","activeElement","HTMLElement","t5","Array","from","querySelectorAll","getFocusableElements","t6","t7","timeoutId","setTimeout","focusableElements","length","focus","clearTimeout","isConnected","isInputElement","tagName","blur","isInputElement_0","t8","t9","handleKeyDown","event","key","preventDefault","focusableElements_0","firstElement","lastElement","shiftKey","contains","addEventListener","removeEventListener","t10","AnimatePresence","motion","useReducedMotion","useCallback","useEffect","useRef","useState","useAriaHidden","useFocusTrap","useMobileDetect","ARIA_IDS","ARIA_LABELS","clampSize","FULL_SCREEN_CONFIG","PILL_BORDER_RADIUS","PILL_CONTAINER_SIZES","UI_TIMING","cn","Variants","FC","ReactNode","PillMode","PillContainerProps","mode","children","onModeChange","isFullScreen","className","sizeSpring","type","const","stiffness","damping","mass","fullScreenTween","duration","ease","reducedMotionTransition","sizes","containerVariants","Record","width","height","padding","borderRadius","collapsed","pill","hovered","composing","rounded","active","expanded","fullScreenVariant","widthPercent","maxWidth","heightPercent","contentVariants","hidden","opacity","visible","transition","delay","exit","hintVariants","barVariants","idle","scaleX","hover","PillContainer","isHovered","setIsHovered","hoverTimeoutRef","NodeJS","Timeout","prefersReducedMotion","wasFullScreenRef","isTransitioningFullScreen","current","isMobile","isDialogActive","containerRef","focusTrapRef","storeTrigger","isActive","onEscape","autoFocus","returnFocus","skipInputFocusReturn","prevModeRef","wasCollapsedOrHovered","isNowDialog","handleMouseEnter","clearTimeout","setTimeout","hoverDebounce","handleMouseLeave","collapseDelay","handleClick","handleFocus","handleBlur","handleKeyDown","e","KeyboardEvent","isShortcut","ctrlKey","metaKey","shiftKey","key","toLowerCase","isEscape","preventDefault","window","addEventListener","removeEventListener","showContent","currentVariant","isDialogMode","setContainerRef","node","HTMLDivElement","glassClassName","undefined","pillTitle","openAssistant","background","backgroundSize","Slot","cva","React","cn","VariantProps","ButtonProps","ComponentProps","buttonVariants","asChild","variants","variant","default","destructive","outline","secondary","ghost","link","size","sm","lg","icon","defaultVariants","Button","t0","$","_c","className","props","t1","undefined","Comp","t2","t3","c","_c","AlertCircle","AlertTriangle","Check","ChevronDownIcon","ChevronUpIcon","X","useCallback","useState","formatArgs","humanizeToolName","TOOL_DENIED_MESSAGE","cn","useMCPTools","Button","formatToolResult","getToolIcon","ToolCallMessagePartComponent","ApprovedResult","approved","result","isApprovedResult","isDeniedResult","hasStatusError","status","type","error","RunningToolDisplay","React","FC","toolName","t0","$","t1","ToolIcon","t2","t3","t4","t5","ApprovalDialog","toolDescription","inputArgs","Record","onApprove","onDeny","isExecuting","isHovered","setIsHovered","Symbol","for","t6","t7","t8","t9","t10","Object","keys","length","t11","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","t24","t25","CompletedToolDisplay","argsText","isExpanded","setIsExpanded","undefined","JSON","stringify","ErrorToolDisplay","DeniedToolDisplay","UnifiedToolFallback","toolCallId","_toolCallId","args","addResult","callTool","tools","setIsExecuting","parsedArgs","parse","e","console","warn","find","t","name","description","handleApprove","toolResult","errorMessage","Error","message","String","handleDeny","statusType","isPendingApproval","displayResult","c","_c","MessagePrimitive","ThreadPrimitive","UnifiedToolFallback","FC","PillMessageContent","$","t0","Symbol","for","UserMessage","_temp","AssistantMessage","PillAssistantMessage","Text","_temp2","tools","Fallback","c","_c","AlertTriangle","ChevronDown","useEffect","useState","useActions","cn","PillMessageContent","FC","PillToolsSectionProps","defaultCollapsed","className","isFullScreen","PillToolsSection","t0","$","t1","t2","undefined","isCollapsed","setIsCollapsed","actions","t3","filter","_temp","completedCount","length","t4","_temp2","runningCount","t5","_temp3","pendingCount","totalCount","t6","t7","t8","t9","t10","Symbol","for","t11","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","t24","t25","touchAction","t26","t27","_temp4","t28","t29","a","status","a_0","a_1","e","stopPropagation","useEffect","useRef","cn","HTMLAttributes","LiveWaveformProps","HTMLDivElement","active","processing","barWidth","barGap","barRadius","barColor","fadeEdges","fadeWidth","height","sensitivity","smoothingTimeConstant","mode","manualAudioLevel","LiveWaveform","t0","$","_c","className","props","t1","t10","t2","t3","t4","t5","t6","t7","t8","t9","undefined","canvasRef","containerRef","t11","Symbol","for","historyRef","lastUpdateRef","processingAnimationRef","t12","lastActiveDataRef","transitionProgressRef","t13","staticBarsRef","needsRedrawRef","gradientCacheRef","lastWidthRef","heightStyle","t14","t15","canvas","current","container","resizeObserver","ResizeObserver","rect","getBoundingClientRect","dpr","window","devicePixelRatio","width","style","ctx","getContext","scale","observe","disconnect","t16","t17","time","animateProcessing","Math","min","processingData","barCount","floor","halfCount","i","normalizedPosition","centerWeight","abs","wave1","sin","wave2","wave3","cos","combinedWave","processingValue","finalValue","length","lastDataIndex","lastValue","push","max","i_0","normalizedPosition_0","centerWeight_0","wave1_0","wave2_0","wave3_0","combinedWave_0","processingValue_0","finalValue_0","lastDataIndex_0","lastValue_0","requestAnimationFrame","cancelAnimationFrame","hasData","fadeProgress","fadeToIdle","map","value","value_0","t18","t19","canvas_0","ctx_0","rafId","animate","currentTime","rect_0","level","barCount_0","halfCount_0","newBars","i_1","distanceFromCenter","value_1","i_2","distanceFromCenter_0","value_2","shift","clearRect","computedBarColor","getComputedStyle","color","step","barCount_1","centerY","dataToRender","i_3","value_3","x","barHeight","y","fillStyle","globalAlpha","beginPath","roundRect","fill","fillRect","i_4","dataIndex","value_4","x_0","barHeight_0","y_0","gradient","createLinearGradient","fadePercent","addColorStop","globalCompositeOperation","t20","t21","t22","t23","t24","t25","c","_c","AlertTriangle","Check","Loader2","Pause","X","AnimatePresence","motion","useEffect","useState","humanizeToolName","cn","useOptionalVoiceThread","useOptionalVoiceToolApproval","FC","approvalBarVariants","hidden","opacity","height","y","visible","transition","type","const","stiffness","damping","exit","duration","countdownVariants","pulse","scale","repeat","Infinity","PillVoiceApprovalBarProps","className","PillVoiceApprovalBar","t0","$","voiceThread","voiceApproval","isExecuting","setIsExecuting","t1","pendingApproval","pauseAudio","resumeAudio","t2","t3","timeoutRemaining","approve","deny","t4","toolName","t5","handleApprove","t6","handleDeny","t7","t8","Symbol","for","t9","t10","t11","t12","t13","t14","undefined","t15","t16","t17","t18","t19","t20","t21","c","_c","Mic","MicOff","PhoneOff","AnimatePresence","motion","useCallback","cn","useOptionalVoiceThread","useOptionalVoiceToolApproval","LiveWaveform","PillVoiceApprovalBar","FC","ToolBorderStatus","PillVoiceProps","onEnd","compact","className","voiceVariants","hidden","opacity","scale","y","visible","transition","type","const","stiffness","damping","exit","duration","buttonVariants","idle","hover","tap","transcriptVariants","height","voiceToolCallToBorderStatus","toolCall","status","error","PillVoice","t0","$","t1","undefined","voiceThread","voiceToolApproval","t2","clearPendingApproval","stop","handleEnd","t3","toggleMute","handleToggleMute","isActive","isConnecting","isError","isMuted","audioLevel","transcript","isWaitingForApproval","micLevel","speakerLevel","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","t16","t17","Symbol","for","t18","t19","t20","t21","t22","t23","t24","t25","t26","t27","t28","t29","t30","t31","t32","t33","t34","t35","t36","t37","t38","t39","t40","t41","t42","repeat","Infinity","toolName","t43","t44","text","isDone","t45","t46","t47","t48","t49","t50","useVoiceBorderStatus","X","AnimatePresence","motion","useCallback","useState","useMobileDetect","MAX_PROMPT_BUBBLES","cn","Prompt","Variants","FC","MouseEvent","PromptBadgeProps","prompts","onSelect","prompt","className","STAGGER_DELAY","STAGGER_DELAY_INITIAL","STAGGER_DELAY_EXIT","containerVariants","hidden","opacity","visible","transition","staggerChildren","delayChildren","exit","staggerDirection","bubbleVariants","y","scale","type","stiffness","damping","duration","bubbleStyles","dismissBadgeBaseStyles","PromptBadge","t0","$","_c","isDismissed","setIsDismissed","isMobile","t1","handleSelect","t2","Symbol","for","e","stopPropagation","handleDismiss","length","T0","T1","t10","t11","t12","t13","t14","t3","t4","t5","t6","t7","t8","t9","visiblePrompts","slice","t15","t16","t17","dismissBadgeStyles","div","map","prompt_0","index","isMiddleBubble","name","description","AnimatePresence","motion","useCallback","useRef","cn","Prompt","FC","PromptSuggestionsProps","prompts","onSelect","prompt","className","PromptSuggestions","t0","$","_c","scrollRef","t1","handleClick","length","t2","t3","t4","Symbol","for","opacity","height","t5","t6","t7","touchAction","t8","t9","prompt_0","index","name","scale","type","stiffness","damping","delay","description","map","_temp","t10","e","stopPropagation","c","_c","useThread","useMemo","cn","PillMarkdown","FC","TextPart","type","text","useStreamingText","$","messages","_temp","isRunning","_temp2","t0","bb0","lastAssistantMessage","reverse","find","_temp3","textParts","content","filter","_temp4","lastText","at","trim","length","part","m","role","thread_0","thread","StreamingResponseProps","maxHeight","className","isFullScreen","StreamingResponse","t1","t2","undefined","streamingText","t3","t4","t5","t6","t7","Symbol","for","t8","t9","c","_c","AnimatePresence","motion","useEffect","useRef","useState","cn","FC","ReactNode","ToolBorderStatus","ToolStatusBorderProps","status","children","className","borderRadius","borderVariants","idle","opacity","scale","calling","transition","duration","error","shakeAnimation","x","ease","const","ToolStatusBorder","t0","$","t1","undefined","effectiveStatus","t2","t3","t4","t5","t6","t7","t8","useToolBorderStatus","hasRunningAction","lastActionStatus","setStatus","timeoutRef","current","clearTimeout","setTimeout","ThreadPrimitive","useComposerRuntime","useThreadRuntime","Expand","GripHorizontal","Minimize","X","AnimatePresence","motion","useDragControls","useCallback","useEffect","useMemo","useRef","useState","useAgent","useOptionalAgentUI","useKeyboardAware","useMobileDetect","useHasPendingToolCalls","usePendingToolCalls","usePinchGesture","ARIA_LABELS","AUTO_COLLAPSE_TIMEOUT_MS","debugLog","DRAG_OPACITY","GESTURE_CONFIG","KEYBOARD_GAP_PX","PILL_BORDER_RADIUS","formatToolDenialWithReason","resolvePendingToolCall","cn","ActivityIndicator","ApprovalModeIndicator","IdleIndicator","ElicitationButtonBar","PillComposer","PillContainer","PillToolsSection","PillVoice","useVoiceBorderStatus","PromptBadge","PromptSuggestions","StreamingResponse","SummaryBlock","WelcomeMessage","ToolStatusBorder","useToolBorderStatus","Prompt","FC","PillMode","PillPosition","AgentPillProps","position","showVoiceButton","isVoiceActive","onVoiceToggle","autoCollapse","className","AgentPill","agent","messages","isRunning","hasMessages","currentAction","lastCompletedAction","summary","voice","tools","agentVoiceActive","hasPendingApproval","pendingToolCalls","threadRuntime","agentUI","userMode","setUserMode","hasUnread","markRead","markUnread","dragPosition","x","y","setDragPosition","setPosition","resetPosition","isFullScreen","enterFullScreen","exitFullScreen","dragControls","constraintsRef","HTMLDivElement","autoCollapseTimeoutRef","NodeJS","Timeout","lastMessageCountRef","isKeyboardVisible","keyboardHeight","isMobile","prompts","getPrompt","composerRuntime","handleDragEnd","_","info","offset","velocity","dragDistance","Math","sqrt","isExpanded","swipeDistance","swipeVelocity","swipe","isAggressiveSwipe","minDistance","minVelocity","velocityOnlyThreshold","dragActivationDistance","currentCount","length","current","voiceBorderStatus","isVoiceModeActive","textBorderStatus","status","borderStatus","mode","handleModeChange","newMode","handleCollapse","clearTimeout","setTimeout","handleVoiceToggle","isActive","isConnecting","stop","start","handlePromptSelect","prompt","result","name","userMessage","find","m","role","content","textContent","type","text","setText","send","err","handleElicitationDeny","reason","firstTool","message","messageId","toolCallId","borderRadius","pill","rounded","handlers","pinchHandlers","onPinchOut","onPinchIn","enabled","isComposerReady","setComposerReady","timer","handleKeyDown","e","KeyboardEvent","key","preventDefault","window","addEventListener","removeEventListener","scale","opacity","dragging","stiffness","damping","touchAction","dragHandle","collapseFullScreen","expandFullScreen","endVoiceSession","closeAssistant","error","duration","isSupported","AssistantRuntimeProvider","AssistantChatTransport","useChatRuntime","lastAssistantMessageIsCompleteWithToolCalls","useMemo","MCPToolRegistry","WEBMCP_PRODUCTION_API_BASE","MCPToolsProvider","ToolApprovalProvider","VoiceThreadBridge","AgentUIProvider","ToolApprovalMode","ToolWithSource","FC","ReactNode","PillMode","AgentProviderProps","children","apiBase","tokenEndpoint","autoConnectLocal","defaultOpen","defaultMode","defaultApprovalMode","onToolsChange","tools","onVoiceError","error","onVoiceConnect","onVoiceDisconnect","duration","onOpenChange","open","onModeChange","mode","onApprovalModeChange","AgentRuntimeProps","AgentRuntime","t0","$","_c","resolvedApiBase","chatApi","t1","api","transport","t2","sendAutomaticallyWhen","_temp","runtime","resolvedTokenEndpoint","t3","Symbol","for","t4","t5","AgentProvider","undefined","t6","t7","messages","WEBMCP_STYLES","injectStyles","document","styleId","getElementById","style","createElement","id","textContent","head","appendChild","r2wc","AgentPill","AgentProvider","injectStyles","WEBMCP_PRODUCTION_API_BASE","FC","getDefaultApiBase","process","env","NODE_ENV","window","location","origin","DevModeConfig","anthropicApiKey","openaiApiKey","EmbeddedAgentProps","appId","devMode","EmbeddedAgent","t0","$","_c","apiBase","console","debug","mode","voiceEnabled","t1","undefined","t2","t3","WebMCPAgentElement","Parameters","props","registerWebMCPAgent","tagName","customElements","get","define"],"sources":["../src/lib/constants.ts","../src/lib/utils.ts","../src/components/pill/PillMarkdown.tsx","../src/components/pill/SummaryBlock.tsx","../src/lib/format.ts","../src/hooks/useActions.ts","../src/lib/mcp-transport.ts","../src/providers/MCPToolsProvider.tsx","../src/lib/thread-utils.ts","../src/providers/ToolApprovalProvider.tsx","../src/services/realtime/audio-analyzer.ts","../src/services/realtime/event-emitter.ts","../src/services/realtime/message-handler.ts","../src/services/realtime/tool-manager.ts","../src/services/realtime/webrtc-manager.ts","../src/services/realtime/openai-realtime-service.ts","../src/services/realtime/types.ts","../src/hooks/useVoiceMode.ts","../src/providers/VoiceModeProvider.tsx","../src/providers/VoiceToolApprovalProvider.tsx","../src/providers/VoiceThreadBridge.tsx","../src/core/hooks/useAgent.ts","../src/core/providers/AgentUIProvider.tsx","../src/hooks/useKeyboardAware.ts","../src/hooks/useMobileDetect.ts","../src/hooks/usePendingToolCalls.ts","../src/hooks/usePinchGesture.ts","../src/components/pill/ActivityIndicator.tsx","../src/components/pill/ApprovalModeToggle.tsx","../src/components/pill/CurrentActivity.tsx","../src/components/MCPToolRegistry.tsx","../src/components/pill/ElicitationButtonBar.tsx","../src/components/pill/PillComposer.tsx","../src/hooks/useAriaHidden.ts","../src/hooks/useFocusTrap.ts","../src/components/pill/PillContainer.tsx","../src/components/button.tsx","../src/components/UnifiedToolFallback.tsx","../src/components/pill/PillMessageContent.tsx","../src/components/pill/PillToolsSection.tsx","../src/components/live-waveform.tsx","../src/components/pill/PillVoiceApprovalBar.tsx","../src/components/pill/PillVoice.tsx","../src/components/pill/PromptBadge.tsx","../src/components/pill/PromptSuggestions.tsx","../src/components/pill/StreamingResponse.tsx","../src/components/pill/ToolStatusBorder.tsx","../src/components/pill/AgentPill.tsx","../src/core/providers/AgentProvider.tsx","../src/generated/inline-styles.ts","../src/web-component.tsx"],"sourcesContent":["/**\n * Shared Constants\n *\n * Centralized location for all magic numbers, timeouts, and configuration values.\n * Having these in one place makes the codebase more maintainable and easier to tune.\n */\n\n// ============================================================================\n// Mobile UX Constants\n// ============================================================================\n\n/**\n * Gesture configuration for touch interactions.\n *\n * Mobile swipe-to-dismiss requires an AGGRESSIVE upward swipe to prevent\n * accidental dismisses while allowing intentional quick swipes.\n */\nexport const GESTURE_CONFIG = {\n\t/** Minimum drag distance (px) before it counts as a drag (prevents tap interference) */\n\tdragActivationDistance: 15,\n\n\t/** Swipe-to-dismiss thresholds (mobile only) */\n\tswipe: {\n\t\t/** Must swipe at least this far (px) AND this fast to dismiss */\n\t\tminDistance: 100,\n\t\t/** Minimum velocity (px/s) required with minDistance */\n\t\tminVelocity: 800,\n\t\t/** OR swipe this fast (px/s) regardless of distance for quick flicks */\n\t\tvelocityOnlyThreshold: 1200,\n\t},\n} as const\n\n/**\n * Container sizing for different pill modes.\n * Uses CSS clamp() for fluid responsive sizing.\n *\n * Format: { min, preferred (vw), max }\n *\n * WCAG 2.5.8 (Level AA): Touch targets must be at least 24x24 CSS pixels\n * WCAG 2.5.5 (Level AAA): Touch targets should be at least 44x44 CSS pixels\n * We use 24px minimum for collapsed state to meet AA compliance.\n */\nexport const PILL_CONTAINER_SIZES = {\n\tcollapsed: { width: { min: 44, vw: 12, max: 56 }, height: { min: 24, vw: 6, max: 28 } },\n\thovered: { width: { min: 160, vw: 45, max: 180 }, height: { min: 36, vw: 9, max: 40 } },\n\tcomposing: { width: { min: 260, vw: 80, max: 340 } },\n\tactive: { width: { min: 260, vw: 80, max: 340 } },\n\texpanded: { width: { min: 280, vw: 85, max: 400 } },\n} as const\n\n/** Helper to generate CSS clamp() string from sizing config */\nexport function clampSize(config: { min: number; vw: number; max: number }): string {\n\treturn `clamp(${config.min}px, ${config.vw}vw, ${config.max}px)`\n}\n\n/** Auto-collapse timeout in milliseconds (inactivity before pill collapses) */\nexport const AUTO_COLLAPSE_TIMEOUT_MS = 30000\n\n/** Maximum character limit for composer input */\nexport const COMPOSER_MAX_CHARS = 4000\n\n/** Border radius values for pill states */\nexport const PILL_BORDER_RADIUS = {\n\t/** Pill shape (collapsed/hovered) */\n\tpill: '9999px',\n\t/** Rounded rectangle (expanded states) */\n\trounded: '16px',\n\t/** Inner elements (cards, buttons, etc.) */\n\tinner: '10px',\n\t/** Small elements (chips, badges) */\n\tsmall: '6px',\n} as const\n\n/**\n * Spacing scale for consistent padding/margins.\n * Uses a compact scale optimized for mobile information density.\n * Values in pixels - use with template literals: `${PILL_SPACING.sm}px`\n */\nexport const PILL_SPACING = {\n\t/** Extra small: 4px - minimal gaps */\n\txs: 4,\n\t/** Small: 6px - tight spacing */\n\tsm: 6,\n\t/** Medium: 8px - default spacing */\n\tmd: 8,\n\t/** Large: 10px - section spacing */\n\tlg: 10,\n\t/** Extra large: 12px - container padding */\n\txl: 12,\n} as const\n\n/**\n * Max heights for scrollable sections.\n * Mobile-first values (larger on mobile for easier touch scrolling).\n */\nexport const PILL_MAX_HEIGHTS = {\n\t/** Tools section: 160px mobile, 128px desktop */\n\ttools: { mobile: 160, desktop: 128 },\n\t/** Summary block: 128px mobile, 96px desktop */\n\tsummary: { mobile: 128, desktop: 96 },\n\t/** Composer input: 120px mobile, 96px desktop */\n\tcomposer: { mobile: 120, desktop: 96 },\n} as const\n\n/** Maximum number of prompt bubbles to show above collapsed pill */\nexport const MAX_PROMPT_BUBBLES = 3\n\n/** Debounce/delay values in milliseconds */\nexport const UI_TIMING = {\n\t/** Hover debounce before expanding */\n\thoverDebounce: 100,\n\t/** Delay before collapsing after mouse leave */\n\tcollapseDelay: 50,\n\t/** Copy button feedback duration */\n\tcopyFeedback: 2000,\n} as const\n\n/** Minimum height difference (px) to consider keyboard visible (avoids browser chrome false positives) */\nexport const KEYBOARD_VISIBILITY_THRESHOLD_PX = 100\n\n/** Gap (px) between pill and keyboard when keyboard is visible */\nexport const KEYBOARD_GAP_PX = 16\n\n/**\n * Drag interaction opacity configuration.\n * Lower opacity allows seeing content underneath while dragging (useful for mobile).\n */\nexport const DRAG_OPACITY = {\n\t/** Opacity while actively dragging (0.3 = mostly transparent to see underlying content) */\n\tdragging: 0.3,\n\t/** Normal opacity when not dragging */\n\tnormal: 1,\n} as const\n\n// ============================================================================\n// Full-Screen Mode Constants\n// ============================================================================\n\n/**\n * Full-screen mode sizing configuration.\n * Uses viewport units for responsive full-screen layout.\n */\nexport const FULL_SCREEN_CONFIG = {\n\t/** Maximum width of full-screen container */\n\tmaxWidth: '640px',\n\t/** Width as percentage of viewport */\n\twidthPercent: 95,\n\t/** Height as percentage of viewport */\n\theightPercent: 85,\n\t/** Padding inside the container */\n\tpadding: 16,\n} as const\n\n/**\n * Pinch gesture configuration for two-finger expand/collapse.\n */\nexport const PINCH_GESTURE_CONFIG = {\n\t/** Minimum scale change to trigger expand/collapse (30% = 0.3) */\n\tthreshold: 0.3,\n\t/** Minimum distance between fingers to start tracking (px) */\n\tminInitialDistance: 50,\n} as const\n\n// ============================================================================\n// Accessibility Constants\n// ============================================================================\n\n/** ARIA label IDs for accessibility */\nexport const ARIA_IDS = {\n\t/** ID for the pill dialog title (used with aria-labelledby) */\n\tpillTitle: 'agent-pill-title',\n\t/** ID for the pill dialog description (used with aria-describedby) */\n\tpillDescription: 'agent-pill-description',\n\t/** ID for the live region announcements */\n\tliveRegion: 'agent-pill-live-region',\n} as const\n\n/** ARIA labels for various UI elements */\nexport const ARIA_LABELS = {\n\topenAssistant: 'Open assistant',\n\tcloseAssistant: 'Close assistant',\n\tendVoiceSession: 'End voice session',\n\tdragHandle: 'Drag to reposition',\n\tsendMessage: 'Send message',\n\tvoiceInput: 'Start voice input',\n\texpandFullScreen: 'Expand to full screen',\n\tcollapseFullScreen: 'Collapse from full screen',\n} as const\n\n// ============================================================================\n// API Configuration\n// ============================================================================\n\n/** Production API base URL for WebMCP chat and token server */\nexport const WEBMCP_PRODUCTION_API_BASE = 'https://webmcp-agent-playground.alexmnahas.workers.dev'\n\n// ============================================================================\n// MCP Connection Constants\n// ============================================================================\n\n/** Maximum number of reconnection attempts before giving up */\nexport const MCP_MAX_RECONNECT_ATTEMPTS = 5\n\n/** Base delay in milliseconds for exponential backoff reconnection */\nexport const MCP_BASE_RECONNECT_DELAY_MS = 1000\n\n/** Maximum reconnect delay in milliseconds (caps exponential backoff) */\nexport const MCP_MAX_RECONNECT_DELAY_MS = 30000\n\n/** Delay before auto-connecting to tab-based MCP sources (allows server initialization) */\nexport const MCP_TAB_CONNECT_DELAY_MS = 100\n\n// ============================================================================\n// Voice Mode / Realtime API Constants\n// ============================================================================\n\n/** Number of frequency bins for audio visualization */\nexport const AUDIO_FREQUENCY_BINS = 32\n\n/** Default OpenAI Realtime model */\nexport const REALTIME_DEFAULT_MODEL = 'gpt-realtime'\n\n/** Default voice for OpenAI Realtime */\nexport const REALTIME_DEFAULT_VOICE = 'echo'\n\n/** Default OpenAI Realtime API URL */\nexport const REALTIME_DEFAULT_API_URL = 'https://api.openai.com/v1/realtime'\n\n/** Interval in milliseconds for audio visualization updates (~60fps) */\nexport const AUDIO_VISUALIZATION_INTERVAL_MS = 16\n\n/** Delay in milliseconds before requesting response after tool execution */\nexport const RESPONSE_REQUEST_DELAY_MS = 150\n\n/** Duration to show completed tool calls before clearing (success) */\nexport const TOOL_CALL_DISPLAY_DURATION_MS = 1500\n\n/** Duration to show failed tool calls before clearing (error) */\nexport const TOOL_CALL_ERROR_DISPLAY_DURATION_MS = 3000\n\n/** Duration to retain voice actions after session ends (for display) */\nexport const VOICE_ACTIONS_RETENTION_MS = 3000\n\n/** Duration to retain voice summary after session ends */\nexport const VOICE_SUMMARY_RETENTION_MS = 30000\n\n// ============================================================================\n// Voice Tool Approval Constants\n// ============================================================================\n\n/** Timeout before auto-deny when waiting for voice approval (30 seconds) */\nexport const VOICE_APPROVAL_TIMEOUT_MS = 30000\n\n/** Interval for countdown timer updates */\nexport const VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS = 1000\n\n/**\n * Keywords that trigger approval or denial.\n * Uses word boundary matching for safety (prevents \"yesterday\" matching \"yes\").\n */\nexport const VOICE_APPROVAL_KEYWORDS = {\n\tapprove: ['approve', 'yes', 'confirm', 'allow', 'go ahead', 'do it', 'proceed'],\n\tdeny: ['deny', 'no', 'cancel', 'stop', 'reject', \"don't\", 'dont'],\n} as const\n\n/**\n * Tool result messages for voice mode approvals.\n * Used when syncing voice approval results to the thread.\n */\nexport const VOICE_TOOL_RESULT_MESSAGES = {\n\t/** Message when tool was approved and executed in voice mode */\n\thandled: '[Handled in voice mode]',\n\t/** Message when voice session ended with pending approvals */\n\tsessionEnded: '[Voice session ended]',\n} as const\n\n// ============================================================================\n// Waveform Visualization Constants\n// ============================================================================\n\n/** Default history size for scrolling waveform mode */\nexport const WAVEFORM_HISTORY_SIZE = 60\n\n/** Update rate in milliseconds for waveform visualization */\nexport const WAVEFORM_UPDATE_RATE_MS = 30\n\n// ============================================================================\n// WebSocket States (for type-safe comparisons)\n// ============================================================================\n\n/** WebSocket OPEN state value */\nexport const WEBSOCKET_OPEN = 1\n\n// ============================================================================\n// Logging Configuration\n// ============================================================================\n\n/**\n * Enable debug logging for development.\n * Can be enabled by setting window.__WEBMCP_DEBUG__ = true in the browser console.\n * In production builds, this defaults to false.\n */\nexport const DEBUG_LOGGING_ENABLED =\n\ttypeof window !== 'undefined' &&\n\t(window as { __WEBMCP_DEBUG__?: boolean }).__WEBMCP_DEBUG__ === true\n\n/**\n * Conditional debug logger that only logs when DEBUG_LOGGING_ENABLED is true.\n * Can be enabled at runtime by setting window.__WEBMCP_DEBUG__ = true\n *\n * @param component - The component or service name for the log prefix\n * @param message - The log message\n * @param data - Optional data to include in the log\n */\nexport function debugLog(component: string, message: string, data?: unknown): void {\n\t// Check the flag at runtime to allow enabling after page load\n\tconst isDebugEnabled =\n\t\ttypeof window !== 'undefined' &&\n\t\t(window as { __WEBMCP_DEBUG__?: boolean }).__WEBMCP_DEBUG__ === true\n\n\tif (isDebugEnabled) {\n\t\tif (data !== undefined) {\n\t\t\tconsole.log(`[${component}] ${message}`, data)\n\t\t} else {\n\t\t\tconsole.log(`[${component}] ${message}`)\n\t\t}\n\t}\n}\n","import { clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nimport type { ClassValue } from 'clsx'\n\n/**\n * Merges Tailwind CSS classes with proper precedence handling.\n * Combines clsx for conditional classes and tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]): string {\n\treturn twMerge(clsx(inputs))\n}\n","'use client'\n\n/**\n * Markdown renderer for pill components.\n * Uses the same styling as the main MarkdownText but accepts content as a prop.\n */\nimport { memo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nimport { cn } from '../../lib/utils'\n\nimport type { FC, HTMLAttributes } from 'react'\nimport type { Components } from 'react-markdown'\n\ninterface PillMarkdownProps {\n\tcontent: string\n\tclassName?: string\n\t/** Compact mode uses smaller text and tighter spacing */\n\tcompact?: boolean\n}\n\ntype ElementProps = HTMLAttributes<HTMLElement>\n\n/**\n * Markdown component for rendering content within pill UI.\n * Supports GitHub-flavored markdown with compact styling option.\n */\nexport const PillMarkdown: FC<PillMarkdownProps> = memo(({ content, className, compact }) => {\n\tconst components: Components = {\n\t\th1: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<h1\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-h1 mb-3 scroll-m-20 font-extrabold tracking-tight last:mb-0',\n\t\t\t\t\tcompact ? 'text-base' : 'text-lg',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\th2: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<h2\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-h2 mt-3 mb-2 scroll-m-20 font-semibold tracking-tight first:mt-0 last:mb-0',\n\t\t\t\t\tcompact ? 'text-sm' : 'text-base',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\th3: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<h3\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-h3 mt-2 mb-1 scroll-m-20 font-semibold tracking-tight first:mt-0 last:mb-0',\n\t\t\t\t\tcompact ? 'text-sm' : 'text-[15px]',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tp: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<p\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-p leading-relaxed first:mt-0 last:mb-0',\n\t\t\t\t\tcompact ? 'text-xs my-1' : 'text-sm my-2',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\ta: ({ className: cn_, ...props }: HTMLAttributes<HTMLAnchorElement>) => (\n\t\t\t<a\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-a font-medium text-primary underline underline-offset-4 hover:text-primary/80',\n\t\t\t\t\tcompact ? 'text-xs' : 'text-sm',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tul: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<ul\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-ul ml-4 list-disc [&>li]:mt-0.5',\n\t\t\t\t\tcompact ? 'text-xs my-1' : 'text-sm my-2',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tol: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<ol\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-ol ml-4 list-decimal [&>li]:mt-0.5',\n\t\t\t\t\tcompact ? 'text-xs my-1' : 'text-sm my-2',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tli: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<li className={cn('aui-md-li', cn_)} {...props} />\n\t\t),\n\t\tblockquote: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<blockquote\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-blockquote border-l-2 border-white/20 pl-3 italic text-white/70',\n\t\t\t\t\tcompact ? 'text-xs' : 'text-sm',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tcode: ({ className: cn_, ...props }: ElementProps) => {\n\t\t\t// Check if this is inline code (no language class)\n\t\t\tconst isInline = !cn_?.includes('language-')\n\t\t\tif (isInline) {\n\t\t\t\treturn (\n\t\t\t\t\t<code\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'aui-md-inline-code rounded bg-white/10 px-1 py-0.5 font-mono',\n\t\t\t\t\t\t\tcompact ? 'text-[10px]' : 'text-xs',\n\t\t\t\t\t\t\tcn_\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<code\n\t\t\t\t\tclassName={cn('aui-md-code block font-mono', compact ? 'text-[10px]' : 'text-xs', cn_)}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t)\n\t\t},\n\t\tpre: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<pre\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-pre overflow-x-auto rounded-lg bg-black/30 p-2 my-2',\n\t\t\t\t\tcompact ? 'text-[10px]' : 'text-xs',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\thr: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<hr className={cn('aui-md-hr my-2 border-white/10', cn_)} {...props} />\n\t\t),\n\t\tstrong: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<strong className={cn('aui-md-strong font-semibold', cn_)} {...props} />\n\t\t),\n\t\tem: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<em className={cn('aui-md-em italic', cn_)} {...props} />\n\t\t),\n\t}\n\n\treturn (\n\t\t<div className={cn('aui-md pill-markdown', compact && 'pill-markdown-compact', className)}>\n\t\t\t<ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>\n\t\t\t\t{content}\n\t\t\t</ReactMarkdown>\n\t\t</div>\n\t)\n})\n\nPillMarkdown.displayName = 'PillMarkdown'\n","'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport { AlertCircle, Check, CheckCircle2, Copy } from 'lucide-react'\nimport { useCallback, useMemo, useState } from 'react'\n\nimport { UI_TIMING } from '../../lib/constants'\nimport { cn } from '../../lib/utils'\nimport { PillMarkdown } from './PillMarkdown'\n\nimport type { FC, ReactNode } from 'react'\n\ninterface SummaryBlockProps {\n\tsummary: string\n\tisSuccess?: boolean\n\tisError?: boolean\n\tactions?: QuickAction[]\n\tclassName?: string\n\t/** Full-screen mode - larger text, no height constraints (parent handles scrolling) */\n\tisFullScreen?: boolean\n}\n\ninterface QuickAction {\n\tlabel: string\n\tonClick: () => void\n\tvariant?: 'primary' | 'secondary'\n}\n\n/**\n * Summary block showing the agent's synthesized output.\n * Displayed after task completion instead of token streaming.\n * Uses compact styling with max-height and scrolling for long responses.\n */\nexport const SummaryBlock: FC<SummaryBlockProps> = ({\n\tsummary,\n\tisSuccess,\n\tisError,\n\tactions,\n\tclassName,\n\tisFullScreen = false,\n}) => {\n\tconst [copied, setCopied] = useState(false)\n\n\tconst handleCopy = useCallback(async () => {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(summary)\n\t\t\tsetCopied(true)\n\t\t\tsetTimeout(() => setCopied(false), UI_TIMING.copyFeedback)\n\t\t} catch {\n\t\t\t// Ignore clipboard errors\n\t\t}\n\t}, [summary])\n\n\treturn (\n\t\t<div className={cn('rounded-lg p-2 relative group', 'bg-white/5', className)}>\n\t\t\t{/* Copy button - visible on touch, appears on hover for desktop */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={(e) => {\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t\tvoid handleCopy()\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'absolute top-1.5 right-1.5 z-10',\n\t\t\t\t\t'p-1.5 sm:p-1 rounded',\n\t\t\t\t\t// On touch devices: always slightly visible. On hover devices: hidden until hover\n\t\t\t\t\t'opacity-50 sm:opacity-0 sm:group-hover:opacity-100',\n\t\t\t\t\t'hover:bg-white/10 active:bg-white/15',\n\t\t\t\t\t'text-white/40 hover:text-white/60',\n\t\t\t\t\t'transition-all duration-150'\n\t\t\t\t)}\n\t\t\t\taria-label={copied ? 'Copied!' : 'Copy response'}\n\t\t\t>\n\t\t\t\t{copied ? (\n\t\t\t\t\t<Check className=\"h-3.5 w-3.5 sm:h-3 sm:w-3 text-white/70\" />\n\t\t\t\t) : (\n\t\t\t\t\t<Copy className=\"h-3.5 w-3.5 sm:h-3 sm:w-3\" />\n\t\t\t\t)}\n\t\t\t</button>\n\n\t\t\t{/* Status header - compact */}\n\t\t\t{(isSuccess || isError) && (\n\t\t\t\t<div className=\"flex items-center gap-1.5 mb-1.5\">\n\t\t\t\t\t{isSuccess && <CheckCircle2 className=\"h-3.5 w-3.5 text-white/60\" />}\n\t\t\t\t\t{isError && <AlertCircle className=\"h-3.5 w-3.5 text-white/60\" />}\n\t\t\t\t\t<span className=\"text-[11px] font-medium text-white/70\">\n\t\t\t\t\t\t{isSuccess ? 'Done' : 'Error'}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Summary content - no height limit when full-screen (parent handles scrolling) */}\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'overflow-y-auto scrollbar-thin scroll-touch',\n\t\t\t\t\t!isFullScreen && 'max-h-32 sm:max-h-24'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<PillMarkdown content={summary} className=\"text-white/80\" compact={!isFullScreen} />\n\t\t\t</div>\n\n\t\t\t{/* Quick actions - compact */}\n\t\t\t{actions && actions.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-1.5 mt-2 pt-1.5 border-t border-white/5\">\n\t\t\t\t\t{actions.map((action, i) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\te.stopPropagation()\n\t\t\t\t\t\t\t\taction.onClick()\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'px-2 py-1 rounded text-[11px] font-medium',\n\t\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\t\taction.variant === 'primary'\n\t\t\t\t\t\t\t\t\t? 'bg-white/90 text-slate-900 hover:bg-white'\n\t\t\t\t\t\t\t\t\t: 'bg-white/10 text-white/70 hover:bg-white/15'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{action.label}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\ninterface TextPart {\n\ttype: 'text'\n\ttext: string\n}\n\n/**\n * Hook to get the latest summary from the thread\n * Returns the last text content from the last assistant message\n */\nexport function useLatestSummary(): string | null {\n\t// Use selector pattern to get messages reactively\n\tconst messages = useThread((thread) => thread.messages)\n\n\treturn useMemo(() => {\n\t\tif (!messages || messages.length === 0) return null\n\n\t\tconst lastAssistantMessage = [...messages].reverse().find((m) => m.role === 'assistant')\n\n\t\tif (!lastAssistantMessage) return null\n\n\t\t// Get the last text content\n\t\tconst textParts = lastAssistantMessage.content.filter((c): c is TextPart => c.type === 'text')\n\t\tconst lastText = textParts.at(-1)\n\n\t\tif (!lastText) return null\n\n\t\treturn lastText.text\n\t}, [messages])\n}\n\n/**\n * Welcome message for empty state\n */\nexport const WelcomeMessage: FC<{ className?: string }> = ({ className }) => {\n\treturn (\n\t\t<div className={cn('text-center py-4', className)}>\n\t\t\t<h3 className=\"text-lg font-semibold text-white mb-1\">Hello!</h3>\n\t\t\t<p className=\"text-sm text-white/60\">How can I help you today?</p>\n\t\t</div>\n\t)\n}\n\n/**\n * Wrapper for conditional content based on thread state\n */\nexport const ThreadContent: FC<{\n\tempty: ReactNode\n\trunning: ReactNode\n\tcomplete: ReactNode\n}> = ({ empty, running, complete }) => {\n\t// Use selector pattern to get messages reactively\n\tconst messages = useThread((thread) => thread.messages)\n\n\tif (!messages || messages.length === 0) {\n\t\treturn <>{empty}</>\n\t}\n\n\t// Check if currently running (last message is assistant and incomplete)\n\tconst lastMessage = messages.at(-1)\n\t// Status is an object with a type property, not a string\n\tconst isRunning = lastMessage?.role === 'assistant' && lastMessage.status?.type !== 'complete'\n\n\tif (isRunning) {\n\t\treturn <>{running}</>\n\t}\n\n\treturn <>{complete}</>\n}\n","/**\n * Formatting utilities for tool display\n *\n * Shared helpers for formatting tool names and arguments across components.\n */\n\n/**\n * Humanize tool name for display\n * Converts snake_case and camelCase to readable text.\n *\n * @param name - The tool name to humanize\n * @param progressive - If true, converts verb to progressive tense (e.g., \"searching\")\n *\n * @example\n * humanizeToolName('get_current_time') // 'Get current time'\n * humanizeToolName('deleteNote') // 'Delete note'\n * humanizeToolName('search_files', true) // 'Searching files'\n */\nexport function humanizeToolName(name: string, progressive = false): string {\n\t// Convert camelCase or snake_case to words\n\tconst words = name\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/_/g, ' ')\n\t\t.toLowerCase()\n\t\t.split(' ')\n\n\tif (words.length === 0) return name\n\n\tif (progressive) {\n\t\t// Make first word progressive (e.g., \"search\" -> \"Searching\")\n\t\tconst verb = words[0]\n\t\tconst progressiveVerb = verb.endsWith('e') ? verb.slice(0, -1) + 'ing' : verb + 'ing'\n\t\twords[0] = progressiveVerb.charAt(0).toUpperCase() + progressiveVerb.slice(1)\n\t} else {\n\t\t// Just capitalize first word\n\t\twords[0] = words[0].charAt(0).toUpperCase() + words[0].slice(1)\n\t}\n\n\treturn words.join(' ')\n}\n\n/**\n * Format tool arguments for display\n * Truncates long strings and formats objects as JSON\n *\n * @example\n * formatArgs({ name: 'test', count: 5 }) // 'name: \"test\"\\ncount: 5'\n */\nexport function formatArgs(args: Record<string, unknown>): string {\n\tconst entries = Object.entries(args)\n\tif (entries.length === 0) return 'No arguments'\n\n\treturn entries\n\t\t.map(([key, value]) => {\n\t\t\tconst displayValue =\n\t\t\t\ttypeof value === 'string'\n\t\t\t\t\t? value.length > 50\n\t\t\t\t\t\t? `\"${value.slice(0, 50)}...\"`\n\t\t\t\t\t\t: `\"${value}\"`\n\t\t\t\t\t: JSON.stringify(value)\n\t\t\treturn `${key}: ${displayValue}`\n\t\t})\n\t\t.join('\\n')\n}\n\n/**\n * Denial message constant\n * Used when user denies a tool execution\n */\nexport const TOOL_DENIED_MESSAGE = 'Tool execution denied by user'\n\n/**\n * Format a denial message with a user-provided reason.\n * Used when user wants to tell the agent what to do differently.\n *\n * @param reason - The user's feedback explaining what to do differently\n * @returns Formatted denial message with reason\n */\nexport function formatToolDenialWithReason(reason: string): string {\n\treturn `Tool denied: ${reason}`\n}\n","import { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { humanizeToolName } from '../lib/format'\n\nimport type { ToolCallMetadata } from '@mcp-b/cloud-mirror-types'\n\n/**\n * Represents a single action derived from a tool call.\n * Metadata (timing, source) is extracted from thread artifacts.\n */\nexport interface Action {\n\tid: string\n\tlabel: string\n\ttoolName: string\n\tstatus: 'running' | 'pending' | 'success' | 'error'\n\targs?: unknown\n\tresult?: unknown\n\terror?: string\n\t/** Timestamp when the tool call started (ms since epoch) */\n\tstartedAt?: number\n\t/** Duration of the tool call in milliseconds */\n\tduration?: number\n\t/** Source ID of the MCP server that handled the call */\n\tsourceId?: string\n\t/** Whether the tool call was aborted (e.g., tool removed during execution) */\n\twasAborted?: boolean\n}\n\ninterface ToolCallPart {\n\ttype: 'tool-call'\n\ttoolCallId: string\n\ttoolName: string\n\targs: unknown\n\tresult?: unknown\n\t// Status from assistant-ui\n\tstatus?: {\n\t\ttype: 'running' | 'complete' | 'incomplete' | 'requires-action'\n\t\terror?: unknown\n\t}\n\t/** Artifact containing ToolCallMetadata (timing, source info) */\n\tartifact?: unknown\n\tisError?: boolean\n}\n\n/**\n * Type guard to check if an artifact is ToolCallMetadata\n */\nfunction isToolCallMetadata(artifact: unknown): artifact is ToolCallMetadata {\n\tif (!artifact || typeof artifact !== 'object') return false\n\tconst a = artifact as Record<string, unknown>\n\treturn (\n\t\ttypeof a.startedAt === 'number' &&\n\t\ttypeof a.duration === 'number' &&\n\t\ttypeof a.sourceId === 'string'\n\t)\n}\n\n/**\n * Hook to derive actions from the current thread's tool calls\n *\n * Actions are a view of tool calls - not separate state.\n * This maintains compatibility with assistant-ui's data model.\n *\n * Metadata (timing, source info) is extracted from the artifact field\n * which is populated by MCPToolRegistry during tool execution.\n */\nexport function useActions(): Action[] {\n\t// Use selector pattern to get messages reactively\n\tconst messages = useThread((thread) => thread.messages)\n\n\treturn useMemo(() => {\n\t\tif (!messages || messages.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst actions: Action[] = []\n\n\t\tfor (const message of messages) {\n\t\t\tif (message.role !== 'assistant') continue\n\n\t\t\tfor (const part of message.content) {\n\t\t\t\tif (part.type !== 'tool-call') continue\n\n\t\t\t\tconst toolPart = part as ToolCallPart\n\t\t\t\tconst isComplete = toolPart.result !== undefined\n\t\t\t\tconst hasError =\n\t\t\t\t\ttoolPart.isError === true ||\n\t\t\t\t\t(toolPart.result &&\n\t\t\t\t\t\ttypeof toolPart.result === 'object' &&\n\t\t\t\t\t\t'error' in (toolPart.result as Record<string, unknown>))\n\n\t\t\t\t// Check for requires-action status (HITL pattern)\n\t\t\t\tconst requiresAction = toolPart.status?.type === 'requires-action'\n\n\t\t\t\tlet status: Action['status']\n\t\t\t\tif (hasError) {\n\t\t\t\t\tstatus = 'error'\n\t\t\t\t} else if (isComplete) {\n\t\t\t\t\tstatus = 'success'\n\t\t\t\t} else if (requiresAction) {\n\t\t\t\t\tstatus = 'pending' // Waiting for user approval\n\t\t\t\t} else {\n\t\t\t\t\tstatus = 'running'\n\t\t\t\t}\n\n\t\t\t\t// Extract metadata from artifact if available\n\t\t\t\tconst metadata = isToolCallMetadata(toolPart.artifact) ? toolPart.artifact : undefined\n\n\t\t\t\tactions.push({\n\t\t\t\t\tid: toolPart.toolCallId,\n\t\t\t\t\ttoolName: toolPart.toolName,\n\t\t\t\t\tlabel: humanizeToolName(toolPart.toolName, status === 'running'),\n\t\t\t\t\tstatus,\n\t\t\t\t\targs: toolPart.args,\n\t\t\t\t\tresult: toolPart.result,\n\t\t\t\t\terror: hasError ? String((toolPart.result as Record<string, unknown>).error) : undefined,\n\t\t\t\t\t// Populate from artifact metadata\n\t\t\t\t\tstartedAt: metadata?.startedAt,\n\t\t\t\t\tduration: metadata?.duration,\n\t\t\t\t\tsourceId: metadata?.sourceId,\n\t\t\t\t\twasAborted: metadata?.wasAborted,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\treturn actions\n\t}, [messages])\n}\n\n/**\n * Hook to get the current running action (if any)\n */\nexport function useCurrentAction(): Action | null {\n\tconst actions = useActions()\n\treturn actions.find((a) => a.status === 'running') ?? null\n}\n\n/**\n * Hook to get recently completed actions\n */\nexport function useRecentActions(limit = 3): Action[] {\n\tconst actions = useActions()\n\treturn actions.filter((a) => a.status === 'success' || a.status === 'error').slice(-limit)\n}\n\n/**\n * Hook to get the last completed action (success or error)\n */\nexport function useLastCompletedAction(): Action | null {\n\tconst actions = useActions()\n\tconst completed = actions.filter((a) => a.status === 'success' || a.status === 'error')\n\treturn completed.at(-1) ?? null\n}\n","/**\n * MCP Transport Utilities\n *\n * Shared transport creation logic for MCP sources.\n * This eliminates duplication between MCPToolsProvider and useMCPSource.\n */\nimport { TabClientTransport } from '@mcp-b/transports'\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\n\nimport type { MCPSourceConfig } from '@mcp-b/cloud-mirror-types'\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'\n\n/**\n * Transport type options for HTTP-based connections\n */\nexport type TransportType = 'http' | 'sse'\n\n/**\n * Creates the appropriate MCP transport based on source configuration.\n *\n * @param config - The MCP source configuration\n * @param transportType - For HTTP sources, specifies whether to use HTTP or SSE transport\n * @returns A configured MCP Transport instance\n *\n * @example Tab-based transport (same-tab or iframe)\n * ```ts\n * const transport = createMCPTransport({ type: 'tab' })\n * ```\n *\n * @example HTTP transport with auth\n * ```ts\n * const transport = createMCPTransport({\n * type: 'http',\n * url: 'https://example.com/mcp',\n * authToken: 'secret'\n * }, 'http')\n * ```\n */\nexport function createMCPTransport(\n\tconfig: MCPSourceConfig,\n\ttransportType: TransportType = 'http'\n): Transport {\n\tif (config.type === 'tab') {\n\t\treturn new TabClientTransport({\n\t\t\ttargetOrigin: config.targetOrigin ?? window.location.origin,\n\t\t\tchannelId: config.channelId ?? 'mcp-default',\n\t\t})\n\t}\n\n\t// HTTP/SSE transport configuration\n\tconst serverUrl = new URL(config.url)\n\tconst headers: Record<string, string> = {\n\t\tAccept: 'application/json, text/event-stream',\n\t\t...(config.customHeaders ?? {}),\n\t}\n\n\tif (config.authToken) {\n\t\theaders.Authorization = `Bearer ${config.authToken}`\n\t}\n\n\tconst transportOptions = {\n\t\trequestInit: { headers },\n\t}\n\n\tif (transportType === 'sse') {\n\t\treturn new SSEClientTransport(serverUrl, transportOptions)\n\t}\n\n\treturn new StreamableHTTPClientTransport(serverUrl, transportOptions)\n}\n\n/**\n * Check if an error indicates we should try SSE fallback.\n *\n * This handles cases where HTTP streaming isn't supported (404/405) or\n * when the connection fails due to CORS/network issues.\n *\n * @param error - The error from the failed HTTP connection\n * @returns true if the error suggests trying SSE transport instead\n */\nexport function shouldFallbackToSSE(error: Error): boolean {\n\tconst message = error.message\n\treturn (\n\t\tmessage.includes('404') ||\n\t\tmessage.includes('Not Found') ||\n\t\tmessage.includes('405') ||\n\t\tmessage.includes('Method Not Allowed') ||\n\t\tmessage === 'Failed to fetch' || // Chrome CORS\n\t\tmessage === 'NetworkError when attempting to fetch resource.' || // Firefox\n\t\tmessage === 'Load failed' // Safari\n\t)\n}\n\n/**\n * Calculate exponential backoff delay for reconnection attempts.\n *\n * @param attempt - The current attempt number (0-based)\n * @param baseDelay - Base delay in milliseconds\n * @param maxDelay - Maximum delay cap in milliseconds\n * @returns The calculated delay in milliseconds\n */\nexport function calculateReconnectDelay(\n\tattempt: number,\n\tbaseDelay: number,\n\tmaxDelay: number\n): number {\n\treturn Math.min(baseDelay * Math.pow(2, attempt), maxDelay)\n}\n","/**\n * MCP Tools Provider\n *\n * Simplified provider for managing tools from multiple MCP sources.\n * Sources can be tab-based (same-tab, iframes) or HTTP-based (remote servers).\n *\n * @example Basic usage\n * ```tsx\n * <MCPToolsProvider>\n * <App />\n * </MCPToolsProvider>\n * ```\n *\n * @example Using the hook\n * ```tsx\n * const { tools, addSource, callTool } = useMCPTools()\n * await addSource('remote', { type: 'http', url: 'http://localhost:8888/mcp' })\n * ```\n */\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport {\n\tPromptListChangedNotificationSchema,\n\tToolListChangedNotificationSchema,\n} from '@modelcontextprotocol/sdk/types.js'\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { MCP_TAB_CONNECT_DELAY_MS } from '../lib/constants'\nimport { createMCPTransport } from '../lib/mcp-transport'\n\nimport type {\n\tCallToolResult,\n\tGetPromptResult,\n\tMCPSource,\n\tMCPSourceConfig,\n\tPrompt,\n\tResource,\n\tResourceTemplate,\n\tToolWithSource,\n} from '@mcp-b/cloud-mirror-types'\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'\nimport type { ReactNode } from 'react'\n\n/** Well-known source IDs */\nexport const SOURCE_LOCAL = 'local'\nexport const SOURCE_REMOTE = 'remote'\n\n/** Internal source state with client reference */\ninterface SourceState extends Omit<MCPSource, 'resources' | 'resourceTemplates' | 'prompts'> {\n\tclient: Client | null\n\ttransport: Transport | null\n\tresources: Resource[]\n\tresourceTemplates: ResourceTemplate[]\n\tprompts: Prompt[]\n}\n\n/**\n * Tracks an in-flight tool call with its abort controller.\n *\n * Note: Aborting a call only affects the caller side (the promise race).\n * The underlying tool execution in the MCP server/handler may continue\n * to completion - this is a limitation of the MCP protocol which doesn't\n * support cancellation. The abort ensures the caller gets a timely error\n * response rather than waiting for a tool that's no longer relevant.\n */\ninterface InflightToolCall {\n\t/** The tool name being called */\n\ttoolName: string\n\t/** The source ID the tool belongs to */\n\tsourceId: string\n\t/** Abort controller to cancel the call */\n\tabortController: AbortController\n}\n\n/**\n * MCP Tools Context Value\n */\nexport interface MCPToolsContextValue {\n\t/** All tools from all sources, tagged with _sourceId */\n\ttools: ToolWithSource[]\n\n\t/** All prompts from all sources */\n\tprompts: Prompt[]\n\n\t/** All sources and their states */\n\tsources: Map<string, MCPSource>\n\n\t/** Add a new source */\n\taddSource: (id: string, config: MCPSourceConfig) => Promise<void>\n\n\t/** Remove a source */\n\tremoveSource: (id: string) => Promise<void>\n\n\t/** Get a specific source */\n\tgetSource: (id: string) => MCPSource | undefined\n\n\t/** Check if a source is connected */\n\tisConnected: (id: string) => boolean\n\n\t/** Call a tool (auto-routes based on tool name lookup) */\n\tcallTool: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>\n\n\t/** Call a tool on a specific source */\n\tcallToolOnSource: (\n\t\tsourceId: string,\n\t\tname: string,\n\t\targs: Record<string, unknown>\n\t) => Promise<CallToolResult>\n\n\t/** Get a prompt's expanded content (auto-routes based on prompt name lookup) */\n\tgetPrompt: (name: string, args?: Record<string, string>) => Promise<GetPromptResult>\n}\n\nconst MCPToolsContext = createContext<MCPToolsContextValue | null>(null)\n\nexport interface MCPToolsProviderProps {\n\tchildren: ReactNode\n\t/** Auto-connect to same-tab source on mount (default: true) */\n\tautoConnectLocal?: boolean\n\t/** Callback when tools change */\n\tonToolsChange?: (tools: ToolWithSource[]) => void\n\t/** Callback when prompts change */\n\tonPromptsChange?: (prompts: Prompt[]) => void\n}\n\nexport function MCPToolsProvider({\n\tchildren,\n\tautoConnectLocal = true,\n\tonToolsChange,\n\tonPromptsChange,\n}: MCPToolsProviderProps) {\n\t// Sources map (internal state with client references)\n\tconst sourcesRef = useRef<Map<string, SourceState>>(new Map())\n\n\t// Track in-flight tool calls for abort handling\n\tconst inflightCallsRef = useRef<Map<string, InflightToolCall>>(new Map())\n\n\t// Counter for generating unique call IDs\n\tconst callIdCounterRef = useRef(0)\n\n\t// Trigger re-renders when sources change\n\tconst [, forceUpdate] = useState({})\n\n\t// Derived tools list\n\tconst [toolsList, setToolsList] = useState<ToolWithSource[]>([])\n\n\t// Derived prompts list\n\tconst [promptsList, setPromptsList] = useState<Prompt[]>([])\n\n\t/**\n\t * Abort in-flight tool calls for tools that are no longer available.\n\t * Called after the tool list changes to clean up orphaned calls.\n\t */\n\tconst abortOrphanedCalls = useCallback((currentTools: ToolWithSource[]) => {\n\t\tconst currentToolNames = new Set(currentTools.map((t) => t.name))\n\n\t\tinflightCallsRef.current.forEach((call, callId) => {\n\t\t\tif (!currentToolNames.has(call.toolName)) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[MCPToolsProvider] Aborting orphaned tool call: ${call.toolName} (call ID: ${callId})`\n\t\t\t\t)\n\t\t\t\tcall.abortController.abort(new Error(`Tool '${call.toolName}' is no longer available`))\n\t\t\t\tinflightCallsRef.current.delete(callId)\n\t\t\t}\n\t\t})\n\t}, [])\n\n\t/**\n\t * Rebuild tools list from all sources\n\t */\n\tconst rebuildTools = useCallback(() => {\n\t\tconst allTools: ToolWithSource[] = []\n\n\t\tsourcesRef.current.forEach((source) => {\n\t\t\tsource.tools.forEach((tool) => {\n\t\t\t\tallTools.push({\n\t\t\t\t\t...tool,\n\t\t\t\t\t_sourceId: source.id,\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\n\t\t// Abort any in-flight calls for tools that are no longer in the list\n\t\tabortOrphanedCalls(allTools)\n\n\t\tsetToolsList(allTools)\n\t}, [abortOrphanedCalls])\n\n\t/**\n\t * Rebuild prompts list from all sources\n\t */\n\tconst rebuildPrompts = useCallback(() => {\n\t\tconst allPrompts: Prompt[] = []\n\n\t\tsourcesRef.current.forEach((source) => {\n\t\t\tsource.prompts.forEach((prompt) => {\n\t\t\t\tallPrompts.push(prompt)\n\t\t\t})\n\t\t})\n\n\t\tsetPromptsList(allPrompts)\n\t}, [])\n\n\t/**\n\t * Get public source state (without client reference)\n\t */\n\tconst getPublicSource = useCallback((source: SourceState): MCPSource => {\n\t\treturn {\n\t\t\tid: source.id,\n\t\t\tconfig: source.config,\n\t\t\tstate: source.state,\n\t\t\terror: source.error,\n\t\t\ttools: source.tools,\n\t\t\tresources: source.resources,\n\t\t\tresourceTemplates: source.resourceTemplates,\n\t\t\tprompts: source.prompts,\n\t\t}\n\t}, [])\n\n\t/**\n\t * Add a new source\n\t */\n\tconst addSource = useCallback(\n\t\tasync (id: string, config: MCPSourceConfig): Promise<void> => {\n\t\t\t// Remove existing source if any\n\t\t\tif (sourcesRef.current.has(id)) {\n\t\t\t\tawait removeSource(id)\n\t\t\t}\n\n\t\t\t// Create initial state\n\t\t\tconst sourceState: SourceState = {\n\t\t\t\tid,\n\t\t\t\tconfig,\n\t\t\t\tstate: 'connecting',\n\t\t\t\terror: null,\n\t\t\t\ttools: [],\n\t\t\t\tresources: [],\n\t\t\t\tresourceTemplates: [],\n\t\t\t\tprompts: [],\n\t\t\t\tclient: null,\n\t\t\t\ttransport: null,\n\t\t\t}\n\n\t\t\tsourcesRef.current.set(id, sourceState)\n\t\t\tforceUpdate({})\n\n\t\t\ttry {\n\t\t\t\t// Create client and transport\n\t\t\t\tconst client = new Client({\n\t\t\t\t\tname: `MCP-Source-${id}`,\n\t\t\t\t\tversion: '1.0.0',\n\t\t\t\t})\n\n\t\t\t\tconst transport = createMCPTransport(config)\n\n\t\t\t\t// Connect\n\t\t\t\tawait client.connect(transport)\n\n\t\t\t\t// Update state with client\n\t\t\t\tsourceState.client = client\n\t\t\t\tsourceState.transport = transport\n\n\t\t\t\t// Get initial tools and prompts\n\t\t\t\tconst { tools } = await client.listTools()\n\t\t\t\tsourceState.tools = tools\n\n\t\t\t\t// Get initial prompts (wrapped in try-catch as some servers may not support prompts)\n\t\t\t\ttry {\n\t\t\t\t\tconst { prompts } = await client.listPrompts()\n\t\t\t\t\tsourceState.prompts = prompts\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.warn(`[MCPToolsProvider:${id}] Server does not support prompts:`, err)\n\t\t\t\t\tsourceState.prompts = []\n\t\t\t\t}\n\n\t\t\t\tsourceState.state = 'connected'\n\n\t\t\t\t// Listen for tool updates\n\t\t\t\tclient.setNotificationHandler(ToolListChangedNotificationSchema, async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst updated = await client.listTools()\n\t\t\t\t\t\tsourceState.tools = updated.tools\n\t\t\t\t\t\trebuildTools()\n\t\t\t\t\t\tforceUpdate({})\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Failed to update tools:`, err)\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\t// Listen for prompt updates\n\t\t\t\tclient.setNotificationHandler(PromptListChangedNotificationSchema, async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst updated = await client.listPrompts()\n\t\t\t\t\t\tsourceState.prompts = updated.prompts\n\t\t\t\t\t\trebuildPrompts()\n\t\t\t\t\t\tforceUpdate({})\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Failed to update prompts:`, err)\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\trebuildTools()\n\t\t\t\trebuildPrompts()\n\t\t\t\tforceUpdate({})\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error(String(err))\n\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Connection failed:`, error)\n\n\t\t\t\tsourceState.state = 'error'\n\t\t\t\tsourceState.error = error\n\t\t\t\tforceUpdate({})\n\t\t\t}\n\t\t},\n\t\t[rebuildTools, rebuildPrompts]\n\t)\n\n\t/**\n\t * Remove a source\n\t */\n\tconst removeSource = useCallback(\n\t\tasync (id: string): Promise<void> => {\n\t\t\tconst source = sourcesRef.current.get(id)\n\t\t\tif (!source) return\n\n\t\t\t// Close client and transport\n\t\t\tif (source.client) {\n\t\t\t\ttry {\n\t\t\t\t\tawait source.client.close()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Error closing client:`, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (source.transport) {\n\t\t\t\ttry {\n\t\t\t\t\tawait source.transport.close()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Error closing transport:`, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsourcesRef.current.delete(id)\n\t\t\trebuildTools()\n\t\t\trebuildPrompts()\n\t\t\tforceUpdate({})\n\t\t},\n\t\t[rebuildTools, rebuildPrompts]\n\t)\n\n\t/**\n\t * Get a source by ID\n\t */\n\tconst getSource = useCallback(\n\t\t(id: string): MCPSource | undefined => {\n\t\t\tconst source = sourcesRef.current.get(id)\n\t\t\treturn source ? getPublicSource(source) : undefined\n\t\t},\n\t\t[getPublicSource]\n\t)\n\n\t/**\n\t * Check if a source is connected\n\t */\n\tconst isConnected = useCallback((id: string): boolean => {\n\t\tconst source = sourcesRef.current.get(id)\n\t\treturn source?.state === 'connected'\n\t}, [])\n\n\t/**\n\t * Call a tool on a specific source with in-flight tracking and abort support.\n\t * If the tool is removed while the call is in progress, the call will be aborted.\n\t */\n\tconst callToolOnSource = useCallback(\n\t\tasync (\n\t\t\tsourceId: string,\n\t\t\tname: string,\n\t\t\targs: Record<string, unknown>\n\t\t): Promise<CallToolResult> => {\n\t\t\tconst source = sourcesRef.current.get(sourceId)\n\t\t\tif (!source?.client) {\n\t\t\t\tthrow new Error(`Source '${sourceId}' not connected`)\n\t\t\t}\n\n\t\t\t// Generate unique call ID and create abort controller\n\t\t\tconst callId = `${sourceId}-${name}-${++callIdCounterRef.current}`\n\t\t\tconst abortController = new AbortController()\n\n\t\t\t// Register in-flight call\n\t\t\tinflightCallsRef.current.set(callId, {\n\t\t\t\ttoolName: name,\n\t\t\t\tsourceId,\n\t\t\t\tabortController,\n\t\t\t})\n\n\t\t\ttry {\n\t\t\t\t// Create a promise that rejects when aborted\n\t\t\t\tconst abortPromise = new Promise<never>((_, reject) => {\n\t\t\t\t\tconst signal = abortController.signal\n\n\t\t\t\t\t// Handle already-aborted signal (race condition prevention)\n\t\t\t\t\tif (signal.aborted) {\n\t\t\t\t\t\treject(signal.reason || new Error(`Tool '${name}' call was aborted`))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Use { once: true } to auto-cleanup the listener\n\t\t\t\t\tsignal.addEventListener(\n\t\t\t\t\t\t'abort',\n\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\treject(signal.reason || new Error(`Tool '${name}' call was aborted`))\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ once: true }\n\t\t\t\t\t)\n\t\t\t\t})\n\n\t\t\t\t// Race between the actual tool call and the abort signal\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tsource.client.callTool({ name, arguments: args }),\n\t\t\t\t\tabortPromise,\n\t\t\t\t])\n\n\t\t\t\treturn result as CallToolResult\n\t\t\t} catch (error) {\n\t\t\t\t// Check if this was an abort\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\t// Return an error result for aborted calls\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text' as const,\n\t\t\t\t\t\t\t\ttext: `Tool call aborted: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\t// Clean up the in-flight tracking\n\t\t\t\tinflightCallsRef.current.delete(callId)\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\t/**\n\t * Call a tool (auto-routes based on tool name)\n\t */\n\tconst callTool = useCallback(\n\t\tasync (name: string, args: Record<string, unknown>): Promise<CallToolResult> => {\n\t\t\t// Find which source has this tool\n\t\t\tconst tool = toolsList.find((t) => t.name === name)\n\t\t\tif (!tool) {\n\t\t\t\tthrow new Error(`Tool '${name}' not found`)\n\t\t\t}\n\n\t\t\treturn callToolOnSource(tool._sourceId, name, args)\n\t\t},\n\t\t[toolsList, callToolOnSource]\n\t)\n\n\t/**\n\t * Get a prompt's expanded content (auto-routes based on prompt name)\n\t */\n\tconst getPrompt = useCallback(\n\t\tasync (name: string, args?: Record<string, string>): Promise<GetPromptResult> => {\n\t\t\t// Find which source has this prompt\n\t\t\tfor (const source of sourcesRef.current.values()) {\n\t\t\t\tconst hasPrompt = source.prompts.some((p) => p.name === name)\n\t\t\t\tif (hasPrompt && source.client) {\n\t\t\t\t\treturn (await source.client.getPrompt({ name, arguments: args })) as GetPromptResult\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(`Prompt '${name}' not found`)\n\t\t},\n\t\t[]\n\t)\n\n\t/**\n\t * Get sources map for context (public view).\n\t *\n\t * Note: This useMemo reads from sourcesRef but depends on toolsList/promptsList.\n\t * This is intentional - toolsList and promptsList are derived from sourcesRef,\n\t * so when they change, it means sourcesRef has changed and we need to rebuild\n\t * the public view. This avoids exposing sourcesRef as a dependency while still\n\t * triggering recomputation when source data changes.\n\t */\n\tconst sources = useMemo(() => {\n\t\tconst publicSources = new Map<string, MCPSource>()\n\t\tsourcesRef.current.forEach((source) => {\n\t\t\tpublicSources.set(source.id, getPublicSource(source))\n\t\t})\n\t\treturn publicSources\n\t}, [toolsList, promptsList, getPublicSource])\n\n\t// Auto-connect to local source on mount\n\tuseEffect(() => {\n\t\tif (autoConnectLocal) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tvoid addSource(SOURCE_LOCAL, { type: 'tab' })\n\t\t\t}, MCP_TAB_CONNECT_DELAY_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [autoConnectLocal, addSource])\n\n\t// Notify on tools change\n\tuseEffect(() => {\n\t\tonToolsChange?.(toolsList)\n\t}, [toolsList, onToolsChange])\n\n\t// Notify on prompts change\n\tuseEffect(() => {\n\t\tonPromptsChange?.(promptsList)\n\t}, [promptsList, onPromptsChange])\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\tconst sources = sourcesRef\n\t\tconst inflightCalls = inflightCallsRef\n\t\treturn () => {\n\t\t\t// Abort all in-flight tool calls\n\t\t\t// Note: We iterate first, then clear - don't mutate during iteration\n\t\t\tinflightCalls.current.forEach((call) => {\n\t\t\t\tcall.abortController.abort(new Error('Provider unmounted'))\n\t\t\t})\n\t\t\tinflightCalls.current.clear()\n\n\t\t\t// Close all source connections\n\t\t\tsources.current.forEach((source) => {\n\t\t\t\tif (source.client) {\n\t\t\t\t\tvoid source.client.close().catch(console.error)\n\t\t\t\t}\n\t\t\t\tif (source.transport) {\n\t\t\t\t\tvoid source.transport.close().catch(console.error)\n\t\t\t\t}\n\t\t\t})\n\t\t\tsources.current.clear()\n\t\t}\n\t}, [])\n\n\tconst value = useMemo<MCPToolsContextValue>(\n\t\t() => ({\n\t\t\ttools: toolsList,\n\t\t\tprompts: promptsList,\n\t\t\tsources,\n\t\t\taddSource,\n\t\t\tremoveSource,\n\t\t\tgetSource,\n\t\t\tisConnected,\n\t\t\tcallTool,\n\t\t\tcallToolOnSource,\n\t\t\tgetPrompt,\n\t\t}),\n\t\t[\n\t\t\ttoolsList,\n\t\t\tpromptsList,\n\t\t\tsources,\n\t\t\taddSource,\n\t\t\tremoveSource,\n\t\t\tgetSource,\n\t\t\tisConnected,\n\t\t\tcallTool,\n\t\t\tcallToolOnSource,\n\t\t\tgetPrompt,\n\t\t]\n\t)\n\n\treturn <MCPToolsContext.Provider value={value}>{children}</MCPToolsContext.Provider>\n}\n\n/**\n * Hook to access MCP Tools context\n */\nexport function useMCPTools(): MCPToolsContextValue {\n\tconst context = useContext(MCPToolsContext)\n\tif (!context) {\n\t\tthrow new Error('useMCPTools must be used within an MCPToolsProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access MCP Tools context\n */\nexport function useOptionalMCPTools(): MCPToolsContextValue | null {\n\treturn useContext(MCPToolsContext)\n}\n","/**\n * Thread Utilities\n *\n * Shared utilities for working with assistant-ui thread state.\n * These functions provide a non-reactive way to query and modify thread state,\n * suitable for use in callbacks and effects.\n *\n * For reactive hooks, see usePendingToolCalls.ts which wraps these utilities.\n */\n\nimport type { ThreadAssistantMessage, ThreadRuntime } from '@assistant-ui/react'\n\n/**\n * Information about a pending tool call that requires user approval\n */\nexport interface PendingToolCallInfo {\n\tmessageId: string\n\ttoolCallId: string\n\ttoolName: string\n\targs: Record<string, unknown>\n}\n\n/**\n * Find all pending tool calls in a thread.\n *\n * This is a non-reactive utility for use in callbacks.\n * For reactive state, use usePendingToolCalls() hook instead.\n *\n * @param threadRuntime - The thread runtime to query\n * @returns Array of pending tool calls with their metadata\n */\nexport function getPendingToolCalls(threadRuntime: ThreadRuntime): PendingToolCallInfo[] {\n\tconst messages = threadRuntime.getState().messages\n\tconst result: PendingToolCallInfo[] = []\n\n\tfor (const msg of messages) {\n\t\t// Only assistant messages can have tool calls\n\t\tif (msg.role !== 'assistant') continue\n\n\t\t// Cast to assistant message to access status\n\t\tconst assistantMsg = msg as ThreadAssistantMessage\n\n\t\t// Only process messages waiting for tool results\n\t\tif (assistantMsg.status?.type !== 'requires-action') continue\n\n\t\t// Find tool-call parts without results\n\t\tfor (const part of assistantMsg.content) {\n\t\t\tif (part.type !== 'tool-call') continue\n\t\t\tif (part.result !== undefined) continue\n\n\t\t\tresult.push({\n\t\t\t\tmessageId: msg.id,\n\t\t\t\ttoolCallId: part.toolCallId,\n\t\t\t\ttoolName: part.toolName,\n\t\t\t\targs: (part.args as Record<string, unknown>) ?? {},\n\t\t\t})\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Find pending tool calls matching a specific tool name.\n *\n * @param threadRuntime - The thread runtime to query\n * @param toolName - The tool name to filter by\n * @returns Array of matching pending tool calls\n */\nexport function getPendingToolCallsByName(\n\tthreadRuntime: ThreadRuntime,\n\ttoolName: string\n): PendingToolCallInfo[] {\n\treturn getPendingToolCalls(threadRuntime).filter((tc) => tc.toolName === toolName)\n}\n\n/**\n * Resolve a pending tool call by adding a result.\n *\n * @param threadRuntime - The thread runtime\n * @param messageId - The message ID containing the tool call\n * @param toolCallId - The specific tool call ID to resolve\n * @param result - The result string to add\n * @returns true if resolved successfully, false if tool call not found\n */\nexport function resolvePendingToolCall(\n\tthreadRuntime: ThreadRuntime,\n\tmessageId: string,\n\ttoolCallId: string,\n\tresult: string\n): boolean {\n\tconst messageRuntime = threadRuntime.getMessageById(messageId)\n\tconst partRuntime = messageRuntime?.getMessagePartByToolCallId(toolCallId)\n\n\tif (partRuntime) {\n\t\tpartRuntime.addToolResult(result)\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * Resolve all pending tool calls matching a tool name.\n *\n * @param threadRuntime - The thread runtime\n * @param toolName - The tool name to match\n * @param result - The result string to add to all matches\n * @returns Number of tool calls resolved\n */\nexport function resolveAllPendingToolCallsByName(\n\tthreadRuntime: ThreadRuntime,\n\ttoolName: string,\n\tresult: string\n): number {\n\tconst pendingCalls = getPendingToolCallsByName(threadRuntime, toolName)\n\tlet resolved = 0\n\n\tfor (const call of pendingCalls) {\n\t\tif (resolvePendingToolCall(threadRuntime, call.messageId, call.toolCallId, result)) {\n\t\t\tresolved++\n\t\t}\n\t}\n\n\treturn resolved\n}\n\n/**\n * Resolve all pending tool calls in the thread.\n *\n * @param threadRuntime - The thread runtime\n * @param result - The result string to add to all pending calls\n * @returns Number of tool calls resolved\n */\nexport function resolveAllPendingToolCalls(threadRuntime: ThreadRuntime, result: string): number {\n\tconst pendingCalls = getPendingToolCalls(threadRuntime)\n\tlet resolved = 0\n\n\tfor (const call of pendingCalls) {\n\t\tif (resolvePendingToolCall(threadRuntime, call.messageId, call.toolCallId, result)) {\n\t\t\tresolved++\n\t\t}\n\t}\n\n\treturn resolved\n}\n","/**\n * Tool Approval Provider\n *\n * Manages user preferences for destructive tool approval.\n * When mode is 'ask', tools with destructiveHint: true require user confirmation.\n * When mode is 'auto', all tools execute immediately.\n *\n * @example\n * ```tsx\n * <ToolApprovalProvider>\n * <App />\n * </ToolApprovalProvider>\n *\n * // In a component:\n * const { mode, setMode, requiresApproval } = useToolApproval()\n * ```\n */\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'\n\nimport type { Tool, ToolApprovalMode, ToolApprovalSettings } from '@mcp-b/cloud-mirror-types'\nimport type { ReactNode } from 'react'\n\nconst STORAGE_KEY = 'webmcp-tool-approval-mode'\nconst DEFAULT_MODE: ToolApprovalMode = 'ask'\n\n/**\n * Tool Approval Context Value\n */\nexport interface ToolApprovalContextValue extends ToolApprovalSettings {\n\t/** Set the approval mode */\n\tsetMode: (mode: ToolApprovalMode) => void\n\t/** Toggle between 'auto' and 'ask' modes */\n\ttoggleMode: () => void\n\t/** Check if a specific tool requires approval based on its annotations */\n\trequiresApproval: (tool: Tool) => boolean\n\t/** Check if a tool is considered destructive based on its annotations */\n\tisDestructive: (tool: Tool) => boolean\n}\n\nconst ToolApprovalContext = createContext<ToolApprovalContextValue | null>(null)\n\nexport interface ToolApprovalProviderProps {\n\tchildren: ReactNode\n\t/** Initial mode (overrides stored preference) */\n\tdefaultMode?: ToolApprovalMode\n\t/** Disable localStorage persistence */\n\tdisablePersistence?: boolean\n\t/** Callback when mode changes */\n\tonModeChange?: (mode: ToolApprovalMode) => void\n}\n\n/**\n * Check if a tool is destructive based on MCP annotations.\n *\n * A tool is considered destructive if:\n * - It has destructiveHint: true explicitly set, OR\n * - It is NOT read-only (readOnlyHint is false or undefined) AND destructiveHint is not false\n *\n * This follows the MCP spec where destructiveHint defaults to true for non-read-only tools.\n */\nfunction checkIsDestructive(tool: Tool): boolean {\n\tconst annotations = tool.annotations\n\n\t// If no annotations, default to destructive (MCP spec default)\n\tif (!annotations) {\n\t\treturn true\n\t}\n\n\t// If explicitly marked as read-only, it's not destructive\n\tif (annotations.readOnlyHint === true) {\n\t\treturn false\n\t}\n\n\t// If destructiveHint is explicitly set, use that value\n\tif (typeof annotations.destructiveHint === 'boolean') {\n\t\treturn annotations.destructiveHint\n\t}\n\n\t// Default: non-read-only tools are considered potentially destructive\n\treturn true\n}\n\nexport function ToolApprovalProvider({\n\tchildren,\n\tdefaultMode,\n\tdisablePersistence = false,\n\tonModeChange,\n}: ToolApprovalProviderProps) {\n\t// Initialize mode from storage or default\n\tconst [mode, setModeState] = useState<ToolApprovalMode>(() => {\n\t\tif (defaultMode) return defaultMode\n\t\tif (disablePersistence) return DEFAULT_MODE\n\n\t\ttry {\n\t\t\tconst stored = localStorage.getItem(STORAGE_KEY)\n\t\t\tif (stored === 'auto' || stored === 'ask') {\n\t\t\t\treturn stored\n\t\t\t}\n\t\t} catch {\n\t\t\t// localStorage not available\n\t\t}\n\t\treturn DEFAULT_MODE\n\t})\n\n\t// Persist mode changes\n\tuseEffect(() => {\n\t\tif (disablePersistence) return\n\n\t\ttry {\n\t\t\tlocalStorage.setItem(STORAGE_KEY, mode)\n\t\t} catch {\n\t\t\t// localStorage not available\n\t\t}\n\t}, [mode, disablePersistence])\n\n\t// Set mode with callback\n\tconst setMode = useCallback(\n\t\t(newMode: ToolApprovalMode) => {\n\t\t\tsetModeState(newMode)\n\t\t\tonModeChange?.(newMode)\n\t\t},\n\t\t[onModeChange]\n\t)\n\n\t// Toggle between modes\n\tconst toggleMode = useCallback(() => {\n\t\tsetMode(mode === 'auto' ? 'ask' : 'auto')\n\t}, [mode, setMode])\n\n\t// Check if a tool is destructive\n\tconst isDestructive = useCallback((tool: Tool): boolean => {\n\t\treturn checkIsDestructive(tool)\n\t}, [])\n\n\t// Check if a tool requires approval (destructive + ask mode)\n\tconst requiresApproval = useCallback(\n\t\t(tool: Tool): boolean => {\n\t\t\tif (mode === 'auto') return false\n\t\t\treturn isDestructive(tool)\n\t\t},\n\t\t[mode, isDestructive]\n\t)\n\n\tconst value = useMemo<ToolApprovalContextValue>(\n\t\t() => ({\n\t\t\tmode,\n\t\t\tsetMode,\n\t\t\ttoggleMode,\n\t\t\trequiresApproval,\n\t\t\tisDestructive,\n\t\t}),\n\t\t[mode, setMode, toggleMode, requiresApproval, isDestructive]\n\t)\n\n\treturn <ToolApprovalContext.Provider value={value}>{children}</ToolApprovalContext.Provider>\n}\n\n/**\n * Hook to access tool approval settings\n */\nexport function useToolApproval(): ToolApprovalContextValue {\n\tconst context = useContext(ToolApprovalContext)\n\tif (!context) {\n\t\tthrow new Error('useToolApproval must be used within a ToolApprovalProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access tool approval settings\n */\nexport function useOptionalToolApproval(): ToolApprovalContextValue | null {\n\treturn useContext(ToolApprovalContext)\n}\n","import { debugLog } from '../../lib/constants'\n\n/**\n * Audio analyzer for processing microphone and speaker audio streams.\n * Uses Web Audio API to analyze audio levels and frequency data.\n */\nexport class AudioAnalyzer {\n\tprivate audioContext: AudioContext | null = null\n\tprivate analyser: AnalyserNode | null = null\n\tprivate source: MediaStreamAudioSourceNode | null = null\n\tprivate dataArray: Uint8Array<ArrayBuffer> | null = null\n\tprivate animationId: number | null = null\n\n\t/**\n\t * Initialize the audio analyzer with a media stream\n\t * @param stream - MediaStream to analyze (typically from microphone or speaker)\n\t */\n\tasync initialize(stream: MediaStream): Promise<void> {\n\t\t// Log stream info for debugging\n\t\tconst audioTracks = stream.getAudioTracks()\n\t\tdebugLog('AudioAnalyzer', 'Initializing with stream', {\n\t\t\tstreamId: stream.id,\n\t\t\taudioTracks: audioTracks.length,\n\t\t\ttrackInfo: audioTracks.map((t) => ({\n\t\t\t\tid: t.id,\n\t\t\t\tlabel: t.label,\n\t\t\t\tenabled: t.enabled,\n\t\t\t\tmuted: t.muted,\n\t\t\t\treadyState: t.readyState,\n\t\t\t})),\n\t\t})\n\n\t\tthis.audioContext = new AudioContext()\n\t\tdebugLog('AudioAnalyzer', `AudioContext created, initial state: ${this.audioContext.state}`)\n\n\t\t// Always try to resume - some browsers need this regardless of reported state\n\t\ttry {\n\t\t\tawait this.audioContext.resume()\n\t\t\tdebugLog('AudioAnalyzer', `AudioContext after resume: ${this.audioContext.state}`)\n\t\t} catch (err) {\n\t\t\tconsole.warn('[AudioAnalyzer] Failed to resume AudioContext:', err)\n\t\t}\n\n\t\tthis.analyser = this.audioContext.createAnalyser()\n\t\tthis.analyser.fftSize = 256\n\t\tthis.analyser.smoothingTimeConstant = 0.8\n\n\t\tthis.source = this.audioContext.createMediaStreamSource(stream)\n\t\tthis.source.connect(this.analyser)\n\n\t\tconst bufferLength = this.analyser.frequencyBinCount\n\t\tthis.dataArray = new Uint8Array(new ArrayBuffer(bufferLength))\n\n\t\tdebugLog('AudioAnalyzer', 'Setup complete', {\n\t\t\tsampleRate: this.audioContext.sampleRate,\n\t\t\tfrequencyBinCount: bufferLength,\n\t\t\tcontextState: this.audioContext.state,\n\t\t})\n\t}\n\n\tgetAudioLevel(): number {\n\t\tif (!this.analyser || !this.dataArray) return 0\n\n\t\tthis.analyser.getByteFrequencyData(this.dataArray)\n\n\t\t// Calculate average volume\n\t\tlet sum = 0\n\t\tfor (let i = 0; i < this.dataArray.length; i++) {\n\t\t\tsum += this.dataArray[i]\n\t\t}\n\t\tconst average = sum / this.dataArray.length\n\n\t\t// Normalize to 0-1 range\n\t\treturn Math.min(1, average / 128)\n\t}\n\n\tgetFrequencyData(bins = 16): number[] {\n\t\tif (!this.analyser || !this.dataArray) return new Array(bins).fill(0)\n\n\t\tthis.analyser.getByteFrequencyData(this.dataArray)\n\n\t\tconst result: number[] = []\n\t\tconst samplesPerBin = Math.floor(this.dataArray.length / bins)\n\n\t\tfor (let i = 0; i < bins; i++) {\n\t\t\tlet sum = 0\n\t\t\tfor (let j = 0; j < samplesPerBin; j++) {\n\t\t\t\tsum += this.dataArray[i * samplesPerBin + j]\n\t\t\t}\n\t\t\t// Normalize to 0-1 range\n\t\t\tresult.push(Math.min(1, sum / samplesPerBin / 255))\n\t\t}\n\n\t\treturn result\n\t}\n\n\tstartAnalysis(callback: (level: number, frequencies: number[]) => void): void {\n\t\tconst analyze = () => {\n\t\t\tconst level = this.getAudioLevel()\n\t\t\tconst frequencies = this.getFrequencyData()\n\t\t\tcallback(level, frequencies)\n\t\t\tthis.animationId = requestAnimationFrame(analyze)\n\t\t}\n\t\tanalyze()\n\t}\n\n\tstopAnalysis(): void {\n\t\tif (this.animationId !== null) {\n\t\t\tcancelAnimationFrame(this.animationId)\n\t\t\tthis.animationId = null\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.stopAnalysis()\n\n\t\tif (this.source) {\n\t\t\tthis.source.disconnect()\n\t\t\tthis.source = null\n\t\t}\n\n\t\tif (this.analyser) {\n\t\t\tthis.analyser.disconnect()\n\t\t\tthis.analyser = null\n\t\t}\n\n\t\tif (this.audioContext) {\n\t\t\tvoid this.audioContext.close()\n\t\t\tthis.audioContext = null\n\t\t}\n\n\t\tthis.dataArray = null\n\t}\n}\n","import type { EventCallback, IEventEmitter } from './types'\n\nexport class EventEmitter implements IEventEmitter {\n\tprivate listeners = new Map<string, Set<EventCallback>>()\n\n\ton(event: string, callback: EventCallback): void {\n\t\tif (!this.listeners.has(event)) {\n\t\t\tthis.listeners.set(event, new Set())\n\t\t}\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tlisteners.add(callback)\n\t\t}\n\t}\n\n\toff(event: string, callback: EventCallback): void {\n\t\tthis.listeners.get(event)?.delete(callback)\n\t}\n\n\temit(event: string, data: unknown): void {\n\t\tthis.listeners.get(event)?.forEach((callback) => {\n\t\t\ttry {\n\t\t\t\tcallback(data)\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`Error in event listener for ${event}:`, error)\n\t\t\t}\n\t\t})\n\t}\n\n\tremoveAllListeners(event?: string): void {\n\t\tif (event) {\n\t\t\tthis.listeners.delete(event)\n\t\t} else {\n\t\t\tthis.listeners.clear()\n\t\t}\n\t}\n\n\tlistenerCount(event: string): number {\n\t\treturn this.listeners.get(event)?.size || 0\n\t}\n}\n","import { RESPONSE_REQUEST_DELAY_MS } from '../../lib/constants'\n\nimport type { EventEmitter } from './event-emitter'\nimport type { ToolManager } from './tool-manager'\nimport type { FunctionCall, RealtimeMessage } from './types'\n\n/**\n * Type for response output items from OpenAI Realtime API\n */\ninterface ResponseOutputItem {\n\ttype: string\n\tstatus?: string\n\tname?: string\n\tcall_id?: string\n\targuments?: string\n}\n\n/**\n * Type guard to check if an output item is a completed function call\n */\nfunction isCompletedFunctionCall(item: ResponseOutputItem): item is ResponseOutputItem & {\n\tname: string\n\tcall_id: string\n\targuments: string\n} {\n\treturn (\n\t\titem.type === 'function_call' &&\n\t\titem.status === 'completed' &&\n\t\ttypeof item.name === 'string' &&\n\t\ttypeof item.call_id === 'string'\n\t)\n}\n\nexport class MessageHandler {\n\tprivate isProcessingResponse = false\n\tprivate pendingFunctionCalls = new Set<string>()\n\tprivate responseRequestTimer: ReturnType<typeof setTimeout> | null = null\n\tprivate hasRequestedResponse = false\n\n\tconstructor(\n\t\tprivate toolManager: ToolManager,\n\t\tprivate eventEmitter: EventEmitter\n\t) {}\n\n\tasync handleMessage(data: string, dataChannel: RTCDataChannel): Promise<void> {\n\t\tlet msg: RealtimeMessage\n\n\t\ttry {\n\t\t\tmsg = JSON.parse(data) as RealtimeMessage\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to parse realtime message:', error)\n\t\t\treturn\n\t\t}\n\n\t\t// Log all incoming events for debugging\n\t\t// Route message to appropriate handler\n\t\tswitch (msg.type) {\n\t\t\tcase 'response.created':\n\t\t\t\tthis.handleResponseCreated(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'response.done':\n\t\t\t\tawait this.handleResponseDone(msg, dataChannel)\n\t\t\t\tbreak\n\n\t\t\tcase 'response.function_call_arguments.done':\n\t\t\t\tthis.handleFunctionCallArguments()\n\t\t\t\tbreak\n\n\t\t\tcase 'input_audio_buffer.speech_started':\n\t\t\tcase 'input_audio_buffer.speech_stopped':\n\t\t\t\tthis.handleSpeechEvents(msg)\n\t\t\t\tbreak\n\n\t\t\t// GA API: response.output_audio events\n\t\t\tcase 'response.output_audio.delta':\n\t\t\tcase 'response.output_audio.done':\n\t\t\t\tthis.handleAudioEvents(msg)\n\t\t\t\tbreak\n\n\t\t\t// GA API: response.output_audio_transcript and response.output_text events\n\t\t\tcase 'response.output_audio_transcript.delta':\n\t\t\tcase 'response.output_audio_transcript.done':\n\t\t\tcase 'response.output_text.delta':\n\t\t\tcase 'response.output_text.done':\n\t\t\t\tthis.handleTranscriptEvents(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'conversation.item.input_audio_transcription.completed':\n\t\t\t\tthis.handleUserTranscript(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'error':\n\t\t\t\tthis.handleError(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'session.created':\n\t\t\tcase 'session.updated':\n\t\t\t\tthis.handleSessionEvents(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'conversation.item.created':\n\t\t\tcase 'input_audio_buffer.committed':\n\t\t\t\t// Log only, no action needed\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate handleResponseCreated(_msg: RealtimeMessage): void {\n\t\tthis.isProcessingResponse = true\n\t\tthis.hasRequestedResponse = false\n\t}\n\n\tprivate async handleResponseDone(\n\t\tmsg: RealtimeMessage,\n\t\tdataChannel: RTCDataChannel\n\t): Promise<void> {\n\t\t// Safely extract response output with proper type checking\n\t\tconst outputItems = this.extractResponseOutput(msg.response)\n\n\t\t// Check if there are function calls to process\n\t\tconst hasFunctionCalls = outputItems.some(isCompletedFunctionCall)\n\n\t\t// Only set isProcessingResponse to false if there are no function calls\n\t\tif (!hasFunctionCalls) {\n\t\t\tthis.isProcessingResponse = false\n\t\t\tthis.hasRequestedResponse = false\n\t\t}\n\n\t\t// Process any function calls in the response\n\t\tif (outputItems.length > 0) {\n\t\t\t// Extract function calls with proper type narrowing\n\t\t\tconst functionCalls: FunctionCall[] = outputItems\n\t\t\t\t.filter(isCompletedFunctionCall)\n\t\t\t\t.map((item) => ({\n\t\t\t\t\tname: item.name,\n\t\t\t\t\tcall_id: item.call_id,\n\t\t\t\t\targuments: item.arguments ?? '',\n\t\t\t\t}))\n\n\t\t\tfor (const functionCall of functionCalls) {\n\t\t\t\tif (!this.pendingFunctionCalls.has(functionCall.call_id)) {\n\t\t\t\t\tthis.pendingFunctionCalls.add(functionCall.call_id)\n\t\t\t\t\tawait this.executeFunctionCall(functionCall, dataChannel)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[MessageHandler] Skipping duplicate function call: ${functionCall.name} (${functionCall.call_id})`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// After all function calls are processed, check if we need to request a response\n\t\t\tif (functionCalls.length > 0 && this.pendingFunctionCalls.size === 0) {\n\t\t\t\tthis.requestResponseIfNeeded(dataChannel)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Safely extract response output array from response object\n\t */\n\tprivate extractResponseOutput(response: unknown): ResponseOutputItem[] {\n\t\tif (!response || typeof response !== 'object') {\n\t\t\treturn []\n\t\t}\n\n\t\tconst r = response as Record<string, unknown>\n\t\tif (!Array.isArray(r.output)) {\n\t\t\treturn []\n\t\t}\n\n\t\t// Filter to only valid output items\n\t\treturn r.output.filter(\n\t\t\t(item): item is ResponseOutputItem =>\n\t\t\t\titem !== null &&\n\t\t\t\ttypeof item === 'object' &&\n\t\t\t\ttypeof (item as ResponseOutputItem).type === 'string'\n\t\t)\n\t}\n\n\tprivate handleFunctionCallArguments(): void {\n\t\t// Function call arguments are being accumulated\n\t\t// Actual execution happens in handleResponseDone\n\t}\n\n\tprivate handleSpeechEvents(msg: RealtimeMessage): void {\n\t\tconst eventType =\n\t\t\tmsg.type === 'input_audio_buffer.speech_started' ? 'speech_started' : 'speech_stopped'\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate handleAudioEvents(msg: RealtimeMessage): void {\n\t\tconst eventType = msg.type === 'response.output_audio.delta' ? 'audio_started' : 'audio_stopped'\n\t\tconsole.log(`[MessageHandler] Assistant ${eventType}`, {\n\t\t\ttype: msg.type,\n\t\t\thasAudio: !!(msg as { delta?: unknown }).delta,\n\t\t})\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate handleTranscriptEvents(msg: RealtimeMessage): void {\n\t\t// GA API event name mappings\n\t\tconst eventMap: Record<string, string> = {\n\t\t\t'response.output_audio_transcript.delta': 'assistant_transcript',\n\t\t\t'response.output_audio_transcript.done': 'assistant_transcript_done',\n\t\t\t'response.output_text.delta': 'text',\n\t\t\t'response.output_text.done': 'text_done',\n\t\t}\n\n\t\tconst eventType = eventMap[msg.type]\n\t\tif (eventType) {\n\t\t\tthis.eventEmitter.emit(eventType, msg)\n\t\t}\n\t}\n\n\tprivate handleUserTranscript(msg: RealtimeMessage): void {\n\t\tthis.eventEmitter.emit('user_transcript_done', { text: msg.transcript })\n\t}\n\n\tprivate handleSessionEvents(_msg: RealtimeMessage): void {\n\t\t// Session events are handled but no action is needed at this time\n\t}\n\n\tprivate handleError(msg: RealtimeMessage): void {\n\t\tconsole.error('Realtime API error:', msg)\n\t\tthis.eventEmitter.emit('error', msg)\n\t\tthis.isProcessingResponse = false\n\t\tthis.hasRequestedResponse = false\n\n\t\t// Clear any pending response timer\n\t\tif (this.responseRequestTimer) {\n\t\t\tclearTimeout(this.responseRequestTimer)\n\t\t\tthis.responseRequestTimer = null\n\t\t}\n\t}\n\n\tprivate async executeFunctionCall(\n\t\tfunctionCall: FunctionCall,\n\t\tdataChannel: RTCDataChannel\n\t): Promise<void> {\n\t\tconst { name, call_id } = functionCall\n\n\t\ttry {\n\t\t\t// Emit start event\n\t\t\tthis.eventEmitter.emit('tool_call_started', { name })\n\n\t\t\t// Execute tool\n\t\t\tconst result = await this.toolManager.executeToolCall(functionCall)\n\n\t\t\t// Check if data channel is still open before sending\n\t\t\tif (dataChannel.readyState !== 'open') {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`[MessageHandler] Cannot send tool result for ${name}: DataChannel is ${dataChannel.readyState}`\n\t\t\t\t)\n\t\t\t\tthis.eventEmitter.emit('tool_call_completed', {\n\t\t\t\t\tname,\n\t\t\t\t\terror: 'DataChannel closed during tool execution',\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Send result back\n\t\t\tconst response = {\n\t\t\t\ttype: 'conversation.item.create',\n\t\t\t\titem: {\n\t\t\t\t\ttype: 'function_call_output',\n\t\t\t\t\tcall_id: call_id,\n\t\t\t\t\toutput: JSON.stringify(\n\t\t\t\t\t\tresult.success\n\t\t\t\t\t\t\t? result.data\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tdataChannel.send(JSON.stringify(response))\n\n\t\t\t// Emit completion event\n\t\t\tthis.eventEmitter.emit('tool_call_completed', {\n\t\t\t\tname,\n\t\t\t\terror: result.success ? undefined : result.error,\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tconsole.error(`[MessageHandler] Tool execution failed for ${name}:`, error)\n\t\t\tthis.sendToolError(call_id, String(error), dataChannel)\n\t\t} finally {\n\t\t\tthis.pendingFunctionCalls.delete(call_id)\n\n\t\t\t// After removing this function call, check if all are complete\n\t\t\tif (this.pendingFunctionCalls.size === 0) {\n\t\t\t\t// All function calls are done, now we can request a response\n\t\t\t\tthis.isProcessingResponse = false\n\t\t\t\tthis.hasRequestedResponse = false\n\t\t\t\tthis.requestResponseIfNeeded(dataChannel)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sendToolError(call_id: string, error: string, dataChannel: RTCDataChannel): void {\n\t\t// Check if data channel is still open before sending error\n\t\tif (dataChannel.readyState !== 'open') {\n\t\t\tconsole.error(\n\t\t\t\t`[MessageHandler] Cannot send tool error: DataChannel is ${dataChannel.readyState}`\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\tconst errorResponse = {\n\t\t\ttype: 'conversation.item.create',\n\t\t\titem: {\n\t\t\t\ttype: 'function_call_output',\n\t\t\t\tcall_id: call_id,\n\t\t\t\toutput: JSON.stringify({ error, success: false }),\n\t\t\t},\n\t\t}\n\n\t\tdataChannel.send(JSON.stringify(errorResponse))\n\t}\n\n\tprivate requestResponseIfNeeded(dataChannel: RTCDataChannel): void {\n\t\t// Clear any existing timer\n\t\tif (this.responseRequestTimer) {\n\t\t\tclearTimeout(this.responseRequestTimer)\n\t\t\tthis.responseRequestTimer = null\n\t\t}\n\n\t\t// Set a new timer to request response (delay prevents race conditions)\n\t\tthis.responseRequestTimer = setTimeout(() => {\n\t\t\tif (\n\t\t\t\t!this.isProcessingResponse &&\n\t\t\t\t!this.hasRequestedResponse &&\n\t\t\t\tdataChannel.readyState === 'open' &&\n\t\t\t\tthis.pendingFunctionCalls.size === 0\n\t\t\t) {\n\t\t\t\tthis.hasRequestedResponse = true\n\t\t\t\tthis.isProcessingResponse = true\n\t\t\t\tdataChannel.send(JSON.stringify({ type: 'response.create' }))\n\t\t\t}\n\t\t\tthis.responseRequestTimer = null\n\t\t}, RESPONSE_REQUEST_DELAY_MS)\n\t}\n\n\treset(): void {\n\t\tthis.isProcessingResponse = false\n\t\tthis.hasRequestedResponse = false\n\t\tthis.pendingFunctionCalls.clear()\n\n\t\t// Clear any pending response timer\n\t\tif (this.responseRequestTimer) {\n\t\t\tclearTimeout(this.responseRequestTimer)\n\t\t\tthis.responseRequestTimer = null\n\t\t}\n\t}\n}\n","import { jsonrepair } from 'jsonrepair'\n\nimport type { FunctionCall, OpenAITool, ToolExecutionResult } from './types'\n\nexport interface RegisteredTool {\n\tname: string\n\tdescription: string\n\tinputSchema?: Record<string, unknown>\n}\n\nexport type ToolExecutor = (name: string, args: Record<string, unknown>) => Promise<unknown>\n\nexport class ToolManager {\n\tprivate tools: RegisteredTool[] = []\n\tprivate executor: ToolExecutor | null = null\n\tprivate lastSentToolSignature = ''\n\n\tsetTools(tools: RegisteredTool[]): void {\n\t\tthis.tools = tools\n\t}\n\n\tsetExecutor(executor: ToolExecutor): void {\n\t\tthis.executor = executor\n\t}\n\n\tresetSession(): void {\n\t\tconsole.log('[ToolManager] resetSession called (lastSentToolSignature preserved)')\n\t}\n\n\tprivate getToolSignature(tools: RegisteredTool[]): string {\n\t\treturn tools\n\t\t\t.map((t) => t.name)\n\t\t\t.sort()\n\t\t\t.join('|')\n\t}\n\n\thasToolsChanged(): boolean {\n\t\tconst currentSignature = this.getToolSignature(this.tools)\n\t\treturn currentSignature !== this.lastSentToolSignature\n\t}\n\n\tmarkToolsSent(): void {\n\t\tthis.lastSentToolSignature = this.getToolSignature(this.tools)\n\t}\n\n\tformatToolsForOpenAI(): OpenAITool[] {\n\t\t// Built-in tools\n\t\tconst builtInTools: OpenAITool[] = [\n\t\t\t{\n\t\t\t\ttype: 'function',\n\t\t\t\tname: 'list_available_tools',\n\t\t\t\tdescription:\n\t\t\t\t\t'List all currently available tools that can be called. Use this when you need to know what tools are available or when the user asks about available capabilities.',\n\t\t\t\tparameters: {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tproperties: {},\n\t\t\t\t\trequired: [],\n\t\t\t\t},\n\t\t\t},\n\t\t]\n\n\t\t// Registered tools\n\t\tconst registeredTools = this.tools.map((tool) => ({\n\t\t\ttype: 'function' as const,\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description || `Execute ${tool.name} action`,\n\t\t\tparameters: this.validateToolSchema(tool.inputSchema),\n\t\t}))\n\n\t\treturn [...builtInTools, ...registeredTools]\n\t}\n\n\tprivate validateToolSchema(schema: Record<string, unknown> | undefined): {\n\t\ttype: string\n\t\tproperties?: Record<string, unknown>\n\t\trequired?: string[]\n\t} {\n\t\tif (!schema) {\n\t\t\treturn { type: 'object', properties: {}, required: [] }\n\t\t}\n\n\t\tconst result: {\n\t\t\ttype: string\n\t\t\tproperties?: Record<string, unknown>\n\t\t\trequired?: string[]\n\t\t} = { type: 'object', ...schema }\n\n\t\tif (result.type === 'object') {\n\t\t\tresult.properties = (result.properties as Record<string, unknown>) || {}\n\n\t\t\t// Validate and fix nested schemas (especially arrays missing 'items')\n\t\t\tresult.properties = this.validateNestedSchemas(result.properties)\n\n\t\t\t// Generate required array if not present\n\t\t\tif (!result.required && result.properties) {\n\t\t\t\tresult.required = Object.entries(result.properties)\n\t\t\t\t\t.filter(([, prop]) => {\n\t\t\t\t\t\tif (prop && typeof prop === 'object') {\n\t\t\t\t\t\t\tconst p = prop as { optional?: boolean; nullable?: boolean; type?: string }\n\t\t\t\t\t\t\treturn !p.optional && !p.nullable && p.type !== 'null'\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false\n\t\t\t\t\t})\n\t\t\t\t\t.map(([key]) => key)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Recursively validate nested schemas, ensuring array types have 'items'.\n\t * The OpenAI Realtime API requires array schemas to have an 'items' field.\n\t */\n\tprivate validateNestedSchemas(properties: Record<string, unknown>): Record<string, unknown> {\n\t\tconst validated: Record<string, unknown> = {}\n\n\t\tfor (const [key, value] of Object.entries(properties)) {\n\t\t\tif (!value || typeof value !== 'object') {\n\t\t\t\tvalidated[key] = value\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst prop = value as Record<string, unknown>\n\t\t\tconst propType = prop.type as string | undefined\n\n\t\t\tif (propType === 'array') {\n\t\t\t\t// Ensure array schemas have 'items' - required by OpenAI Realtime API\n\t\t\t\tif (!prop.items) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ToolManager] Array property '${key}' missing 'items' - adding default string items`\n\t\t\t\t\t)\n\t\t\t\t\tvalidated[key] = {\n\t\t\t\t\t\t...prop,\n\t\t\t\t\t\titems: { type: 'string' },\n\t\t\t\t\t}\n\t\t\t\t} else if (typeof prop.items === 'object') {\n\t\t\t\t\t// Recursively validate items schema\n\t\t\t\t\tconst items = prop.items as Record<string, unknown>\n\t\t\t\t\tif (items.type === 'object' && items.properties) {\n\t\t\t\t\t\tvalidated[key] = {\n\t\t\t\t\t\t\t...prop,\n\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t...items,\n\t\t\t\t\t\t\t\tproperties: this.validateNestedSchemas(items.properties as Record<string, unknown>),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalidated[key] = prop\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvalidated[key] = prop\n\t\t\t\t}\n\t\t\t} else if (propType === 'object' && prop.properties) {\n\t\t\t\t// Recursively validate nested object properties\n\t\t\t\tvalidated[key] = {\n\t\t\t\t\t...prop,\n\t\t\t\t\tproperties: this.validateNestedSchemas(prop.properties as Record<string, unknown>),\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvalidated[key] = prop\n\t\t\t}\n\t\t}\n\n\t\treturn validated\n\t}\n\n\tasync executeToolCall(functionCall: FunctionCall): Promise<ToolExecutionResult> {\n\t\tconst { name, arguments: argsString } = functionCall\n\n\t\t// Handle built-in tools\n\t\tif (name === 'list_available_tools') {\n\t\t\treturn this.executeListTools()\n\t\t}\n\n\t\t// Check if executor is set\n\t\tif (!this.executor) {\n\t\t\tconsole.error('[ToolManager] Tool executor not configured')\n\t\t\treturn { success: false, error: 'Tool executor not configured' }\n\t\t}\n\n\t\t// Parse arguments - use jsonrepair to handle malformed JSON from OpenAI\n\t\tlet args: Record<string, unknown>\n\t\ttry {\n\t\t\tconst repaired = argsString ? jsonrepair(argsString) : '{}'\n\t\t\targs = JSON.parse(repaired) as Record<string, unknown>\n\t\t} catch (error) {\n\t\t\tconsole.error('[ToolManager] Failed to parse arguments:', error)\n\t\t\tconsole.error('[ToolManager] Raw argsString:', argsString?.slice(0, 200))\n\t\t\treturn { success: false, error: 'Invalid arguments format' }\n\t\t}\n\n\t\t// Execute via the executor - it handles tool lookup from the current MCP context\n\t\t// Note: We intentionally don't verify the tool exists in this.tools first because\n\t\t// the executor has access to the latest tool list via React context/closure, which\n\t\t// may be more up-to-date than our cached copy (avoiding stale closure issues).\n\t\t// The executor will throw if the tool is not found.\n\t\ttry {\n\t\t\tconst result = await this.executor(name, args)\n\t\t\treturn { success: true, data: result }\n\t\t} catch (error) {\n\t\t\tconsole.error(`[ToolManager] Tool execution error for ${name}:`, error)\n\t\t\treturn { success: false, error: String(error) }\n\t\t}\n\t}\n\n\tprivate executeListTools(): ToolExecutionResult {\n\t\tconst toolList = this.tools.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description || 'No description available',\n\t\t\tparameters: tool.inputSchema || {},\n\t\t}))\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\ttools: toolList,\n\t\t\t\tcount: toolList.length,\n\t\t\t\tmessage:\n\t\t\t\t\ttoolList.length > 0\n\t\t\t\t\t\t? `Found ${toolList.length} available tools`\n\t\t\t\t\t\t: 'No tools currently available',\n\t\t\t},\n\t\t}\n\t}\n\n\tgetChangesSummary(): { added: string[]; removed: string[]; total: number } | null {\n\t\tif (!this.hasToolsChanged()) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst prevTools = this.lastSentToolSignature.split('|').filter(Boolean)\n\t\tconst currTools = this.tools.map((t) => t.name)\n\n\t\tconst prevSet = new Set(prevTools)\n\t\tconst currSet = new Set(currTools)\n\n\t\tconst added = currTools.filter((name) => !prevSet.has(name))\n\t\tconst removed = prevTools.filter((name) => !currSet.has(name))\n\n\t\treturn {\n\t\t\tadded,\n\t\t\tremoved,\n\t\t\ttotal: this.tools.length,\n\t\t}\n\t}\n}\n","import {\n\tdebugLog,\n\tREALTIME_DEFAULT_API_URL,\n\tREALTIME_DEFAULT_MODEL,\n\tREALTIME_DEFAULT_VOICE,\n} from '../../lib/constants'\n\nimport type { RealtimeConfig, RealtimeSession } from './types'\n\ninterface EphemeralTokenResponse {\n\tclient_secret?: {\n\t\tvalue?: string\n\t}\n}\n\nfunction hasClientSecret(response: unknown): response is {\n\tclient_secret: { value: string }\n} {\n\tif (!response || typeof response !== 'object') {\n\t\treturn false\n\t}\n\tconst secret = (response as EphemeralTokenResponse).client_secret\n\treturn typeof secret?.value === 'string'\n}\n\nexport class WebRTCManager {\n\tprivate tokenEndpoint: string\n\n\tconstructor(tokenEndpoint: string) {\n\t\tthis.tokenEndpoint = tokenEndpoint\n\t}\n\n\tasync createSession(config: RealtimeConfig = {}): Promise<RealtimeSession> {\n\t\tconst model = config.model || REALTIME_DEFAULT_MODEL\n\t\tconst voice = config.voice || REALTIME_DEFAULT_VOICE\n\t\tconst apiUrl = config.apiUrl || REALTIME_DEFAULT_API_URL\n\n\t\t// Get ephemeral token from our backend\n\t\tconst ephemeralKey = await this.getEphemeralToken(model, voice)\n\n\t\t// Create peer connection\n\t\tconst pc = new RTCPeerConnection()\n\n\t\t// Set up audio playback\n\t\tconst audioElement = this.createAudioElement()\n\t\t// Track streams\n\t\tlet remoteStream: MediaStream | null = null\n\t\tpc.ontrack = (e) => {\n\t\t\tremoteStream = e.streams[0]\n\t\t\taudioElement.srcObject = remoteStream\n\t\t\tdebugLog('WebRTC', 'Remote audio stream received and connected to audio element', {\n\t\t\t\tstreamId: remoteStream.id,\n\t\t\t\ttracks: remoteStream.getTracks().length,\n\t\t\t})\n\t\t}\n\n\t\t// Add microphone\n\t\tconst localStream = await this.getUserMedia()\n\t\tdebugLog('WebRTC', 'Local microphone stream acquired', {\n\t\t\tstreamId: localStream.id,\n\t\t\ttracks: localStream.getTracks().map((t) => ({\n\t\t\t\tkind: t.kind,\n\t\t\t\tenabled: t.enabled,\n\t\t\t\tmuted: t.muted,\n\t\t\t\treadyState: t.readyState,\n\t\t\t})),\n\t\t})\n\n\t\tlocalStream.getTracks().forEach((track) => {\n\t\t\tpc.addTrack(track, localStream)\n\t\t})\n\n\t\t// Create data channel for events\n\t\tconst dataChannel = pc.createDataChannel('oai-events')\n\n\t\t// Create offer and establish connection\n\t\tconst offer = await pc.createOffer()\n\t\tawait pc.setLocalDescription(offer)\n\n\t\t// Connect to OpenAI\n\t\tif (!offer.sdp) {\n\t\t\tthrow new Error('Failed to create offer SDP')\n\t\t}\n\t\tconst answer = await this.connectToOpenAI(apiUrl, model, offer.sdp, ephemeralKey)\n\t\tawait pc.setRemoteDescription(answer)\n\n\t\t// Create cleanup function\n\t\tconst cleanup = () => {\n\t\t\tlocalStream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t\taudioElement.remove()\n\t\t\tdataChannel.close()\n\t\t\tpc.close()\n\t\t}\n\n\t\treturn {\n\t\t\tpc,\n\t\t\tdataChannel,\n\t\t\taudioElement,\n\t\t\tlocalStream,\n\t\t\tremoteStream,\n\t\t\tcleanup,\n\t\t}\n\t}\n\n\tprivate async getEphemeralToken(model: string, voice: string): Promise<string> {\n\t\tconst response = await fetch(this.tokenEndpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify({ model, voice }),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text()\n\t\t\tconsole.error('Failed to get ephemeral token:', errorText)\n\t\t\tthrow new Error(`Failed to get ephemeral token: ${response.statusText}`)\n\t\t}\n\n\t\tconst data: unknown = await response.json()\n\n\t\tif (!hasClientSecret(data)) {\n\t\t\tthrow new Error('Invalid token response format')\n\t\t}\n\n\t\treturn data.client_secret.value\n\t}\n\n\tprivate createAudioElement(): HTMLAudioElement {\n\t\tconst audioElement = document.createElement('audio')\n\t\taudioElement.autoplay = true\n\t\taudioElement.style.display = 'none'\n\t\tdocument.body.appendChild(audioElement)\n\t\treturn audioElement\n\t}\n\n\tprivate async getUserMedia(): Promise<MediaStream> {\n\t\ttry {\n\t\t\treturn await navigator.mediaDevices.getUserMedia({\n\t\t\t\taudio: {\n\t\t\t\t\techoCancellation: true,\n\t\t\t\t\tnoiseSuppression: true,\n\t\t\t\t\tautoGainControl: true,\n\t\t\t\t},\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to access microphone: ${error}`)\n\t\t}\n\t}\n\n\tprivate async connectToOpenAI(\n\t\tbaseUrl: string,\n\t\tmodel: string,\n\t\tsdp: string,\n\t\tephemeralKey: string\n\t): Promise<RTCSessionDescriptionInit> {\n\t\tconst response = await fetch(`${baseUrl}?model=${model}`, {\n\t\t\tmethod: 'POST',\n\t\t\tbody: sdp,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${ephemeralKey}`,\n\t\t\t\t'Content-Type': 'application/sdp',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Failed to establish WebRTC connection: ${response.statusText}`)\n\t\t}\n\n\t\tconst answerSdp = await response.text()\n\t\treturn {\n\t\t\ttype: 'answer' as const,\n\t\t\tsdp: answerSdp,\n\t\t}\n\t}\n}\n","import {\n\tAUDIO_FREQUENCY_BINS,\n\tAUDIO_VISUALIZATION_INTERVAL_MS,\n\tdebugLog,\n} from '../../lib/constants'\nimport { AudioAnalyzer } from './audio-analyzer'\nimport { EventEmitter } from './event-emitter'\nimport { MessageHandler } from './message-handler'\nimport { ToolManager } from './tool-manager'\nimport { WebRTCManager } from './webrtc-manager'\n\nimport type { RegisteredTool, ToolExecutor } from './tool-manager'\nimport type { EventCallback, RealtimeConfig, RealtimeSession, SessionConfig } from './types'\n\n/** Pre-allocated zero frequency array for performance */\nconst EMPTY_FREQUENCY_TEMPLATE = Object.freeze(new Array(AUDIO_FREQUENCY_BINS).fill(0))\nconst createZeroFrequencyArray = (): number[] => [...EMPTY_FREQUENCY_TEMPLATE]\n\n/**\n * OpenAI Realtime API Service\n *\n * Manages voice conversations with OpenAI's Realtime API,\n * including WebRTC connections, tool integration, and message handling.\n */\nexport class OpenAIRealtimeService {\n\tprivate session: RealtimeSession | null = null\n\tprivate webrtcManager: WebRTCManager\n\tprivate toolManager: ToolManager\n\tprivate messageHandler: MessageHandler\n\tprivate eventEmitter: EventEmitter\n\tprivate muted = false\n\tprivate lastState: 'disconnected' | 'connecting' | 'connected' | 'error' = 'disconnected'\n\tprivate localAnalyzer: AudioAnalyzer | null = null\n\tprivate remoteAnalyzer: AudioAnalyzer | null = null\n\tprivate visualizationInterval: ReturnType<typeof setInterval> | null = null\n\tprivate sessionStartTime: number | null = null\n\tprivate onToolsChangedCallback: (() => void) | null = null\n\n\tconstructor(tokenEndpoint: string) {\n\t\tthis.webrtcManager = new WebRTCManager(tokenEndpoint)\n\t\tthis.toolManager = new ToolManager()\n\t\tthis.eventEmitter = new EventEmitter()\n\t\tthis.messageHandler = new MessageHandler(this.toolManager, this.eventEmitter)\n\t}\n\n\t/**\n\t * Set the tools available for the voice session\n\t */\n\tsetTools(tools: RegisteredTool[]): void {\n\t\tthis.toolManager.setTools(tools)\n\t\tif (this.isSessionActive()) {\n\t\t\tthis.updateSessionTools()\n\t\t}\n\t}\n\n\t/**\n\t * Set the tool executor function\n\t */\n\tsetToolExecutor(executor: ToolExecutor): void {\n\t\tthis.toolManager.setExecutor(executor)\n\t}\n\n\t/**\n\t * Register callback for when tools change\n\t */\n\tonToolsChanged(callback: () => void): void {\n\t\tthis.onToolsChangedCallback = callback\n\t}\n\n\t/**\n\t * Start a new realtime session\n\t */\n\tasync startSession(config: RealtimeConfig = {}): Promise<RealtimeSession> {\n\t\ttry {\n\t\t\t// Clean up existing session\n\t\t\tif (this.session) {\n\t\t\t\tthis.stopSession()\n\t\t\t}\n\n\t\t\tthis.muted = false\n\t\t\tthis.sessionStartTime = Date.now()\n\t\t\tthis.emitSessionState('connecting')\n\n\t\t\t// Create new WebRTC session\n\t\t\tthis.session = await this.webrtcManager.createSession(config)\n\n\t\t\t// Setup data channel handlers\n\t\t\tthis.setupDataChannel(this.session.dataChannel)\n\n\t\t\t// Monitor peer connection state\n\t\t\tthis.setupPeerConnectionMonitoring(this.session.pc)\n\n\t\t\tif (this.session.localStream) {\n\t\t\t\tawait this.initializeLocalAnalyzer(this.session.localStream)\n\t\t\t}\n\n\t\t\tif (this.session.remoteStream) {\n\t\t\t\tvoid this.initializeRemoteAnalyzer(this.session.remoteStream)\n\t\t\t}\n\n\t\t\t// Update session reference for remote stream\n\t\t\tconst originalOntrack = this.session.pc.ontrack\n\t\t\tconst session = this.session\n\t\t\tthis.session.pc.ontrack = (e) => {\n\t\t\t\tif (originalOntrack) originalOntrack.call(session.pc, e)\n\t\t\t\tif (this.session) {\n\t\t\t\t\tthis.session.remoteStream = e.streams[0]\n\t\t\t\t}\n\n\t\t\t\tconst remoteStream = e.streams[0]\n\t\t\t\tif (!remoteStream) {\n\t\t\t\t\tconsole.warn('[OpenAIRealtimeService] Received ontrack event without stream')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tvoid this.initializeRemoteAnalyzer(remoteStream)\n\t\t\t}\n\n\t\t\treturn this.session\n\t\t} catch (error) {\n\t\t\tthis.handleSessionError(error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Stop the current session\n\t */\n\tstopSession(): void {\n\t\t// Calculate session duration for usage tracking\n\t\tlet durationSeconds = 0\n\t\tif (this.sessionStartTime) {\n\t\t\tdurationSeconds = Math.floor((Date.now() - this.sessionStartTime) / 1000)\n\t\t}\n\n\t\tif (this.visualizationInterval) {\n\t\t\tclearInterval(this.visualizationInterval)\n\t\t\tthis.visualizationInterval = null\n\t\t}\n\n\t\tif (this.localAnalyzer) {\n\t\t\tthis.localAnalyzer.destroy()\n\t\t\tthis.localAnalyzer = null\n\t\t}\n\n\t\tif (this.remoteAnalyzer) {\n\t\t\tthis.remoteAnalyzer.destroy()\n\t\t\tthis.remoteAnalyzer = null\n\t\t}\n\t\tif (this.session) {\n\t\t\tthis.session.cleanup()\n\t\t\tthis.session = null\n\t\t}\n\t\tthis.messageHandler.reset()\n\t\tthis.toolManager.resetSession()\n\n\t\t// Emit disconnected state with session duration\n\t\tthis.muted = false\n\t\tthis.emitSessionState('disconnected', { durationSeconds })\n\n\t\t// Reset session start time\n\t\tthis.sessionStartTime = null\n\t}\n\n\t/**\n\t * Send a text message to the assistant\n\t */\n\tsendUserMessage(text: string): void {\n\t\tif (!this.isSessionActive()) {\n\t\t\tthrow new Error('No active session')\n\t\t}\n\n\t\tconst message = {\n\t\t\ttype: 'conversation.item.create',\n\t\t\titem: {\n\t\t\t\ttype: 'message',\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: [{ type: 'input_text', text }],\n\t\t\t},\n\t\t}\n\n\t\tif (!this.session) {\n\t\t\tthrow new Error('Session is not active')\n\t\t}\n\t\tthis.session.dataChannel.send(JSON.stringify(message))\n\t\tthis.session.dataChannel.send(JSON.stringify({ type: 'response.create' }))\n\t}\n\n\t/**\n\t * Check if session is active\n\t */\n\tisSessionActive(): boolean {\n\t\treturn this.session !== null && this.session.dataChannel.readyState === 'open'\n\t}\n\n\t/**\n\t * Get the local audio stream\n\t */\n\tgetLocalStream(): MediaStream | null {\n\t\treturn this.session?.localStream || null\n\t}\n\n\t/**\n\t * Get the remote audio stream\n\t */\n\tgetRemoteStream(): MediaStream | null {\n\t\treturn this.session?.remoteStream || null\n\t}\n\n\t/**\n\t * Toggle audio mute\n\t */\n\ttoggleMute(muted: boolean): void {\n\t\tif (this.session?.audioElement) {\n\t\t\tthis.session.audioElement.muted = muted\n\t\t}\n\t\tthis.muted = muted\n\t\tthis.emitSessionState(this.lastState, { isMuted: this.muted })\n\t}\n\n\t/**\n\t * Pause audio playback (for approval flow)\n\t * This pauses the audio element without stopping the WebRTC stream.\n\t */\n\tpauseAudio(): void {\n\t\tif (this.session?.audioElement) {\n\t\t\tthis.session.audioElement.pause()\n\t\t}\n\t}\n\n\t/**\n\t * Resume audio playback (after approval flow)\n\t */\n\tresumeAudio(): void {\n\t\tif (this.session?.audioElement) {\n\t\t\tthis.session.audioElement.play().catch((error) => {\n\t\t\t\t// Handle autoplay restrictions gracefully\n\t\t\t\tconsole.warn('[OpenAIRealtimeService] Failed to resume audio:', error)\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Event handling\n\t */\n\ton(event: string, callback: EventCallback): void {\n\t\tthis.eventEmitter.on(event, callback)\n\t}\n\n\toff(event: string, callback: EventCallback): void {\n\t\tthis.eventEmitter.off(event, callback)\n\t}\n\n\tgetSessionStatus(): {\n\t\tstate: 'connecting' | 'connected' | 'disconnected' | 'error'\n\t\tisActive: boolean\n\t\tisMuted: boolean\n\t} {\n\t\treturn {\n\t\t\tstate: this.lastState,\n\t\t\tisActive: this.lastState === 'connected',\n\t\t\tisMuted: this.muted,\n\t\t}\n\t}\n\n\t/**\n\t * Private methods\n\t */\n\tprivate setupDataChannel(dataChannel: RTCDataChannel): void {\n\t\t// Configure session when channel opens\n\t\tdataChannel.addEventListener('open', () => {\n\t\t\tthis.configureSession(dataChannel)\n\t\t\tthis.muted = false\n\t\t\tthis.emitSessionState('connected')\n\t\t})\n\n\t\t// Handle incoming messages\n\t\tdataChannel.addEventListener('message', (event: MessageEvent<string>) => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.messageHandler.handleMessage(event.data, dataChannel)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error('Error handling message:', error)\n\t\t\t\t}\n\t\t\t})()\n\t\t})\n\n\t\t// Handle errors\n\t\tdataChannel.addEventListener('error', (error) => {\n\t\t\tconsole.error('DataChannel error:', error)\n\t\t\tthis.eventEmitter.emit('error', { type: 'datachannel_error', error })\n\t\t})\n\n\t\t// Handle close\n\t\tdataChannel.addEventListener('close', () => {\n\t\t\tthis.messageHandler.reset()\n\t\t\tthis.eventEmitter.emit('session_closed', {})\n\t\t})\n\t}\n\n\tprivate setupPeerConnectionMonitoring(pc: RTCPeerConnection): void {\n\t\t// Monitor connection state changes\n\t\tpc.addEventListener('connectionstatechange', () => {\n\t\t\tif (pc.connectionState === 'failed' || pc.connectionState === 'disconnected') {\n\t\t\t\tconsole.error('Peer connection failed or disconnected')\n\t\t\t\tthis.messageHandler.reset()\n\t\t\t\tthis.eventEmitter.emit('error', {\n\t\t\t\t\ttype: 'connection_error',\n\t\t\t\t\tmessage: `Connection ${pc.connectionState}`,\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t// Monitor ICE connection state\n\t\tpc.addEventListener('iceconnectionstatechange', () => {\n\t\t\tif (pc.iceConnectionState === 'failed' || pc.iceConnectionState === 'disconnected') {\n\t\t\t\tconsole.error('ICE connection failed or disconnected')\n\t\t\t}\n\t\t})\n\n\t\t// Monitor signaling state\n\t\tpc.addEventListener('signalingstatechange', () => {})\n\t}\n\n\tprivate configureSession(dataChannel: RTCDataChannel): void {\n\t\t// Reset per-session state\n\t\tthis.toolManager.resetSession()\n\n\t\t// Get initial tools\n\t\tconst tools = this.toolManager.formatToolsForOpenAI()\n\t\t// Mark tools as sent\n\t\tthis.toolManager.markToolsSent()\n\n\t\tconst sessionConfig: SessionConfig = {\n\t\t\tmodalities: ['text', 'audio'],\n\t\t\tinstructions: this.getSessionInstructions(),\n\t\t\tvoice: 'echo',\n\t\t\ttools: tools,\n\t\t\ttool_choice: 'auto',\n\t\t\tturn_detection: {\n\t\t\t\ttype: 'server_vad',\n\t\t\t\tthreshold: 0.5,\n\t\t\t\tprefix_padding_ms: 300,\n\t\t\t\tsilence_duration_ms: 500,\n\t\t\t},\n\t\t\tinput_audio_transcription: {\n\t\t\t\tmodel: 'whisper-1',\n\t\t\t},\n\t\t}\n\n\t\tconst sessionUpdate = {\n\t\t\ttype: 'session.update',\n\t\t\tsession: sessionConfig,\n\t\t}\n\n\t\tdataChannel.send(JSON.stringify(sessionUpdate))\n\t}\n\n\tprivate updateSessionTools(): void {\n\t\tif (!this.session) {\n\t\t\tconsole.warn('[OpenAIRealtimeService] Cannot update tools: no active session')\n\t\t\treturn\n\t\t}\n\n\t\tif (this.session.dataChannel.readyState !== 'open') {\n\t\t\tconsole.warn(\n\t\t\t\t`[OpenAIRealtimeService] Cannot update tools: DataChannel is ${this.session.dataChannel.readyState}`\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\t// Check if tools have actually changed\n\t\tconst changesSummary = this.toolManager.getChangesSummary()\n\t\tif (!changesSummary) {\n\t\t\treturn\n\t\t}\n\n\t\t// Get the full tool list\n\t\tconst tools = this.toolManager.formatToolsForOpenAI()\n\n\t\tconsole.log(\n\t\t\t'[OpenAIRealtimeService] Sending tool update to OpenAI:',\n\t\t\t`${changesSummary.total} total tools,`,\n\t\t\tchangesSummary.added.length > 0\n\t\t\t\t? `+${changesSummary.added.length} added (${changesSummary.added.slice(0, 3).join(', ')}${changesSummary.added.length > 3 ? '...' : ''})`\n\t\t\t\t: '',\n\t\t\tchangesSummary.removed.length > 0 ? `-${changesSummary.removed.length} removed` : ''\n\t\t)\n\n\t\t// Mark tools as sent\n\t\tthis.toolManager.markToolsSent()\n\n\t\tconst sessionUpdate = {\n\t\t\ttype: 'session.update',\n\t\t\tsession: {\n\t\t\t\ttools: tools,\n\t\t\t\ttool_choice: 'auto',\n\t\t\t},\n\t\t}\n\n\t\tthis.session.dataChannel.send(JSON.stringify(sessionUpdate))\n\t}\n\n\tprivate getSessionInstructions(): string {\n\t\treturn `You are a helpful assistant with access to tools.\n Use the available tools to help users with their tasks.\n You can use the list_available_tools function to see what tools are currently available.\n Be concise and helpful in your responses.`\n\t}\n\n\tprivate handleSessionError(error: unknown): void {\n\t\tconsole.error('Session error:', error)\n\t\tthis.emitSessionState('error', {\n\t\t\ttype: 'session_error',\n\t\t\terror: String(error),\n\t\t})\n\t\tthis.stopSession()\n\t}\n\n\tprivate async initializeLocalAnalyzer(stream: MediaStream): Promise<void> {\n\t\tif (this.localAnalyzer) {\n\t\t\tthis.localAnalyzer.destroy()\n\t\t}\n\n\t\tthis.localAnalyzer = new AudioAnalyzer()\n\t\ttry {\n\t\t\t// Clone the stream to avoid conflicts with WebRTC which consumes the original\n\t\t\tconst clonedStream = new MediaStream(stream.getAudioTracks().map((t) => t.clone()))\n\t\t\tawait this.localAnalyzer.initialize(clonedStream)\n\t\t\tthis.startAudioVisualization()\n\t\t} catch (error) {\n\t\t\tconsole.error('[OpenAIRealtimeService] Failed to initialize local audio analyzer', error)\n\t\t\tif (this.localAnalyzer) {\n\t\t\t\tthis.localAnalyzer.destroy()\n\t\t\t\tthis.localAnalyzer = null\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async initializeRemoteAnalyzer(stream: MediaStream): Promise<void> {\n\t\tif (this.remoteAnalyzer) {\n\t\t\tthis.remoteAnalyzer.destroy()\n\t\t}\n\n\t\tthis.remoteAnalyzer = new AudioAnalyzer()\n\t\ttry {\n\t\t\t// Clone the stream to avoid conflicts with WebRTC\n\t\t\tconst clonedStream = new MediaStream(stream.getAudioTracks().map((t) => t.clone()))\n\t\t\tawait this.remoteAnalyzer.initialize(clonedStream)\n\t\t\tthis.startAudioVisualization()\n\t\t} catch (error) {\n\t\t\tconsole.error('[OpenAIRealtimeService] Failed to initialize remote audio analyzer', error)\n\t\t\tif (this.remoteAnalyzer) {\n\t\t\t\tthis.remoteAnalyzer.destroy()\n\t\t\t\tthis.remoteAnalyzer = null\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate startAudioVisualization(): void {\n\t\tif (!this.localAnalyzer && !this.remoteAnalyzer) {\n\t\t\tdebugLog('OpenAIRealtimeService', 'Audio visualization not started: no analyzers ready')\n\t\t\treturn\n\t\t}\n\n\t\tif (this.visualizationInterval) {\n\t\t\tclearInterval(this.visualizationInterval)\n\t\t}\n\n\t\tlet logCounter = 0\n\t\tthis.visualizationInterval = setInterval(() => {\n\t\t\tconst micLevel = this.localAnalyzer?.getAudioLevel() ?? 0\n\t\t\tconst micFrequency =\n\t\t\t\tthis.localAnalyzer?.getFrequencyData(AUDIO_FREQUENCY_BINS) ?? createZeroFrequencyArray()\n\t\t\tconst speakerLevel = this.remoteAnalyzer?.getAudioLevel() ?? 0\n\t\t\tconst speakerFrequency =\n\t\t\t\tthis.remoteAnalyzer?.getFrequencyData(AUDIO_FREQUENCY_BINS) ?? createZeroFrequencyArray()\n\n\t\t\t// Log audio levels periodically for debugging (every ~1 second)\n\t\t\tlogCounter++\n\t\t\tif (logCounter % 60 === 0) {\n\t\t\t\tdebugLog('OpenAIRealtimeService', 'Audio levels', {\n\t\t\t\t\tmic: micLevel.toFixed(3),\n\t\t\t\t\tspeaker: speakerLevel.toFixed(3),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthis.eventEmitter.emit('audio_level', {\n\t\t\t\tmicLevel,\n\t\t\t\tmicFrequency,\n\t\t\t\tspeakerLevel,\n\t\t\t\tspeakerFrequency,\n\t\t\t})\n\t\t}, AUDIO_VISUALIZATION_INTERVAL_MS)\n\t}\n\n\tprivate emitSessionState(\n\t\tstate: 'connecting' | 'connected' | 'disconnected' | 'error',\n\t\textra: Record<string, unknown> = {}\n\t): void {\n\t\tthis.lastState = state\n\t\tconst payload = {\n\t\t\tstate,\n\t\t\tisActive: state === 'connected',\n\t\t\tisMuted: this.muted,\n\t\t\t...extra,\n\t\t}\n\n\t\tthis.eventEmitter.emit('session_state', payload)\n\n\t\tswitch (state) {\n\t\t\tcase 'connecting':\n\t\t\t\tthis.eventEmitter.emit('session_connecting', payload)\n\t\t\t\tbreak\n\t\t\tcase 'connected':\n\t\t\t\tthis.eventEmitter.emit('session_connected', payload)\n\t\t\t\tbreak\n\t\t\tcase 'disconnected':\n\t\t\t\tthis.eventEmitter.emit('session_closed', payload)\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tthis.eventEmitter.emit('error', payload)\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Re-export types for convenience\nexport type { RealtimeConfig, RealtimeSession } from './types'\n","/**\n * Types for OpenAI Realtime API integration\n */\n\nexport interface RealtimeConfig {\n\tmodel?: string\n\tvoice?: string\n\tapiUrl?: string\n\ttokenEndpoint?: string\n}\n\nexport interface RealtimeSession {\n\tpc: RTCPeerConnection\n\tdataChannel: RTCDataChannel\n\taudioElement: HTMLAudioElement\n\tlocalStream: MediaStream | null\n\tremoteStream: MediaStream | null\n\tcleanup: () => void\n}\n\nexport interface OpenAITool {\n\ttype: 'function'\n\tname: string\n\tdescription: string\n\tparameters: {\n\t\ttype: string\n\t\tproperties?: Record<string, unknown>\n\t\trequired?: string[]\n\t}\n}\n\nexport interface SessionConfig {\n\tmodalities: string[]\n\tinstructions: string\n\tvoice?: string\n\ttools: OpenAITool[]\n\ttool_choice: string\n\tturn_detection: {\n\t\ttype: string\n\t\tthreshold: number\n\t\tprefix_padding_ms: number\n\t\tsilence_duration_ms: number\n\t}\n\tinput_audio_transcription?: {\n\t\tmodel: string\n\t}\n}\n\nexport interface FunctionCall {\n\tname: string\n\targuments: string\n\tcall_id: string\n\ttype?: string\n\tstatus?: string\n}\n\nexport interface ConversationItem {\n\ttype: string\n\trole?: string\n\tcontent?: unknown[]\n\tcall_id?: string\n\toutput?: string\n}\n\nexport interface RealtimeMessage {\n\ttype: string\n\t[key: string]: unknown\n}\n\nexport interface ToolExecutionResult {\n\tsuccess: boolean\n\tdata?: unknown\n\terror?: string\n}\n\nexport type EventCallback = (data: unknown) => void\n\nexport interface IEventEmitter {\n\ton(event: string, callback: EventCallback): void\n\toff(event: string, callback: EventCallback): void\n\temit(event: string, data: unknown): void\n}\n\nexport interface AudioLevelData {\n\tmicLevel: number\n\tmicFrequency: number[]\n\tspeakerLevel: number\n\tspeakerFrequency: number[]\n}\n\nexport interface TranscriptData {\n\ttype: 'user' | 'assistant'\n\ttext: string\n\tisDone: boolean\n}\n\nexport interface ToolCallData {\n\tstatus: 'started' | 'completed'\n\ttoolName: string\n\terror?: string\n}\n\nexport interface VoiceModeState {\n\tisActive: boolean\n\tisConnecting: boolean\n\tisMuted: boolean\n\tisError: boolean\n\tconnectionState: string\n\taudioLevel?: AudioLevelData\n\ttranscript?: TranscriptData\n\ttoolCall?: ToolCallData\n\terror?: string\n}\n\n// ============================================================================\n// Event Data Types - For type-safe event handling\n// ============================================================================\n\n/**\n * Session state event data from the realtime service\n */\nexport interface SessionStateEventData {\n\tstate: 'connecting' | 'connected' | 'disconnected' | 'error'\n\tisActive: boolean\n\tisMuted: boolean\n\tdurationSeconds?: number\n}\n\n/**\n * User transcript event data\n */\nexport interface UserTranscriptEventData {\n\ttext: string\n}\n\n/**\n * Assistant transcript streaming event data\n */\nexport interface AssistantTranscriptEventData {\n\tdelta?: string\n\ttranscript?: string\n}\n\n/**\n * Tool call started event data\n */\nexport interface ToolCallStartedEventData {\n\tname: string\n}\n\n/**\n * Tool call completed event data\n */\nexport interface ToolCallCompletedEventData {\n\tname: string\n\terror?: string\n}\n\n/**\n * Nested error object from OpenAI Realtime API\n */\nexport interface NestedErrorObject {\n\tcode?: string\n\tmessage?: string\n\tparam?: string\n\tevent_id?: string | null\n\ttype?: string\n}\n\n/**\n * Error event data\n * The 'error' field can be either a string or a nested error object from OpenAI\n */\nexport interface ErrorEventData {\n\terror?: string | NestedErrorObject\n\tmessage?: string\n\ttype?: string\n}\n\n// ============================================================================\n// Type Guards - Runtime type checking for event data\n// ============================================================================\n\n/**\n * Type guard for SessionStateEventData\n */\nexport function isSessionStateEventData(data: unknown): data is SessionStateEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn (\n\t\ttypeof d.state === 'string' &&\n\t\t['connecting', 'connected', 'disconnected', 'error'].includes(d.state) &&\n\t\ttypeof d.isActive === 'boolean' &&\n\t\ttypeof d.isMuted === 'boolean'\n\t)\n}\n\n/**\n * Type guard for UserTranscriptEventData\n */\nexport function isUserTranscriptEventData(data: unknown): data is UserTranscriptEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn typeof d.text === 'string'\n}\n\n/**\n * Type guard for AssistantTranscriptEventData\n */\nexport function isAssistantTranscriptEventData(\n\tdata: unknown\n): data is AssistantTranscriptEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn d.delta === undefined || typeof d.delta === 'string'\n}\n\n/**\n * Type guard for ToolCallStartedEventData\n */\nexport function isToolCallStartedEventData(data: unknown): data is ToolCallStartedEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn typeof d.name === 'string'\n}\n\n/**\n * Type guard for ToolCallCompletedEventData\n */\nexport function isToolCallCompletedEventData(data: unknown): data is ToolCallCompletedEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn typeof d.name === 'string'\n}\n\n/**\n * Type guard for ErrorEventData\n */\nexport function isErrorEventData(data: unknown): data is ErrorEventData {\n\tif (!data || typeof data !== 'object') return false\n\t// Error events must have at least one of these fields\n\tconst d = data as Record<string, unknown>\n\t// error can be a string OR an object with a message\n\tconst hasError = typeof d.error === 'string' || (typeof d.error === 'object' && d.error !== null)\n\treturn hasError || typeof d.message === 'string' || typeof d.type === 'string'\n}\n\n/**\n * Extract a string error message from ErrorEventData.\n * Handles both string errors and nested error objects from OpenAI Realtime API.\n */\nexport function extractErrorMessage(data: ErrorEventData): string {\n\t// Handle nested error object (OpenAI Realtime API format)\n\tif (data.error && typeof data.error === 'object') {\n\t\tconst nestedError = data.error as NestedErrorObject\n\t\treturn nestedError.message || nestedError.code || 'Unknown error'\n\t}\n\n\t// Handle string error\n\tif (typeof data.error === 'string') {\n\t\treturn data.error\n\t}\n\n\t// Fallback to message field\n\tif (typeof data.message === 'string') {\n\t\treturn data.message\n\t}\n\n\treturn 'Unknown error'\n}\n\n/**\n * Type guard for AudioLevelData\n */\nexport function isAudioLevelData(data: unknown): data is AudioLevelData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn (\n\t\ttypeof d.micLevel === 'number' &&\n\t\tArray.isArray(d.micFrequency) &&\n\t\ttypeof d.speakerLevel === 'number' &&\n\t\tArray.isArray(d.speakerFrequency)\n\t)\n}\n","/**\n * Voice Mode Hook\n *\n * Manages OpenAI Realtime API voice sessions with WebRTC.\n * Provides audio level streaming, transcript events, and tool call tracking.\n *\n * @example Basic usage\n * ```tsx\n * const {\n * isActive,\n * startSession,\n * stopSession,\n * toggleMute\n * } = useVoiceMode({\n * tokenEndpoint: '/api/realtime/session'\n * })\n * ```\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport {\n\tTOOL_CALL_DISPLAY_DURATION_MS,\n\tTOOL_CALL_ERROR_DISPLAY_DURATION_MS,\n} from '../lib/constants'\nimport {\n\textractErrorMessage,\n\tisAssistantTranscriptEventData,\n\tisAudioLevelData,\n\tisErrorEventData,\n\tisSessionStateEventData,\n\tisToolCallCompletedEventData,\n\tisToolCallStartedEventData,\n\tisUserTranscriptEventData,\n\tOpenAIRealtimeService,\n} from '../services/realtime'\n\nimport type {\n\tAudioLevelData,\n\tRealtimeConfig,\n\tRegisteredTool,\n\tToolCallData,\n\tToolExecutor,\n\tTranscriptData,\n\tVoiceModeState,\n} from '../services/realtime'\n\nexport interface UseVoiceModeOptions {\n\t/** Endpoint to get ephemeral tokens from */\n\ttokenEndpoint: string\n\t/** Tools available for the voice session */\n\ttools?: RegisteredTool[]\n\t/** Tool executor function */\n\ttoolExecutor?: ToolExecutor\n\t/** Callback when session connects */\n\tonConnect?: () => void\n\t/** Callback when session disconnects */\n\tonDisconnect?: (durationSeconds: number) => void\n\t/** Callback when error occurs */\n\tonError?: (error: string) => void\n\t/** Callback when user transcript is complete */\n\tonUserTranscript?: (text: string) => void\n\t/** Callback when assistant transcript is complete */\n\tonAssistantTranscript?: (text: string) => void\n}\n\nexport interface UseVoiceModeReturn extends VoiceModeState {\n\t/** Start voice session */\n\tstartSession: (config?: RealtimeConfig) => Promise<void>\n\t/** Stop voice session */\n\tstopSession: () => void\n\t/** Toggle microphone mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send text message while in voice mode */\n\tsendMessage: (text: string) => void\n\t/** Pause audio playback (for approval flow) */\n\tpauseAudio: () => void\n\t/** Resume audio playback (after approval flow) */\n\tresumeAudio: () => void\n}\n\nexport function useVoiceMode(options: UseVoiceModeOptions): UseVoiceModeReturn {\n\tconst {\n\t\ttokenEndpoint,\n\t\ttools,\n\t\ttoolExecutor,\n\t\tonConnect,\n\t\tonDisconnect,\n\t\tonError,\n\t\tonUserTranscript,\n\t\tonAssistantTranscript,\n\t} = options\n\n\t// State\n\tconst [isActive, setIsActive] = useState(false)\n\tconst [isConnecting, setIsConnecting] = useState(false)\n\tconst [isMuted, setIsMuted] = useState(false)\n\tconst [isError, setIsError] = useState(false)\n\tconst [connectionState, setConnectionState] = useState('disconnected')\n\tconst [audioLevel, setAudioLevel] = useState<AudioLevelData | undefined>()\n\tconst [transcript, setTranscript] = useState<TranscriptData | undefined>()\n\tconst [toolCall, setToolCall] = useState<ToolCallData | undefined>()\n\tconst [error, setError] = useState<string | undefined>()\n\n\t// Service ref\n\tconst serviceRef = useRef<OpenAIRealtimeService | null>(null)\n\n\t// Callbacks refs to avoid stale closures\n\tconst onConnectRef = useRef(onConnect)\n\tconst onDisconnectRef = useRef(onDisconnect)\n\tconst onErrorRef = useRef(onError)\n\tconst onUserTranscriptRef = useRef(onUserTranscript)\n\tconst onAssistantTranscriptRef = useRef(onAssistantTranscript)\n\n\tuseEffect(() => {\n\t\tonConnectRef.current = onConnect\n\t\tonDisconnectRef.current = onDisconnect\n\t\tonErrorRef.current = onError\n\t\tonUserTranscriptRef.current = onUserTranscript\n\t\tonAssistantTranscriptRef.current = onAssistantTranscript\n\t}, [onConnect, onDisconnect, onError, onUserTranscript, onAssistantTranscript])\n\n\t// Get or create service instance\n\tconst getService = useCallback(() => {\n\t\tif (!serviceRef.current) {\n\t\t\tserviceRef.current = new OpenAIRealtimeService(tokenEndpoint)\n\t\t}\n\t\treturn serviceRef.current\n\t}, [tokenEndpoint])\n\n\t// Update tools when they change\n\tuseEffect(() => {\n\t\tif (tools) {\n\t\t\tconst service = getService()\n\t\t\tservice.setTools(tools)\n\t\t}\n\t}, [tools, getService])\n\n\t// Update tool executor when it changes\n\tuseEffect(() => {\n\t\tif (toolExecutor) {\n\t\t\tconst service = getService()\n\t\t\tservice.setToolExecutor(toolExecutor)\n\t\t}\n\t}, [toolExecutor, getService])\n\n\t// Set up event listeners\n\tuseEffect(() => {\n\t\tconst service = getService()\n\n\t\t// Session state handler - uses type guard for safe access\n\t\tconst handleSessionState = (data: unknown) => {\n\t\t\tif (!isSessionStateEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid session state event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetConnectionState(data.state)\n\t\t\tsetIsActive(data.isActive)\n\t\t\tsetIsMuted(data.isMuted)\n\t\t\tsetIsConnecting(data.state === 'connecting')\n\t\t\tsetIsError(data.state === 'error')\n\n\t\t\tif (data.state === 'connected') {\n\t\t\t\tonConnectRef.current?.()\n\t\t\t} else if (data.state === 'disconnected') {\n\t\t\t\tonDisconnectRef.current?.(data.durationSeconds ?? 0)\n\t\t\t}\n\t\t}\n\n\t\t// Audio level handler - uses type guard for safe access\n\t\tconst handleAudioLevel = (data: unknown) => {\n\t\t\tif (isAudioLevelData(data)) {\n\t\t\t\tsetAudioLevel(data)\n\t\t\t}\n\t\t}\n\n\t\t// User transcript handler - uses type guard for safe access\n\t\tconst handleUserTranscript = (data: unknown) => {\n\t\t\tif (!isUserTranscriptEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid user transcript event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetTranscript({ type: 'user', text: data.text, isDone: true })\n\t\t\tonUserTranscriptRef.current?.(data.text)\n\t\t}\n\n\t\t// Assistant transcript handler (streaming) - uses type guard for safe access\n\t\tconst handleAssistantTranscript = (data: unknown) => {\n\t\t\tif (!isAssistantTranscriptEventData(data)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst text = data.delta || data.transcript || ''\n\t\t\tsetTranscript((prev) => ({\n\t\t\t\ttype: 'assistant',\n\t\t\t\ttext: prev?.type === 'assistant' ? prev.text + text : text,\n\t\t\t\tisDone: false,\n\t\t\t}))\n\t\t}\n\n\t\t// Assistant transcript done handler - uses type guard for safe access\n\t\tconst handleAssistantTranscriptDone = (data: unknown) => {\n\t\t\tif (!isAssistantTranscriptEventData(data)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst text = data.transcript || ''\n\t\t\tsetTranscript({ type: 'assistant', text, isDone: true })\n\t\t\tonAssistantTranscriptRef.current?.(text)\n\t\t}\n\n\t\t// Tool call started handler - uses type guard for safe access\n\t\tconst handleToolCallStarted = (data: unknown) => {\n\t\t\tif (!isToolCallStartedEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid tool call started event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetToolCall({ status: 'started', toolName: data.name })\n\t\t}\n\n\t\t// Tool call completed handler - uses type guard for safe access\n\t\tconst handleToolCallCompleted = (data: unknown) => {\n\t\t\tif (!isToolCallCompletedEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid tool call completed event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetToolCall({ status: 'completed', toolName: data.name, error: data.error })\n\n\t\t\t// Clear tool call after a delay (longer for errors)\n\t\t\tsetTimeout(\n\t\t\t\t() => {\n\t\t\t\t\tsetToolCall(undefined)\n\t\t\t\t},\n\t\t\t\tdata.error ? TOOL_CALL_ERROR_DISPLAY_DURATION_MS : TOOL_CALL_DISPLAY_DURATION_MS\n\t\t\t)\n\t\t}\n\n\t\t// Error handler - uses type guard for safe access\n\t\tconst handleError = (data: unknown) => {\n\t\t\tif (!isErrorEventData(data)) {\n\t\t\t\tsetError('Unknown error')\n\t\t\t\tsetIsError(true)\n\t\t\t\tonErrorRef.current?.('Unknown error')\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Use extractErrorMessage to handle both string and nested object errors\n\t\t\tconst errorMsg = extractErrorMessage(data)\n\t\t\tsetError(errorMsg)\n\t\t\tsetIsError(true)\n\t\t\tonErrorRef.current?.(errorMsg)\n\t\t}\n\n\t\t// Register listeners\n\t\tservice.on('session_state', handleSessionState)\n\t\tservice.on('audio_level', handleAudioLevel)\n\t\tservice.on('user_transcript_done', handleUserTranscript)\n\t\tservice.on('assistant_transcript', handleAssistantTranscript)\n\t\tservice.on('assistant_transcript_done', handleAssistantTranscriptDone)\n\t\tservice.on('tool_call_started', handleToolCallStarted)\n\t\tservice.on('tool_call_completed', handleToolCallCompleted)\n\t\tservice.on('error', handleError)\n\n\t\t// Cleanup\n\t\treturn () => {\n\t\t\tservice.off('session_state', handleSessionState)\n\t\t\tservice.off('audio_level', handleAudioLevel)\n\t\t\tservice.off('user_transcript_done', handleUserTranscript)\n\t\t\tservice.off('assistant_transcript', handleAssistantTranscript)\n\t\t\tservice.off('assistant_transcript_done', handleAssistantTranscriptDone)\n\t\t\tservice.off('tool_call_started', handleToolCallStarted)\n\t\t\tservice.off('tool_call_completed', handleToolCallCompleted)\n\t\t\tservice.off('error', handleError)\n\t\t}\n\t}, [getService])\n\n\t// Start session\n\tconst startSession = useCallback(\n\t\tasync (config?: RealtimeConfig) => {\n\t\t\ttry {\n\t\t\t\tsetIsConnecting(true)\n\t\t\t\tsetIsError(false)\n\t\t\t\tsetError(undefined)\n\n\t\t\t\tconst service = getService()\n\t\t\t\tawait service.startSession(config)\n\t\t\t} catch (err) {\n\t\t\t\tsetIsConnecting(false)\n\t\t\t\tsetIsError(true)\n\t\t\t\tconst errorMsg = err instanceof Error ? err.message : 'Failed to start session'\n\t\t\t\tsetError(errorMsg)\n\t\t\t\tonErrorRef.current?.(errorMsg)\n\t\t\t}\n\t\t},\n\t\t[getService]\n\t)\n\n\t// Stop session\n\tconst stopSession = useCallback(() => {\n\t\tconst service = getService()\n\t\tservice.stopSession()\n\t\tsetAudioLevel(undefined)\n\t\tsetTranscript(undefined)\n\t\tsetToolCall(undefined)\n\t}, [getService])\n\n\t// Toggle mute\n\tconst toggleMute = useCallback(\n\t\t(muted?: boolean) => {\n\t\t\tconst service = getService()\n\t\t\tconst newMuted = muted !== undefined ? muted : !isMuted\n\t\t\tservice.toggleMute(newMuted)\n\t\t\tsetIsMuted(newMuted)\n\t\t},\n\t\t[getService, isMuted]\n\t)\n\n\t// Send message\n\tconst sendMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tconst service = getService()\n\t\t\tif (service.isSessionActive()) {\n\t\t\t\tservice.sendUserMessage(text)\n\t\t\t}\n\t\t},\n\t\t[getService]\n\t)\n\n\t// Pause audio (for approval flow)\n\tconst pauseAudio = useCallback(() => {\n\t\tconst service = getService()\n\t\tservice.pauseAudio()\n\t}, [getService])\n\n\t// Resume audio (after approval flow)\n\tconst resumeAudio = useCallback(() => {\n\t\tconst service = getService()\n\t\tservice.resumeAudio()\n\t}, [getService])\n\n\t// Memoize return value\n\treturn useMemo(\n\t\t() => ({\n\t\t\tisActive,\n\t\t\tisConnecting,\n\t\t\tisMuted,\n\t\t\tisError,\n\t\t\tconnectionState,\n\t\t\taudioLevel,\n\t\t\ttranscript,\n\t\t\ttoolCall,\n\t\t\terror,\n\t\t\tstartSession,\n\t\t\tstopSession,\n\t\t\ttoggleMute,\n\t\t\tsendMessage,\n\t\t\tpauseAudio,\n\t\t\tresumeAudio,\n\t\t}),\n\t\t[\n\t\t\tisActive,\n\t\t\tisConnecting,\n\t\t\tisMuted,\n\t\t\tisError,\n\t\t\tconnectionState,\n\t\t\taudioLevel,\n\t\t\ttranscript,\n\t\t\ttoolCall,\n\t\t\terror,\n\t\t\tstartSession,\n\t\t\tstopSession,\n\t\t\ttoggleMute,\n\t\t\tsendMessage,\n\t\t\tpauseAudio,\n\t\t\tresumeAudio,\n\t\t]\n\t)\n}\n","import { createContext, useContext, useMemo } from 'react'\n\nimport { useVoiceMode } from '../hooks/useVoiceMode'\n\nimport type { ReactNode } from 'react'\nimport type { UseVoiceModeReturn } from '../hooks/useVoiceMode'\nimport type { RegisteredTool, ToolExecutor } from '../services/realtime'\n\n/**\n * Voice Mode Provider\n *\n * Provides voice mode state and controls to the component tree.\n */\n\nexport interface VoiceModeContextValue extends UseVoiceModeReturn {\n\tisSupported: boolean\n}\n\nconst VoiceModeContext = createContext<VoiceModeContextValue | null>(null)\n\nexport interface VoiceModeProviderProps {\n\tchildren: ReactNode\n\t/** Backend endpoint for ephemeral tokens */\n\ttokenEndpoint: string\n\t/** Tools available for voice mode */\n\ttools?: RegisteredTool[]\n\t/** Tool executor function */\n\ttoolExecutor?: ToolExecutor\n\t/** Callback when session connects */\n\tonConnect?: () => void\n\t/** Callback when session disconnects */\n\tonDisconnect?: (durationSeconds: number) => void\n\t/** Callback when error occurs */\n\tonError?: (error: string) => void\n\t/** Callback when user transcript is complete */\n\tonUserTranscript?: (text: string) => void\n\t/** Callback when assistant transcript is complete */\n\tonAssistantTranscript?: (text: string) => void\n}\n\n/**\n * Check if the browser supports WebRTC and getUserMedia\n */\nfunction checkVoiceModeSupport(): boolean {\n\treturn !!(\n\t\ttypeof window !== 'undefined' &&\n\t\twindow.RTCPeerConnection &&\n\t\tnavigator.mediaDevices?.getUserMedia\n\t)\n}\n\nexport function VoiceModeProvider({\n\tchildren,\n\ttokenEndpoint,\n\ttools,\n\ttoolExecutor,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n\tonUserTranscript,\n\tonAssistantTranscript,\n}: VoiceModeProviderProps) {\n\tconst voiceMode = useVoiceMode({\n\t\ttokenEndpoint,\n\t\ttools,\n\t\ttoolExecutor,\n\t\tonConnect,\n\t\tonDisconnect,\n\t\tonError,\n\t\tonUserTranscript,\n\t\tonAssistantTranscript,\n\t})\n\n\tconst isSupported = useMemo(() => checkVoiceModeSupport(), [])\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\t...voiceMode,\n\t\t\tisSupported,\n\t\t}),\n\t\t[voiceMode, isSupported]\n\t)\n\n\treturn <VoiceModeContext.Provider value={value}>{children}</VoiceModeContext.Provider>\n}\n\n/**\n * Hook to access voice mode context\n */\nexport function useVoiceModeContext(): VoiceModeContextValue {\n\tconst context = useContext(VoiceModeContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceModeContext must be used within a VoiceModeProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access voice mode context (returns null if not in provider)\n */\nexport function useOptionalVoiceModeContext(): VoiceModeContextValue | null {\n\treturn useContext(VoiceModeContext)\n}\n","/**\n * Voice Tool Approval Provider\n *\n * Manages tool approval state for voice mode. When a destructive tool is called\n * during a voice session, this provider pauses execution and waits for the user\n * to approve or deny (via voice keywords or button tap).\n *\n * Key features:\n * - 30-second timeout with auto-deny (safe default)\n * - Support for both voice keyword detection and button tap\n * - Single pending approval at a time (voice mode is sequential)\n *\n * @example\n * ```tsx\n * <VoiceToolApprovalProvider>\n * <VoiceMode />\n * </VoiceToolApprovalProvider>\n *\n * // In a component:\n * const { pendingApproval, approve, deny, requestApproval } = useVoiceToolApproval()\n * ```\n */\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS, VOICE_APPROVAL_TIMEOUT_MS } from '../lib/constants'\n\nimport type { FC, ReactNode } from 'react'\n\n/**\n * Pending approval request\n */\nexport interface VoicePendingApproval {\n\t/** Unique call ID from OpenAI Realtime */\n\tcallId: string\n\t/** Name of the tool being requested */\n\ttoolName: string\n\t/** Arguments passed to the tool */\n\targs: Record<string, unknown>\n\t/** Timestamp when approval was requested */\n\ttimestamp: number\n}\n\n/**\n * Voice Tool Approval Context Value\n */\nexport interface VoiceToolApprovalContextValue {\n\t/** Current pending approval (null if none) */\n\tpendingApproval: VoicePendingApproval | null\n\t/** Approve the current pending tool call */\n\tapprove: () => void\n\t/** Deny the current pending tool call */\n\tdeny: () => void\n\t/** Seconds remaining before auto-deny */\n\ttimeoutRemaining: number\n\t/** Whether we're currently waiting for approval */\n\tisWaitingForApproval: boolean\n\t/**\n\t * Request approval for a tool call.\n\t * Returns a Promise that resolves to true (approved) or false (denied/timeout).\n\t */\n\trequestApproval: (\n\t\tcallId: string,\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>\n\t) => Promise<boolean>\n\t/** Clear any pending approval without resolving (e.g., when voice session ends) */\n\tclearPendingApproval: () => void\n}\n\nconst VoiceToolApprovalContext = createContext<VoiceToolApprovalContextValue | null>(null)\n\nexport interface VoiceToolApprovalProviderProps {\n\tchildren: ReactNode\n\t/** Custom timeout in milliseconds (defaults to VOICE_APPROVAL_TIMEOUT_MS) */\n\ttimeout?: number\n\t/** Callback when approval times out */\n\tonTimeout?: (toolName: string) => void\n\t/** Callback when user approves */\n\tonApprove?: (toolName: string) => void\n\t/** Callback when user denies */\n\tonDeny?: (toolName: string) => void\n}\n\n/**\n * Provider for voice mode tool approval.\n *\n * Wraps voice mode components to enable approval workflow for destructive tools.\n */\nexport const VoiceToolApprovalProvider: FC<VoiceToolApprovalProviderProps> = ({\n\tchildren,\n\ttimeout = VOICE_APPROVAL_TIMEOUT_MS,\n\tonTimeout,\n\tonApprove,\n\tonDeny,\n}) => {\n\t// Current pending approval\n\tconst [pendingApproval, setPendingApproval] = useState<VoicePendingApproval | null>(null)\n\n\t// Time remaining for countdown\n\tconst [timeoutRemaining, setTimeoutRemaining] = useState(0)\n\n\t// Refs for the resolve function and timeout\n\tconst resolveRef = useRef<((approved: boolean) => void) | null>(null)\n\tconst timeoutIdRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\tconst countdownIdRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n\t// Callback refs to avoid stale closures\n\tconst onTimeoutRef = useRef(onTimeout)\n\tconst onApproveRef = useRef(onApprove)\n\tconst onDenyRef = useRef(onDeny)\n\tonTimeoutRef.current = onTimeout\n\tonApproveRef.current = onApprove\n\tonDenyRef.current = onDeny\n\n\t/**\n\t * Clear all timers\n\t */\n\tconst clearTimers = useCallback(() => {\n\t\tif (timeoutIdRef.current) {\n\t\t\tclearTimeout(timeoutIdRef.current)\n\t\t\ttimeoutIdRef.current = null\n\t\t}\n\t\tif (countdownIdRef.current) {\n\t\t\tclearInterval(countdownIdRef.current)\n\t\t\tcountdownIdRef.current = null\n\t\t}\n\t}, [])\n\n\t/**\n\t * Resolve the pending approval and clean up\n\t */\n\tconst resolveApproval = useCallback(\n\t\t(approved: boolean, reason: 'approve' | 'deny' | 'timeout' = approved ? 'approve' : 'deny') => {\n\t\t\tconst toolName = pendingApproval?.toolName\n\n\t\t\t// Resolve the promise\n\t\t\tif (resolveRef.current) {\n\t\t\t\tresolveRef.current(approved)\n\t\t\t\tresolveRef.current = null\n\t\t\t}\n\n\t\t\t// Clear state\n\t\t\tclearTimers()\n\t\t\tsetPendingApproval(null)\n\t\t\tsetTimeoutRemaining(0)\n\n\t\t\t// Fire callbacks\n\t\t\tif (toolName) {\n\t\t\t\tif (reason === 'timeout') {\n\t\t\t\t\tonTimeoutRef.current?.(toolName)\n\t\t\t\t} else if (reason === 'approve') {\n\t\t\t\t\tonApproveRef.current?.(toolName)\n\t\t\t\t} else {\n\t\t\t\t\tonDenyRef.current?.(toolName)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[pendingApproval?.toolName, clearTimers]\n\t)\n\n\t/**\n\t * Approve the current pending tool call\n\t */\n\tconst approve = useCallback(() => {\n\t\tif (pendingApproval) {\n\t\t\tresolveApproval(true, 'approve')\n\t\t}\n\t}, [pendingApproval, resolveApproval])\n\n\t/**\n\t * Deny the current pending tool call\n\t */\n\tconst deny = useCallback(() => {\n\t\tif (pendingApproval) {\n\t\t\tresolveApproval(false, 'deny')\n\t\t}\n\t}, [pendingApproval, resolveApproval])\n\n\t/**\n\t * Clear pending approval without resolving (for cleanup)\n\t */\n\tconst clearPendingApproval = useCallback(() => {\n\t\tif (resolveRef.current) {\n\t\t\tresolveRef.current(false)\n\t\t\tresolveRef.current = null\n\t\t}\n\t\tclearTimers()\n\t\tsetPendingApproval(null)\n\t\tsetTimeoutRemaining(0)\n\t}, [clearTimers])\n\n\t/**\n\t * Request approval for a tool call.\n\t * Returns a Promise that resolves when the user approves/denies or timeout occurs.\n\t */\n\tconst requestApproval = useCallback(\n\t\t(callId: string, toolName: string, args: Record<string, unknown>): Promise<boolean> => {\n\t\t\treturn new Promise((resolve) => {\n\t\t\t\t// If there's already a pending approval, deny it first\n\t\t\t\tif (resolveRef.current) {\n\t\t\t\t\tresolveRef.current(false)\n\t\t\t\t}\n\t\t\t\tclearTimers()\n\n\t\t\t\t// Store the resolve function\n\t\t\t\tresolveRef.current = resolve\n\n\t\t\t\t// Set pending approval state\n\t\t\t\tsetPendingApproval({\n\t\t\t\t\tcallId,\n\t\t\t\t\ttoolName,\n\t\t\t\t\targs,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t})\n\n\t\t\t\t// Set initial timeout remaining\n\t\t\t\tconst timeoutSeconds = Math.ceil(timeout / 1000)\n\t\t\t\tsetTimeoutRemaining(timeoutSeconds)\n\n\t\t\t\t// Start countdown interval\n\t\t\t\tcountdownIdRef.current = setInterval(() => {\n\t\t\t\t\tsetTimeoutRemaining((prev) => {\n\t\t\t\t\t\tif (prev <= 1) {\n\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn prev - 1\n\t\t\t\t\t})\n\t\t\t\t}, VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS)\n\n\t\t\t\t// Set auto-deny timeout\n\t\t\t\ttimeoutIdRef.current = setTimeout(() => {\n\t\t\t\t\t// Auto-deny on timeout\n\t\t\t\t\tif (resolveRef.current) {\n\t\t\t\t\t\tresolveRef.current(false)\n\t\t\t\t\t\tresolveRef.current = null\n\t\t\t\t\t}\n\t\t\t\t\tclearTimers()\n\t\t\t\t\tsetPendingApproval(null)\n\t\t\t\t\tsetTimeoutRemaining(0)\n\t\t\t\t\tonTimeoutRef.current?.(toolName)\n\t\t\t\t}, timeout)\n\t\t\t})\n\t\t},\n\t\t[timeout, clearTimers]\n\t)\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tclearTimers()\n\t\t\tif (resolveRef.current) {\n\t\t\t\tresolveRef.current(false)\n\t\t\t\tresolveRef.current = null\n\t\t\t}\n\t\t}\n\t}, [clearTimers])\n\n\tconst value = useMemo<VoiceToolApprovalContextValue>(\n\t\t() => ({\n\t\t\tpendingApproval,\n\t\t\tapprove,\n\t\t\tdeny,\n\t\t\ttimeoutRemaining,\n\t\t\tisWaitingForApproval: pendingApproval !== null,\n\t\t\trequestApproval,\n\t\t\tclearPendingApproval,\n\t\t}),\n\t\t[pendingApproval, approve, deny, timeoutRemaining, requestApproval, clearPendingApproval]\n\t)\n\n\treturn (\n\t\t<VoiceToolApprovalContext.Provider value={value}>{children}</VoiceToolApprovalContext.Provider>\n\t)\n}\n\n/**\n * Hook to access voice tool approval context.\n * @throws Error if used outside VoiceToolApprovalProvider\n */\nexport function useVoiceToolApproval(): VoiceToolApprovalContextValue {\n\tconst context = useContext(VoiceToolApprovalContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceToolApproval must be used within a VoiceToolApprovalProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access voice tool approval context.\n * Returns null if not within provider.\n */\nexport function useOptionalVoiceToolApproval(): VoiceToolApprovalContextValue | null {\n\treturn useContext(VoiceToolApprovalContext)\n}\n","/**\n * VoiceThreadBridge\n *\n * Bridges voice mode events to the assistant-ui thread.\n * When voice transcripts and tool calls occur, they are pushed into the thread\n * as real messages, making assistant-ui the single source of truth.\n *\n * This replaces the separate voice state tracking (useVoiceActions, useVoiceSummary)\n * with unified thread state.\n *\n * Voice messages are tagged with metadata to distinguish them from text messages:\n * - metadata.source: 'voice'\n * - metadata.voiceSessionId: unique session identifier\n *\n * Tool calls from voice mode are also added to the thread with full metadata\n * (timing, source attribution) matching the text mode behavior.\n */\n\nimport { useThreadRuntime } from '@assistant-ui/react'\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { VOICE_TOOL_RESULT_MESSAGES } from '../lib/constants'\nimport { TOOL_DENIED_MESSAGE } from '../lib/format'\nimport { resolveAllPendingToolCalls, resolveAllPendingToolCallsByName } from '../lib/thread-utils'\nimport { useOptionalMCPTools } from './MCPToolsProvider'\nimport { useOptionalToolApproval } from './ToolApprovalProvider'\nimport { useOptionalVoiceModeContext, VoiceModeProvider } from './VoiceModeProvider'\nimport {\n\tuseOptionalVoiceToolApproval,\n\tVoiceToolApprovalProvider,\n} from './VoiceToolApprovalProvider'\n\nimport type { ToolCallMetadata, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { FC, MutableRefObject, ReactNode } from 'react'\nimport type { RegisteredTool, ToolExecutor } from '../services/realtime'\n\n/**\n * Data needed to add a voice tool call to the thread\n */\ninterface VoiceToolCallData {\n\ttoolCallId: string\n\ttoolName: string\n\targs: Record<string, unknown>\n\tresult: string\n\tisError: boolean\n\tartifact: ToolCallMetadata\n}\n\n/**\n * Callback type for adding tool calls to thread\n */\ntype AddToolCallToThread = (data: VoiceToolCallData) => void\n\n/**\n * Voice session metadata attached to messages\n */\nexport interface VoiceMessageMetadata {\n\tsource: 'voice'\n\tvoiceSessionId: string\n\ttimestamp: number\n}\n\n/**\n * Voice thread context - provides voice controls and current session info\n */\nexport interface VoiceThreadContextValue {\n\t/** Whether a voice session is active */\n\tisActive: boolean\n\t/** Whether voice is connecting */\n\tisConnecting: boolean\n\t/** Whether there's a voice error */\n\tisError: boolean\n\t/** Whether microphone is muted */\n\tisMuted: boolean\n\t/** Whether voice mode is supported in this browser */\n\tisSupported: boolean\n\t/** Current error message */\n\terror?: string\n\t/** Current voice session ID (null if no active session) */\n\tsessionId: string | null\n\t/** Start a voice session */\n\tstart: () => Promise<void>\n\t/** Stop the voice session */\n\tstop: () => void\n\t/** Toggle microphone mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send a text message in voice mode */\n\tsendMessage: (text: string) => void\n\t/** Pause audio playback (for approval flow) */\n\tpauseAudio: () => void\n\t/** Resume audio playback (after approval flow) */\n\tresumeAudio: () => void\n\t/** Audio level data for visualization */\n\taudioLevel?: {\n\t\tmicLevel: number\n\t\tspeakerLevel: number\n\t}\n\t/** Current transcript being spoken */\n\ttranscript?: {\n\t\ttype: 'user' | 'assistant'\n\t\ttext: string\n\t\tisDone: boolean\n\t}\n\t/** Current tool call being executed */\n\ttoolCall?: {\n\t\tstatus: 'started' | 'completed'\n\t\ttoolName: string\n\t\terror?: string\n\t}\n}\n\nconst VoiceThreadContext = createContext<VoiceThreadContextValue | null>(null)\n\n/**\n * Generate a unique session ID\n */\nfunction generateSessionId(): string {\n\treturn `voice-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n/**\n * Convert MCP tools to the format expected by the voice service\n */\nfunction convertToRegisteredTool(tool: ToolWithSource): RegisteredTool {\n\treturn {\n\t\tname: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tinputSchema: (tool.inputSchema ?? { type: 'object', properties: {} }) as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>,\n\t}\n}\n\nexport interface VoiceThreadBridgeProps {\n\tchildren: ReactNode\n\t/** Token endpoint for voice sessions */\n\ttokenEndpoint: string\n\t/** Callback when voice session connects */\n\tonConnect?: () => void\n\t/** Callback when voice session disconnects */\n\tonDisconnect?: (durationSeconds: number) => void\n\t/** Callback when voice error occurs */\n\tonError?: (error: string) => void\n}\n\n/**\n * Internal component that bridges voice events to the thread.\n * Must be used inside both VoiceModeProvider and AssistantRuntimeProvider.\n */\nconst VoiceThreadIntegrator: FC<{\n\tchildren: ReactNode\n\tsessionId: string | null\n\tsetSessionId: (id: string | null) => void\n\taddToolCallRef: MutableRefObject<AddToolCallToThread | null>\n\tonConnect?: () => void\n\tonDisconnect?: (durationSeconds: number) => void\n\tonError?: (error: string) => void\n}> = ({ children, sessionId, setSessionId, addToolCallRef, onConnect, onDisconnect, onError }) => {\n\tconst threadRuntime = useThreadRuntime()\n\tconst voiceMode = useOptionalVoiceModeContext()\n\n\t// Track last transcript to detect changes\n\tconst lastUserTranscriptRef = useRef<string>('')\n\tconst lastAssistantTranscriptRef = useRef<string>('')\n\tconst wasActiveRef = useRef(false)\n\n\t// Refs for callbacks\n\tconst onConnectRef = useRef(onConnect)\n\tconst onDisconnectRef = useRef(onDisconnect)\n\tconst onErrorRef = useRef(onError)\n\tonConnectRef.current = onConnect\n\tonDisconnectRef.current = onDisconnect\n\tonErrorRef.current = onError\n\n\t/**\n\t * Set up the callback for adding tool calls to thread.\n\t * This is called by toolExecutor when a voice tool call completes.\n\t */\n\tuseEffect(() => {\n\t\taddToolCallRef.current = (data: VoiceToolCallData) => {\n\t\t\tif (!sessionId) {\n\t\t\t\tconsole.warn('[VoiceThreadIntegrator] Cannot add tool call - no active session')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Append complete tool-call message to thread\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tthreadRuntime.append({\n\t\t\t\trole: 'assistant',\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'tool-call',\n\t\t\t\t\t\ttoolCallId: data.toolCallId,\n\t\t\t\t\t\ttoolName: data.toolName,\n\t\t\t\t\t\targs: data.args,\n\t\t\t\t\t\targsText: JSON.stringify(data.args),\n\t\t\t\t\t\tresult: data.result,\n\t\t\t\t\t\tisError: data.isError,\n\t\t\t\t\t\tartifact: data.artifact,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tmetadata: {\n\t\t\t\t\tcustom: {\n\t\t\t\t\t\tsource: 'voice',\n\t\t\t\t\t\tvoiceSessionId: sessionId,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t} as any)\n\t\t}\n\n\t\treturn () => {\n\t\t\taddToolCallRef.current = null\n\t\t}\n\t}, [threadRuntime, sessionId, addToolCallRef])\n\n\t/**\n\t * Add a user message to the thread (from voice transcript)\n\t */\n\tconst addUserMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (!sessionId || !text.trim()) return\n\n\t\t\t// Use custom metadata for voice messages\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst metadata: any = {\n\t\t\t\tcustom: {\n\t\t\t\t\tsource: 'voice',\n\t\t\t\t\tvoiceSessionId: sessionId,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthreadRuntime.append({\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: [{ type: 'text', text }],\n\t\t\t\tmetadata,\n\t\t\t})\n\t\t},\n\t\t[threadRuntime, sessionId]\n\t)\n\n\t/**\n\t * Add an assistant message to the thread (from voice transcript)\n\t */\n\tconst addAssistantMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (!sessionId || !text.trim()) return\n\n\t\t\t// Use custom metadata for voice messages\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst metadata: any = {\n\t\t\t\tcustom: {\n\t\t\t\t\tsource: 'voice',\n\t\t\t\t\tvoiceSessionId: sessionId,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthreadRuntime.append({\n\t\t\t\trole: 'assistant',\n\t\t\t\tcontent: [{ type: 'text', text }],\n\t\t\t\tmetadata,\n\t\t\t})\n\t\t},\n\t\t[threadRuntime, sessionId]\n\t)\n\n\t// Track session state changes\n\tuseEffect(() => {\n\t\tif (!voiceMode) return\n\n\t\tconst isActive = voiceMode.isActive || voiceMode.isConnecting\n\n\t\t// Session just started\n\t\tif (!wasActiveRef.current && isActive && !sessionId) {\n\t\t\tconst newSessionId = generateSessionId()\n\t\t\tsetSessionId(newSessionId)\n\t\t}\n\n\t\t// Session just connected\n\t\tif (!wasActiveRef.current && voiceMode.isActive) {\n\t\t\tonConnectRef.current?.()\n\t\t}\n\n\t\t// Session just ended\n\t\tif (wasActiveRef.current && !isActive) {\n\t\t\t// Add final assistant message if we have one\n\t\t\t// CRITICAL: Clear refs immediately after use to prevent race condition with transcript effect\n\t\t\t// Both effects can fire in the same render cycle, causing duplicate message IDs\n\t\t\tif (lastAssistantTranscriptRef.current) {\n\t\t\t\taddAssistantMessage(lastAssistantTranscriptRef.current)\n\t\t\t\tlastAssistantTranscriptRef.current = ''\n\t\t\t}\n\t\t\tlastUserTranscriptRef.current = ''\n\n\t\t\t// Clear any remaining pending thread elicitations to prevent duplicate approval UI\n\t\t\tresolveAllPendingToolCalls(threadRuntime, VOICE_TOOL_RESULT_MESSAGES.sessionEnded)\n\n\t\t\t// Clear session\n\t\t\tsetSessionId(null)\n\n\t\t\t// Notify disconnect (duration is not easily available here, use 0)\n\t\t\tonDisconnectRef.current?.(0)\n\t\t}\n\n\t\twasActiveRef.current = isActive\n\t}, [\n\t\tvoiceMode?.isActive,\n\t\tvoiceMode?.isConnecting,\n\t\tsessionId,\n\t\tsetSessionId,\n\t\taddAssistantMessage,\n\t\tthreadRuntime,\n\t])\n\n\t// Track transcript changes and push to thread\n\tuseEffect(() => {\n\t\tif (!voiceMode?.transcript || !sessionId) return\n\n\t\tconst { type, text, isDone } = voiceMode.transcript\n\n\t\tif (type === 'user' && isDone && text !== lastUserTranscriptRef.current) {\n\t\t\t// If we had a pending assistant message, add it first to maintain order\n\t\t\tif (lastAssistantTranscriptRef.current) {\n\t\t\t\taddAssistantMessage(lastAssistantTranscriptRef.current)\n\t\t\t\tlastAssistantTranscriptRef.current = ''\n\t\t\t}\n\n\t\t\t// User finished speaking - add to thread\n\t\t\taddUserMessage(text)\n\t\t\tlastUserTranscriptRef.current = text\n\t\t} else if (type === 'assistant' && isDone && text !== lastAssistantTranscriptRef.current) {\n\t\t\t// Store assistant transcript - we'll add it to thread when:\n\t\t\t// 1. User speaks next (to maintain conversation order)\n\t\t\t// 2. Session ends\n\t\t\tlastAssistantTranscriptRef.current = text\n\t\t}\n\t}, [voiceMode?.transcript, sessionId, addUserMessage, addAssistantMessage])\n\n\t// Track errors\n\tuseEffect(() => {\n\t\tif (voiceMode?.isError && voiceMode?.error) {\n\t\t\tonErrorRef.current?.(voiceMode.error)\n\t\t}\n\t}, [voiceMode?.isError, voiceMode?.error])\n\n\treturn <>{children}</>\n}\n\n/**\n * Inner component that creates the approval-aware tool executor.\n * Must be inside VoiceToolApprovalProvider to access the approval context.\n */\nconst ApprovalAwareVoiceBridge: FC<{\n\tchildren: ReactNode\n\ttokenEndpoint: string\n\tvoiceTools: RegisteredTool[]\n\tsessionId: string | null\n\tsetSessionId: (id: string | null) => void\n\taddToolCallRef: MutableRefObject<AddToolCallToThread | null>\n\tonConnect?: () => void\n\tonDisconnect?: (durationSeconds: number) => void\n\tonError?: (error: string) => void\n}> = ({\n\tchildren,\n\ttokenEndpoint,\n\tvoiceTools,\n\tsessionId,\n\tsetSessionId,\n\taddToolCallRef,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst mcpTools = useOptionalMCPTools()\n\tconst toolApproval = useOptionalToolApproval()\n\tconst voiceToolApproval = useOptionalVoiceToolApproval()\n\tconst threadRuntime = useThreadRuntime()\n\n\t// Tool executor that routes to MCP with approval checking\n\tconst toolExecutor: ToolExecutor = useCallback(\n\t\tasync (name: string, args: Record<string, unknown>) => {\n\t\t\tif (!mcpTools?.callTool) {\n\t\t\t\tthrow new Error('MCP tools not available')\n\t\t\t}\n\n\t\t\t// Check if tool requires approval\n\t\t\tconst tool = mcpTools.tools.find((t) => t.name === name)\n\t\t\tconst needsApproval = tool && toolApproval?.requiresApproval(tool)\n\n\t\t\tif (needsApproval && voiceToolApproval) {\n\t\t\t\t// Generate a call ID for this approval request\n\t\t\t\tconst callId = `voice-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n\n\t\t\t\t// Request approval and wait for response\n\t\t\t\tconst approved = await voiceToolApproval.requestApproval(callId, name, args)\n\n\t\t\t\t// Sync voice approval to thread to prevent duplicate approval UI in text mode\n\t\t\t\tconst resultMessage = approved ? VOICE_TOOL_RESULT_MESSAGES.handled : TOOL_DENIED_MESSAGE\n\t\t\t\tresolveAllPendingToolCallsByName(threadRuntime, name, resultMessage)\n\n\t\t\t\tif (!approved) {\n\t\t\t\t\t// User denied or timeout - return denial message\n\t\t\t\t\treturn TOOL_DENIED_MESSAGE\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Execute the tool\n\t\t\tconst result = await mcpTools.callTool(name, args)\n\n\t\t\t// Extract text content from MCP result\n\t\t\tconst textContent = result.content?.find(\n\t\t\t\t(c: { type: string; text?: string }): c is { type: 'text'; text: string } =>\n\t\t\t\t\tc.type === 'text'\n\t\t\t)\n\t\t\treturn textContent?.text ?? JSON.stringify(result)\n\t\t},\n\t\t[mcpTools, toolApproval, voiceToolApproval, threadRuntime]\n\t)\n\n\treturn (\n\t\t<VoiceModeProvider tokenEndpoint={tokenEndpoint} tools={voiceTools} toolExecutor={toolExecutor}>\n\t\t\t<VoiceThreadIntegrator\n\t\t\t\tsessionId={sessionId}\n\t\t\t\tsetSessionId={setSessionId}\n\t\t\t\taddToolCallRef={addToolCallRef}\n\t\t\t\tonConnect={onConnect}\n\t\t\t\tonDisconnect={onDisconnect}\n\t\t\t\tonError={onError}\n\t\t\t>\n\t\t\t\t<VoiceThreadContextProvider sessionId={sessionId}>{children}</VoiceThreadContextProvider>\n\t\t\t</VoiceThreadIntegrator>\n\t\t</VoiceModeProvider>\n\t)\n}\n\n/**\n * Bridge component that integrates voice mode with the assistant-ui thread.\n *\n * When voice events occur:\n * 1. User transcripts are added as user messages to the thread\n * 2. Assistant transcripts are added as assistant messages\n * 3. Tool calls are added as tool-call parts with full metadata (timing, source)\n * This ensures the thread is the single source of truth for all conversation history,\n * including tool calls from voice mode with the same metadata as text mode.\n *\n * Voice tool approval:\n * When a destructive tool is called during voice mode, the VoiceToolApprovalProvider\n * pauses execution and shows an approval UI. User can approve via voice keywords\n * (\"approve\", \"yes\") or by tapping buttons.\n */\nexport const VoiceThreadBridge: FC<VoiceThreadBridgeProps> = ({\n\tchildren,\n\ttokenEndpoint,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst mcpTools = useOptionalMCPTools()\n\n\t// Session ID managed at this level so it persists across voice mode restarts\n\tconst [sessionId, setSessionId] = useState<string | null>(null)\n\n\t// Ref for adding tool calls to thread (set by VoiceThreadIntegrator)\n\tconst addToolCallRef = useRef<AddToolCallToThread | null>(null)\n\n\t// Convert MCP tools for voice mode\n\tconst voiceTools = useMemo<RegisteredTool[]>(() => {\n\t\tif (!mcpTools?.tools) return []\n\t\treturn mcpTools.tools.map(convertToRegisteredTool)\n\t}, [mcpTools?.tools])\n\n\treturn (\n\t\t<VoiceToolApprovalProvider>\n\t\t\t<ApprovalAwareVoiceBridge\n\t\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\t\tvoiceTools={voiceTools}\n\t\t\t\tsessionId={sessionId}\n\t\t\t\tsetSessionId={setSessionId}\n\t\t\t\taddToolCallRef={addToolCallRef}\n\t\t\t\tonConnect={onConnect}\n\t\t\t\tonDisconnect={onDisconnect}\n\t\t\t\tonError={onError}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</ApprovalAwareVoiceBridge>\n\t\t</VoiceToolApprovalProvider>\n\t)\n}\n\n/**\n * Internal provider that exposes voice thread context\n */\nconst VoiceThreadContextProvider: FC<{ children: ReactNode; sessionId: string | null }> = ({\n\tchildren,\n\tsessionId,\n}) => {\n\tconst voiceMode = useOptionalVoiceModeContext()\n\n\t// Build context value from voice mode\n\tconst contextValue = useMemo<VoiceThreadContextValue | null>(() => {\n\t\tif (!voiceMode) return null\n\n\t\treturn {\n\t\t\tisActive: voiceMode.isActive,\n\t\t\tisConnecting: voiceMode.isConnecting,\n\t\t\tisError: voiceMode.isError,\n\t\t\tisMuted: voiceMode.isMuted,\n\t\t\tisSupported: voiceMode.isSupported,\n\t\t\terror: voiceMode.error,\n\t\t\tsessionId,\n\t\t\taudioLevel: voiceMode.audioLevel\n\t\t\t\t? {\n\t\t\t\t\t\tmicLevel: voiceMode.audioLevel.micLevel,\n\t\t\t\t\t\tspeakerLevel: voiceMode.audioLevel.speakerLevel,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\ttranscript: voiceMode.transcript\n\t\t\t\t? {\n\t\t\t\t\t\ttype: voiceMode.transcript.type,\n\t\t\t\t\t\ttext: voiceMode.transcript.text,\n\t\t\t\t\t\tisDone: voiceMode.transcript.isDone,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\ttoolCall: voiceMode.toolCall\n\t\t\t\t? {\n\t\t\t\t\t\tstatus: voiceMode.toolCall.status,\n\t\t\t\t\t\ttoolName: voiceMode.toolCall.toolName,\n\t\t\t\t\t\terror: voiceMode.toolCall.error,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tstart: voiceMode.startSession,\n\t\t\tstop: voiceMode.stopSession,\n\t\t\ttoggleMute: voiceMode.toggleMute,\n\t\t\tsendMessage: voiceMode.sendMessage,\n\t\t\tpauseAudio: voiceMode.pauseAudio,\n\t\t\tresumeAudio: voiceMode.resumeAudio,\n\t\t}\n\t}, [voiceMode, sessionId])\n\n\tif (!contextValue) {\n\t\treturn <>{children}</>\n\t}\n\n\treturn <VoiceThreadContext.Provider value={contextValue}>{children}</VoiceThreadContext.Provider>\n}\n\n/**\n * Hook to access voice thread controls\n * @throws Error if used outside VoiceThreadBridge\n */\nexport function useVoiceThread(): VoiceThreadContextValue {\n\tconst context = useContext(VoiceThreadContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceThread must be used within a VoiceThreadBridge')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access voice thread controls\n */\nexport function useOptionalVoiceThread(): VoiceThreadContextValue | null {\n\treturn useContext(VoiceThreadContext)\n}\n\n/**\n * Hook to check if voice mode is available and active\n */\nexport function useIsVoiceActive(): boolean {\n\tconst context = useOptionalVoiceThread()\n\treturn context?.isActive ?? false\n}\n","/**\n * useAgent - Unified Agent Hook\n *\n * The main hook for accessing agent state and capabilities.\n * This is a thin facade over assistant-ui's thread state.\n *\n * Thread state (messages, actions) comes from @assistant-ui/react.\n * Voice transcripts and tool calls are also stored in the thread\n * (via VoiceThreadBridge), making assistant-ui the single source of truth.\n *\n * @example Basic usage\n * ```tsx\n * function MyComponent() {\n * const agent = useAgent()\n *\n * return (\n * <div>\n * {agent.isRunning && <p>Processing...</p>}\n * {agent.messages.map(m => <Message key={m.id} {...m} />)}\n * {agent.voice?.isActive && <p>Voice active</p>}\n * </div>\n * )\n * }\n * ```\n */\n\nimport { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { useLatestSummary } from '../../components/pill/SummaryBlock'\nimport {\n\tuseActions,\n\tuseCurrentAction,\n\tuseLastCompletedAction,\n\tuseRecentActions,\n} from '../../hooks/useActions'\nimport { useOptionalMCPTools } from '../../providers/MCPToolsProvider'\nimport { useOptionalVoiceThread } from '../../providers/VoiceThreadBridge'\n\nimport type { CallToolResult, Prompt, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { Action } from '../../hooks/useActions'\n\n/**\n * Voice mode state and controls\n */\nexport interface AgentVoice {\n\t/** Whether voice session is active */\n\tisActive: boolean\n\t/** Whether voice is connecting */\n\tisConnecting: boolean\n\t/** Whether there's an error */\n\tisError: boolean\n\t/** Whether microphone is muted */\n\tisMuted: boolean\n\t/** Whether voice mode is supported */\n\tisSupported: boolean\n\t/** Current error message */\n\terror?: string\n\t/** Current voice session ID */\n\tsessionId: string | null\n\t/** Audio level for visualization */\n\taudioLevel?: { micLevel: number; speakerLevel: number }\n\t/** Current transcript being spoken */\n\ttranscript?: { type: 'user' | 'assistant'; text: string; isDone: boolean }\n\t/** Start voice session */\n\tstart: () => Promise<void>\n\t/** Stop voice session */\n\tstop: () => void\n\t/** Toggle microphone mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send text message while in voice mode */\n\tsendMessage: (text: string) => void\n}\n\n/**\n * MCP tools state and controls\n */\nexport interface AgentTools {\n\t/** All available tools */\n\tlist: ToolWithSource[]\n\t/** Call a tool by name */\n\tcall: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>\n\t/** Available prompts */\n\tprompts: Prompt[]\n\t/** Get expanded prompt content */\n\tgetPrompt: ((name: string) => Promise<GetPromptResult>) | undefined\n}\n\n/**\n * Thread message type (simplified for external consumers)\n */\nexport interface AgentMessage {\n\tid: string\n\trole: 'user' | 'assistant' | 'system'\n\tcontent: readonly unknown[]\n\tstatus?: { type: string }\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tmetadata?: Record<string, any>\n}\n\n/**\n * Agent state and controls returned by useAgent\n */\nexport interface AgentState {\n\t// Thread state (from assistant-ui - single source of truth)\n\t/** All messages in the thread (includes both text and voice messages) */\n\tmessages: readonly AgentMessage[]\n\t/** Whether the agent is currently processing */\n\tisRunning: boolean\n\t/** Whether thread has any messages */\n\thasMessages: boolean\n\n\t// Actions (derived from thread messages - both text and voice)\n\t/** All actions derived from tool calls in the thread */\n\tactions: Action[]\n\t/** Currently running action (if any) */\n\tcurrentAction: Action | null\n\t/** Recently completed actions */\n\trecentActions: Action[]\n\t/** Last completed action (success or error) */\n\tlastCompletedAction: Action | null\n\n\t// Summary (derived from last assistant message)\n\t/** Summary text from the last assistant message */\n\tsummary: string | null\n\n\t// Voice mode (null if not configured)\n\tvoice: AgentVoice | null\n\n\t// MCP tools (null if not in MCP context)\n\ttools: AgentTools | null\n\n\t// Derived state\n\t/** Whether voice mode is currently active */\n\tisVoiceActive: boolean\n}\n\n/**\n * Main agent hook - provides unified access to all agent capabilities\n *\n * This is a thin facade over assistant-ui. All thread state comes from\n * the assistant-ui runtime, including voice messages (which are pushed\n * into the thread by VoiceThreadBridge).\n */\nexport function useAgent(): AgentState {\n\t// Thread state from assistant-ui (single source of truth)\n\tconst threadMessages = useThread((thread) => thread.messages)\n\tconst isRunning = useThread((thread) => thread.isRunning)\n\n\t// Actions derived from thread messages (includes both text and voice tool calls)\n\tconst actions = useActions()\n\tconst currentAction = useCurrentAction()\n\tconst recentActions = useRecentActions(3)\n\tconst lastCompletedAction = useLastCompletedAction()\n\n\t// Summary from last assistant message\n\tconst summary = useLatestSummary()\n\n\t// Voice controls from VoiceThreadBridge\n\tconst voiceThread = useOptionalVoiceThread()\n\n\t// MCP tools (optional - may not be in MCP context)\n\tconst mcpContext = useOptionalMCPTools()\n\n\t// Derived: is voice active\n\tconst isVoiceActive = !!(\n\t\tvoiceThread?.isActive ||\n\t\tvoiceThread?.isConnecting ||\n\t\tvoiceThread?.isError\n\t)\n\n\t// Has messages\n\tconst hasMessages = (threadMessages?.length ?? 0) > 0\n\n\t// Build voice interface\n\tconst voice: AgentVoice | null = useMemo(() => {\n\t\tif (!voiceThread) return null\n\n\t\treturn {\n\t\t\tisActive: voiceThread.isActive,\n\t\t\tisConnecting: voiceThread.isConnecting,\n\t\t\tisError: voiceThread.isError,\n\t\t\tisMuted: voiceThread.isMuted,\n\t\t\tisSupported: voiceThread.isSupported,\n\t\t\terror: voiceThread.error,\n\t\t\tsessionId: voiceThread.sessionId,\n\t\t\taudioLevel: voiceThread.audioLevel,\n\t\t\ttranscript: voiceThread.transcript,\n\t\t\tstart: voiceThread.start,\n\t\t\tstop: voiceThread.stop,\n\t\t\ttoggleMute: voiceThread.toggleMute,\n\t\t\tsendMessage: voiceThread.sendMessage,\n\t\t}\n\t}, [voiceThread])\n\n\t// Build tools interface\n\tconst tools: AgentTools | null = useMemo(() => {\n\t\tif (!mcpContext) return null\n\n\t\treturn {\n\t\t\tlist: mcpContext.tools,\n\t\t\tcall: mcpContext.callTool,\n\t\t\tprompts: mcpContext.prompts ?? [],\n\t\t\tgetPrompt: mcpContext.getPrompt,\n\t\t}\n\t}, [mcpContext])\n\n\t// Build the full agent state\n\treturn useMemo<AgentState>(\n\t\t() => ({\n\t\t\t// Thread (single source of truth)\n\t\t\tmessages: (threadMessages ?? []) as readonly AgentMessage[],\n\t\t\tisRunning,\n\t\t\thasMessages,\n\n\t\t\t// Actions (derived from thread)\n\t\t\tactions,\n\t\t\tcurrentAction,\n\t\t\trecentActions,\n\t\t\tlastCompletedAction,\n\n\t\t\t// Summary\n\t\t\tsummary,\n\n\t\t\t// Voice\n\t\t\tvoice,\n\n\t\t\t// Tools\n\t\t\ttools,\n\n\t\t\t// Derived\n\t\t\tisVoiceActive,\n\t\t}),\n\t\t[\n\t\t\tthreadMessages,\n\t\t\tisRunning,\n\t\t\thasMessages,\n\t\t\tactions,\n\t\t\tcurrentAction,\n\t\t\trecentActions,\n\t\t\tlastCompletedAction,\n\t\t\tsummary,\n\t\t\tvoice,\n\t\t\ttools,\n\t\t\tisVoiceActive,\n\t\t]\n\t)\n}\n","/**\n * AgentUIProvider\n *\n * Manages non-thread UI state that persists across thread switches.\n * This includes open/close status, pill mode, position, and unread indicators.\n *\n * Thread-level state (messages, tool calls, etc.) is managed by @assistant-ui/react.\n * This provider only handles UI-specific state that is independent of the current thread.\n *\n * @example Basic usage\n * ```tsx\n * import { AgentUIProvider, useAgentUI } from '@mcp-b/embedded-agent'\n *\n * function App() {\n * return (\n * <AgentUIProvider>\n * <MyComponent />\n * </AgentUIProvider>\n * )\n * }\n *\n * function MyComponent() {\n * const { isOpen, setOpen, userMode, setUserMode } = useAgentUI()\n * // ...\n * }\n * ```\n */\n\nimport { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react'\n\nimport type { FC, ReactNode } from 'react'\n\n/** UI mode for the pill widget */\nexport type PillMode = 'collapsed' | 'hovered' | 'composing' | 'active' | 'expanded'\n\n/** Position for draggable elements */\nexport interface Position {\n\tx: number\n\ty: number\n}\n\n/**\n * Agent UI state - non-thread state that persists across sessions\n */\nexport interface AgentUIState {\n\t/** Whether the agent UI is open (modal or expanded pill) */\n\tisOpen: boolean\n\n\t/** Current pill mode */\n\tuserMode: PillMode\n\n\t/** Drag position offset for the pill */\n\tposition: Position\n\n\t/** Whether there are unread messages */\n\thasUnread: boolean\n\n\t/** Whether voice mode is currently active */\n\tisVoiceActive: boolean\n\n\t/** Whether the pill is in full-screen mode */\n\tisFullScreen: boolean\n}\n\n/**\n * Agent UI context value with state and actions\n */\nexport interface AgentUIContextValue extends AgentUIState {\n\t/** Set the open state */\n\tsetOpen: (open: boolean) => void\n\n\t/** Toggle the open state */\n\ttoggleOpen: () => void\n\n\t/** Set the pill mode */\n\tsetUserMode: (mode: PillMode) => void\n\n\t/** Set the drag position */\n\tsetPosition: (position: Position) => void\n\n\t/** Reset position to default */\n\tresetPosition: () => void\n\n\t/** Mark messages as read */\n\tmarkRead: () => void\n\n\t/** Mark messages as unread */\n\tmarkUnread: () => void\n\n\t/** Set voice active state */\n\tsetVoiceActive: (active: boolean) => void\n\n\t/** Collapse the pill to its default state */\n\tcollapse: () => void\n\n\t/** Expand the pill to composing mode */\n\texpand: () => void\n\n\t/** Enter full-screen mode */\n\tenterFullScreen: () => void\n\n\t/** Exit full-screen mode */\n\texitFullScreen: () => void\n\n\t/** Toggle full-screen mode */\n\ttoggleFullScreen: () => void\n}\n\nconst AgentUIContext = createContext<AgentUIContextValue | null>(null)\n\nconst DEFAULT_POSITION: Position = { x: 0, y: 0 }\n\nexport interface AgentUIProviderProps {\n\tchildren: ReactNode\n\n\t/** Initial open state (default: false) */\n\tdefaultOpen?: boolean\n\n\t/** Initial pill mode (default: 'collapsed') */\n\tdefaultMode?: PillMode\n\n\t/** Callback when open state changes */\n\tonOpenChange?: (open: boolean) => void\n\n\t/** Callback when mode changes */\n\tonModeChange?: (mode: PillMode) => void\n}\n\n/**\n * Provider for non-thread UI state.\n *\n * This state persists across:\n * - Thread switches\n * - Modal open/close\n * - Component remounts\n */\nexport const AgentUIProvider: FC<AgentUIProviderProps> = ({\n\tchildren,\n\tdefaultOpen = false,\n\tdefaultMode = 'collapsed',\n\tonOpenChange,\n\tonModeChange,\n}) => {\n\t// Core UI state\n\tconst [isOpen, setIsOpenState] = useState(defaultOpen)\n\tconst [userMode, setUserModeState] = useState<PillMode>(defaultMode)\n\tconst [position, setPositionState] = useState<Position>(DEFAULT_POSITION)\n\tconst [hasUnread, setHasUnread] = useState(false)\n\tconst [isVoiceActive, setIsVoiceActiveState] = useState(false)\n\tconst [isFullScreen, setIsFullScreen] = useState(false)\n\n\t// Callback refs to avoid stale closures\n\tconst onOpenChangeRef = useRef(onOpenChange)\n\tconst onModeChangeRef = useRef(onModeChange)\n\tonOpenChangeRef.current = onOpenChange\n\tonModeChangeRef.current = onModeChange\n\n\t// Actions\n\tconst setOpen = useCallback((open: boolean) => {\n\t\tsetIsOpenState(open)\n\t\tonOpenChangeRef.current?.(open)\n\t}, [])\n\n\tconst toggleOpen = useCallback(() => {\n\t\tsetIsOpenState((prev) => {\n\t\t\tconst next = !prev\n\t\t\tonOpenChangeRef.current?.(next)\n\t\t\treturn next\n\t\t})\n\t}, [])\n\n\tconst setUserMode = useCallback((mode: PillMode) => {\n\t\tsetUserModeState(mode)\n\t\tonModeChangeRef.current?.(mode)\n\t}, [])\n\n\tconst setPosition = useCallback((pos: Position) => {\n\t\tsetPositionState(pos)\n\t}, [])\n\n\tconst resetPosition = useCallback(() => {\n\t\tsetPositionState(DEFAULT_POSITION)\n\t}, [])\n\n\tconst markRead = useCallback(() => {\n\t\tsetHasUnread(false)\n\t}, [])\n\n\tconst markUnread = useCallback(() => {\n\t\tsetHasUnread(true)\n\t}, [])\n\n\tconst setVoiceActive = useCallback((active: boolean) => {\n\t\tsetIsVoiceActiveState(active)\n\t}, [])\n\n\tconst collapse = useCallback(() => {\n\t\tsetUserModeState('collapsed')\n\t\tsetPositionState(DEFAULT_POSITION)\n\t\tsetIsFullScreen(false)\n\t\tonModeChangeRef.current?.('collapsed')\n\t}, [])\n\n\tconst expand = useCallback(() => {\n\t\tsetUserModeState('composing')\n\t\tonModeChangeRef.current?.('composing')\n\t}, [])\n\n\tconst enterFullScreen = useCallback(() => {\n\t\tsetIsFullScreen(true)\n\t}, [])\n\n\tconst exitFullScreen = useCallback(() => {\n\t\tsetIsFullScreen(false)\n\t}, [])\n\n\tconst toggleFullScreen = useCallback(() => {\n\t\tsetIsFullScreen((prev) => !prev)\n\t}, [])\n\n\t// Memoized context value\n\tconst value = useMemo<AgentUIContextValue>(\n\t\t() => ({\n\t\t\t// State\n\t\t\tisOpen,\n\t\t\tuserMode,\n\t\t\tposition,\n\t\t\thasUnread,\n\t\t\tisVoiceActive,\n\t\t\tisFullScreen,\n\n\t\t\t// Actions\n\t\t\tsetOpen,\n\t\t\ttoggleOpen,\n\t\t\tsetUserMode,\n\t\t\tsetPosition,\n\t\t\tresetPosition,\n\t\t\tmarkRead,\n\t\t\tmarkUnread,\n\t\t\tsetVoiceActive,\n\t\t\tcollapse,\n\t\t\texpand,\n\t\t\tenterFullScreen,\n\t\t\texitFullScreen,\n\t\t\ttoggleFullScreen,\n\t\t}),\n\t\t[\n\t\t\tisOpen,\n\t\t\tuserMode,\n\t\t\tposition,\n\t\t\thasUnread,\n\t\t\tisVoiceActive,\n\t\t\tisFullScreen,\n\t\t\tsetOpen,\n\t\t\ttoggleOpen,\n\t\t\tsetUserMode,\n\t\t\tsetPosition,\n\t\t\tresetPosition,\n\t\t\tmarkRead,\n\t\t\tmarkUnread,\n\t\t\tsetVoiceActive,\n\t\t\tcollapse,\n\t\t\texpand,\n\t\t\tenterFullScreen,\n\t\t\texitFullScreen,\n\t\t\ttoggleFullScreen,\n\t\t]\n\t)\n\n\treturn <AgentUIContext.Provider value={value}>{children}</AgentUIContext.Provider>\n}\n\n/**\n * Hook to access agent UI state and actions\n * @throws Error if used outside AgentUIProvider\n */\nexport function useAgentUI(): AgentUIContextValue {\n\tconst context = useContext(AgentUIContext)\n\tif (!context) {\n\t\tthrow new Error('useAgentUI must be used within an AgentUIProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access agent UI state (returns null if not in provider)\n */\nexport function useOptionalAgentUI(): AgentUIContextValue | null {\n\treturn useContext(AgentUIContext)\n}\n\n/**\n * Hook to get just the pill mode (for components that only need mode)\n */\nexport function usePillMode(): PillMode {\n\tconst { userMode } = useAgentUI()\n\treturn userMode\n}\n\n/**\n * Hook to check if agent has unread messages\n */\nexport function useHasUnread(): boolean {\n\tconst { hasUnread } = useAgentUI()\n\treturn hasUnread\n}\n","'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\n\nimport { KEYBOARD_VISIBILITY_THRESHOLD_PX } from '../lib/constants'\n\ninterface KeyboardState {\n\t/** Whether the soft keyboard is currently visible */\n\tisKeyboardVisible: boolean\n\t/** Height of the keyboard in pixels (0 if not visible) */\n\tkeyboardHeight: number\n\t/** Visible viewport height (excluding keyboard) */\n\tvisibleHeight: number\n}\n\n/**\n * Hook to detect and respond to soft keyboard visibility on mobile devices.\n *\n * Uses the Visual Viewport API for reliable keyboard detection.\n * Falls back gracefully on unsupported browsers.\n *\n * Usage:\n * ```tsx\n * const { isKeyboardVisible, keyboardHeight } = useKeyboardAware()\n * // Adjust UI based on keyboard state\n * ```\n */\nexport function useKeyboardAware(): KeyboardState {\n\tconst [state, setState] = useState<KeyboardState>({\n\t\tisKeyboardVisible: false,\n\t\tkeyboardHeight: 0,\n\t\tvisibleHeight: typeof window !== 'undefined' ? window.innerHeight : 0,\n\t})\n\n\tconst updateKeyboardState = useCallback(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst visualViewport = window.visualViewport\n\t\tif (!visualViewport) {\n\t\t\t// Fallback for browsers without Visual Viewport API\n\t\t\tsetState({\n\t\t\t\tisKeyboardVisible: false,\n\t\t\t\tkeyboardHeight: 0,\n\t\t\t\tvisibleHeight: window.innerHeight,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst windowHeight = window.innerHeight\n\t\tconst viewportHeight = visualViewport.height\n\n\t\t// Keyboard is likely visible if viewport is significantly smaller than window\n\t\tconst heightDiff = windowHeight - viewportHeight\n\t\tconst isKeyboardVisible = heightDiff > KEYBOARD_VISIBILITY_THRESHOLD_PX\n\n\t\tsetState({\n\t\t\tisKeyboardVisible,\n\t\t\tkeyboardHeight: isKeyboardVisible ? heightDiff : 0,\n\t\t\tvisibleHeight: viewportHeight,\n\t\t})\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst visualViewport = window.visualViewport\n\n\t\t// Initial update\n\t\tupdateKeyboardState()\n\n\t\tif (visualViewport) {\n\t\t\t// Visual Viewport API - most reliable\n\t\t\tvisualViewport.addEventListener('resize', updateKeyboardState)\n\t\t\tvisualViewport.addEventListener('scroll', updateKeyboardState)\n\n\t\t\treturn () => {\n\t\t\t\tvisualViewport.removeEventListener('resize', updateKeyboardState)\n\t\t\t\tvisualViewport.removeEventListener('scroll', updateKeyboardState)\n\t\t\t}\n\t\t} else {\n\t\t\t// Fallback: listen for window resize\n\t\t\twindow.addEventListener('resize', updateKeyboardState)\n\n\t\t\treturn () => {\n\t\t\t\twindow.removeEventListener('resize', updateKeyboardState)\n\t\t\t}\n\t\t}\n\t}, [updateKeyboardState])\n\n\treturn state\n}\n\n/**\n * Returns a CSS transform value to offset an element above the keyboard.\n * Use this with fixed-position elements that should stay visible when keyboard appears.\n *\n * @param keyboardHeight - Height of keyboard from useKeyboardAware\n * @param additionalOffset - Extra pixels to add above keyboard (default: 8)\n */\nexport function getKeyboardOffset(keyboardHeight: number, additionalOffset = 8): string {\n\tif (keyboardHeight <= 0) return 'translateY(0)'\n\treturn `translateY(-${keyboardHeight + additionalOffset}px)`\n}\n\nexport default useKeyboardAware\n","'use client'\n\nimport { useEffect, useState } from 'react'\n\n/**\n * Hook to detect if the current device is a mobile/touch device.\n * Uses media queries for reliable detection that works with SSR.\n *\n * Detection strategy:\n * 1. (hover: none) - Device has no hover capability (touch-only)\n * 2. (pointer: coarse) - Device uses imprecise pointer (finger vs mouse)\n *\n * Returns:\n * - isMobile: true if device is likely a mobile/touch device\n * - isTouchDevice: true if device supports touch input\n * - isCoarsePointer: true if primary input is coarse (finger)\n */\nexport function useMobileDetect() {\n\tconst [isMobile, setIsMobile] = useState(false)\n\tconst [isTouchDevice, setIsTouchDevice] = useState(false)\n\tconst [isCoarsePointer, setIsCoarsePointer] = useState(false)\n\n\tuseEffect(() => {\n\t\t// Check for touch capability\n\t\tconst hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0\n\n\t\t// Check media queries\n\t\tconst hoverNone = window.matchMedia('(hover: none)')\n\t\tconst pointerCoarse = window.matchMedia('(pointer: coarse)')\n\n\t\tconst updateState = () => {\n\t\t\tsetIsTouchDevice(hasTouch)\n\t\t\tsetIsCoarsePointer(pointerCoarse.matches)\n\t\t\t// Consider mobile if no hover OR coarse pointer\n\t\t\tsetIsMobile(hoverNone.matches || pointerCoarse.matches)\n\t\t}\n\n\t\tupdateState()\n\n\t\t// Listen for changes (e.g., connecting mouse to tablet)\n\t\tconst handleHoverChange = () => updateState()\n\t\tconst handlePointerChange = () => updateState()\n\n\t\thoverNone.addEventListener('change', handleHoverChange)\n\t\tpointerCoarse.addEventListener('change', handlePointerChange)\n\n\t\treturn () => {\n\t\t\thoverNone.removeEventListener('change', handleHoverChange)\n\t\t\tpointerCoarse.removeEventListener('change', handlePointerChange)\n\t\t}\n\t}, [])\n\n\treturn { isMobile, isTouchDevice, isCoarsePointer }\n}\n\n/**\n * Static check for mobile - useful for SSR fallback\n * Returns true on server/initial render to be safe\n */\nexport function checkIsMobileSSR(): boolean {\n\tif (typeof window === 'undefined') return false\n\treturn (\n\t\twindow.matchMedia('(hover: none)').matches || window.matchMedia('(pointer: coarse)').matches\n\t)\n}\n\nexport default useMobileDetect\n","/**\n * usePendingToolCalls Hook\n *\n * Derives pending tool call state from assistant-ui's thread state.\n * This replaces the external pendingApprovalStore by using the single source of truth.\n *\n * Benefits:\n * - No external store synchronization needed\n * - No registration/unregistration logic\n * - No infinite loop issues from useSyncExternalStore\n * - Naturally reactive to thread state changes\n *\n * For non-reactive utilities (callbacks/effects), see lib/thread-utils.ts\n */\nimport { useThread, useThreadRuntime } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport type { ThreadAssistantMessage } from '@assistant-ui/react'\n// Import the type for internal use\nimport type { PendingToolCallInfo } from '../lib/thread-utils'\n\n// Re-export the shared type for backwards compatibility\nexport type { PendingToolCallInfo as PendingToolCall } from '../lib/thread-utils'\n\n/**\n * Hook to get all pending tool calls that require user approval.\n * Derives state from assistant-ui's thread messages.\n *\n * This is a reactive hook - it will re-render when thread state changes.\n * For non-reactive access in callbacks, use getPendingToolCalls() from lib/thread-utils.ts\n */\nexport function usePendingToolCalls(): PendingToolCallInfo[] {\n\tconst messages = useThread((t) => t.messages)\n\n\treturn useMemo(() => {\n\t\tconst result: PendingToolCallInfo[] = []\n\n\t\tfor (const msg of messages) {\n\t\t\t// Only assistant messages can have tool calls\n\t\t\tif (msg.role !== 'assistant') continue\n\n\t\t\t// Cast to assistant message to access status\n\t\t\tconst assistantMsg = msg as ThreadAssistantMessage\n\n\t\t\t// Only process messages waiting for tool results\n\t\t\t// Check for requires-action status (don't check reason - it may vary)\n\t\t\tif (assistantMsg.status?.type !== 'requires-action') continue\n\n\t\t\t// Find tool-call parts without results\n\t\t\tfor (const part of assistantMsg.content) {\n\t\t\t\tif (part.type !== 'tool-call') continue\n\t\t\t\tif (part.result !== undefined) continue\n\n\t\t\t\tresult.push({\n\t\t\t\t\tmessageId: msg.id,\n\t\t\t\t\ttoolCallId: part.toolCallId,\n\t\t\t\t\ttoolName: part.toolName,\n\t\t\t\t\targs: (part.args as Record<string, unknown>) ?? {},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}, [messages])\n}\n\n/**\n * Hook to check if there are any pending tool calls.\n * Optimized for conditional rendering - returns boolean instead of array.\n */\nexport function useHasPendingToolCalls(): boolean {\n\tconst messages = useThread((t) => t.messages)\n\n\treturn useMemo(() => {\n\t\tfor (const msg of messages) {\n\t\t\tif (msg.role !== 'assistant') continue\n\n\t\t\tconst assistantMsg = msg as ThreadAssistantMessage\n\n\t\t\t// Check for requires-action status (don't check reason - it may vary)\n\t\t\tif (assistantMsg.status?.type !== 'requires-action') continue\n\n\t\t\tfor (const part of assistantMsg.content) {\n\t\t\t\tif (part.type === 'tool-call' && part.result === undefined) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t}, [messages])\n}\n\n/**\n * Hook to get the thread runtime for calling addToolResult.\n * Re-exported for convenience.\n */\nexport { useThreadRuntime }\n","'use client'\n\nimport { useCallback, useRef } from 'react'\n\nimport { PINCH_GESTURE_CONFIG } from '../lib/constants'\n\nimport type { TouchEvent as ReactTouchEvent } from 'react'\n\ninterface PinchGestureOptions {\n\t/** Callback when pinch-out (expand) gesture detected */\n\tonPinchOut?: () => void\n\t/** Callback when pinch-in (collapse) gesture detected */\n\tonPinchIn?: () => void\n\t/** Whether gesture detection is enabled */\n\tenabled?: boolean\n\t/** Minimum scale change to trigger (default from PINCH_GESTURE_CONFIG) */\n\tthreshold?: number\n}\n\ninterface PinchState {\n\tinitialDistance: number | null\n\tlastDistance: number | null\n\tisActive: boolean\n}\n\n/** Minimal touch point interface for distance calculation */\ninterface TouchPoint {\n\tclientX: number\n\tclientY: number\n}\n\n/**\n * Calculate distance between two touch points\n */\nfunction getTouchDistance(touch1: TouchPoint, touch2: TouchPoint): number {\n\tconst dx = touch2.clientX - touch1.clientX\n\tconst dy = touch2.clientY - touch1.clientY\n\treturn Math.sqrt(dx * dx + dy * dy)\n}\n\n/**\n * Hook for detecting two-finger pinch gestures.\n *\n * Implements pinch-to-expand (out) and pinch-to-collapse (in) detection\n * using native Touch Events for maximum compatibility.\n *\n * @example\n * ```tsx\n * const { handlers } = usePinchGesture({\n * onPinchOut: () => enterFullScreen(),\n * onPinchIn: () => exitFullScreen(),\n * enabled: isMobile && isExpanded,\n * })\n *\n * return <div {...handlers}>Content</div>\n * ```\n */\nexport function usePinchGesture({\n\tonPinchOut,\n\tonPinchIn,\n\tenabled = true,\n\tthreshold = PINCH_GESTURE_CONFIG.threshold,\n}: PinchGestureOptions) {\n\tconst stateRef = useRef<PinchState>({\n\t\tinitialDistance: null,\n\t\tlastDistance: null,\n\t\tisActive: false,\n\t})\n\n\tconst handleTouchStart = useCallback(\n\t\t(e: ReactTouchEvent) => {\n\t\t\tif (!enabled) return\n\t\t\tif (e.touches.length === 2) {\n\t\t\t\tconst distance = getTouchDistance(e.touches[0], e.touches[1])\n\n\t\t\t\t// Only start tracking if fingers are far enough apart\n\t\t\t\tif (distance >= PINCH_GESTURE_CONFIG.minInitialDistance) {\n\t\t\t\t\tstateRef.current = {\n\t\t\t\t\t\tinitialDistance: distance,\n\t\t\t\t\t\tlastDistance: distance,\n\t\t\t\t\t\tisActive: true,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[enabled]\n\t)\n\n\tconst handleTouchMove = useCallback(\n\t\t(e: ReactTouchEvent) => {\n\t\t\tif (!enabled || !stateRef.current.isActive) return\n\t\t\tif (e.touches.length !== 2) return\n\n\t\t\t// Track the latest distance during the gesture\n\t\t\tconst currentDistance = getTouchDistance(e.touches[0], e.touches[1])\n\t\t\tstateRef.current.lastDistance = currentDistance\n\t\t},\n\t\t[enabled]\n\t)\n\n\tconst handleTouchEnd = useCallback(\n\t\t(e: ReactTouchEvent) => {\n\t\t\tif (!enabled || !stateRef.current.isActive) return\n\n\t\t\tconst { initialDistance, lastDistance } = stateRef.current\n\n\t\t\t// When gesture ends, evaluate if it was a pinch\n\t\t\tif (e.touches.length < 2 && initialDistance !== null && lastDistance !== null) {\n\t\t\t\tconst scaleDelta = (lastDistance - initialDistance) / initialDistance\n\n\t\t\t\tif (scaleDelta > threshold) {\n\t\t\t\t\tonPinchOut?.()\n\t\t\t\t} else if (scaleDelta < -threshold) {\n\t\t\t\t\tonPinchIn?.()\n\t\t\t\t}\n\n\t\t\t\t// Reset state\n\t\t\t\tstateRef.current = {\n\t\t\t\t\tinitialDistance: null,\n\t\t\t\t\tlastDistance: null,\n\t\t\t\t\tisActive: false,\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[enabled, threshold, onPinchOut, onPinchIn]\n\t)\n\n\treturn {\n\t\thandlers: {\n\t\t\tonTouchStart: handleTouchStart,\n\t\t\tonTouchMove: handleTouchMove,\n\t\t\tonTouchEnd: handleTouchEnd,\n\t\t},\n\t}\n}\n\nexport default usePinchGesture\n","/**\n * ActivityIndicator Component\n *\n * Shows what the agent is currently doing based on thread state.\n * Displays in the composer area when the agent is running.\n *\n * Activity states:\n * - \"Thinking...\" - Agent is processing, no tools called yet\n * - \"Running {toolName}...\" - Single tool is executing\n * - \"Running {n} tools...\" - Multiple tools executing in parallel\n * - Shows streaming text preview when available\n */\n'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport {\n\tCamera,\n\tFileText,\n\tLoader2,\n\tMousePointer,\n\tNavigation,\n\tPenLine,\n\tSearch,\n\tTrash2,\n\tWrench,\n} from 'lucide-react'\nimport { useMemo } from 'react'\n\nimport { humanizeToolName } from '../../lib/format'\nimport { cn } from '../../lib/utils'\n\nimport type { LucideIcon } from 'lucide-react'\nimport type { FC } from 'react'\n\n// ============================================================================\n// Tool Icon Mapping\n// ============================================================================\n\n/**\n * Get an appropriate icon for a tool based on its name.\n * Uses pattern matching to categorize tools.\n */\nexport function getToolIcon(toolName: string): LucideIcon {\n\tconst name = toolName.toLowerCase()\n\n\t// Search/find operations\n\tif (\n\t\tname.includes('search') ||\n\t\tname.includes('find') ||\n\t\tname.includes('grep') ||\n\t\tname.includes('glob')\n\t) {\n\t\treturn Search\n\t}\n\n\t// Read/get operations\n\tif (\n\t\tname.includes('read') ||\n\t\tname.includes('get') ||\n\t\tname.includes('fetch') ||\n\t\tname.includes('list')\n\t) {\n\t\treturn FileText\n\t}\n\n\t// Write/create operations\n\tif (\n\t\tname.includes('write') ||\n\t\tname.includes('create') ||\n\t\tname.includes('add') ||\n\t\tname.includes('insert')\n\t) {\n\t\treturn PenLine\n\t}\n\n\t// Delete/remove operations\n\tif (name.includes('delete') || name.includes('remove') || name.includes('clear')) {\n\t\treturn Trash2\n\t}\n\n\t// Navigation operations\n\tif (name.includes('navigate') || name.includes('goto') || name.includes('open')) {\n\t\treturn Navigation\n\t}\n\n\t// UI interaction operations\n\tif (\n\t\tname.includes('click') ||\n\t\tname.includes('fill') ||\n\t\tname.includes('type') ||\n\t\tname.includes('hover')\n\t) {\n\t\treturn MousePointer\n\t}\n\n\t// Screenshot/snapshot operations\n\tif (name.includes('screenshot') || name.includes('snapshot') || name.includes('capture')) {\n\t\treturn Camera\n\t}\n\n\t// Default\n\treturn Wrench\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface ActivityState {\n\ttype: 'idle' | 'thinking' | 'tool' | 'parallel_tools' | 'streaming'\n\tlabel: string\n\ticon: LucideIcon\n\ttoolNames?: string[]\n\tstreamingText?: string\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to derive current activity state from the thread.\n */\nexport function useActivityState(): ActivityState | null {\n\tconst messages = useThread((thread) => thread.messages)\n\tconst isRunning = useThread((thread) => thread.isRunning)\n\n\treturn useMemo(() => {\n\t\tif (!isRunning) return null\n\n\t\t// Find the last assistant message\n\t\tconst lastAssistantMessage = messages\n\t\t\t? [...messages].reverse().find((m) => m.role === 'assistant')\n\t\t\t: null\n\n\t\tif (!lastAssistantMessage) {\n\t\t\t// No assistant message yet - thinking\n\t\t\treturn {\n\t\t\t\ttype: 'thinking',\n\t\t\t\tlabel: 'Thinking...',\n\t\t\t\ticon: Loader2,\n\t\t\t}\n\t\t}\n\n\t\t// Get running tool calls from the message\n\t\tconst runningToolNames: string[] = []\n\t\tlet lastText: string | undefined\n\n\t\tfor (const part of lastAssistantMessage.content) {\n\t\t\tif (part.type === 'tool-call') {\n\t\t\t\t// Check if this tool call is running (no status means running, or status.type === 'running')\n\t\t\t\tconst toolPart = part as { toolName: string; status?: { type: string } }\n\t\t\t\tif (!toolPart.status || toolPart.status.type === 'running') {\n\t\t\t\t\trunningToolNames.push(toolPart.toolName)\n\t\t\t\t}\n\t\t\t} else if (part.type === 'text') {\n\t\t\t\tconst textPart = part as { text: string }\n\t\t\t\tlastText = textPart.text\n\t\t\t}\n\t\t}\n\n\t\t// Determine activity state\n\t\tif (runningToolNames.length === 0) {\n\t\t\t// No running tools\n\t\t\tif (lastText && lastText.length > 0) {\n\t\t\t\t// Has text content - streaming response\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'streaming',\n\t\t\t\t\tlabel: 'Writing response...',\n\t\t\t\t\ticon: PenLine,\n\t\t\t\t\tstreamingText: lastText,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// No text either - still thinking\n\t\t\treturn {\n\t\t\t\ttype: 'thinking',\n\t\t\t\tlabel: 'Thinking...',\n\t\t\t\ticon: Loader2,\n\t\t\t}\n\t\t}\n\n\t\tif (runningToolNames.length === 1) {\n\t\t\t// Single tool running\n\t\t\tconst toolName = runningToolNames[0]\n\t\t\treturn {\n\t\t\t\ttype: 'tool',\n\t\t\t\tlabel: humanizeToolName(toolName, true),\n\t\t\t\ticon: getToolIcon(toolName),\n\t\t\t\ttoolNames: [toolName],\n\t\t\t}\n\t\t}\n\n\t\t// Multiple tools running in parallel\n\t\treturn {\n\t\t\ttype: 'parallel_tools',\n\t\t\tlabel: `Running ${runningToolNames.length} tools...`,\n\t\t\ticon: Loader2,\n\t\t\ttoolNames: runningToolNames,\n\t\t}\n\t}, [messages, isRunning])\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface ActivityIndicatorProps {\n\tclassName?: string\n}\n\n/**\n * Displays the current agent activity.\n * Shows in the composer area when the agent is running.\n */\nexport const ActivityIndicator: FC<ActivityIndicatorProps> = ({ className }) => {\n\tconst activity = useActivityState()\n\n\tif (!activity) return null\n\n\tconst Icon = activity.icon\n\tconst isSpinning = activity.type === 'thinking' || activity.type === 'parallel_tools'\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center gap-2 px-3 py-2',\n\t\t\t\t'rounded-lg bg-blue-500/10 border border-blue-500/20',\n\t\t\t\t'text-sm text-blue-400',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<Icon className={cn('h-4 w-4 flex-shrink-0', isSpinning && 'animate-spin')} />\n\t\t\t<span className=\"truncate\">{activity.label}</span>\n\n\t\t\t{/* Show parallel tool names on hover/expand */}\n\t\t\t{activity.type === 'parallel_tools' && activity.toolNames && (\n\t\t\t\t<div className=\"hidden sm:flex items-center gap-1 ml-1\">\n\t\t\t\t\t{activity.toolNames.slice(0, 3).map((name, i) => {\n\t\t\t\t\t\tconst ToolIcon = getToolIcon(name)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<span key={i} title={humanizeToolName(name, true)}>\n\t\t\t\t\t\t\t\t<ToolIcon className=\"h-3 w-3 text-blue-400/60\" />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t\t{activity.toolNames.length > 3 && (\n\t\t\t\t\t\t<span className=\"text-xs text-blue-400/60\">+{activity.toolNames.length - 3}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\nexport default ActivityIndicator\n","/**\n * Approval Mode Toggle\n *\n * A compact toggle for switching between 'auto' and 'ask' modes\n * for destructive tool approval. Shows in the pill header.\n */\nimport { Shield, ShieldOff } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { useOptionalToolApproval } from '../../providers/ToolApprovalProvider'\n\nimport type { FC } from 'react'\n\nexport interface ApprovalModeToggleProps {\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Compact toggle button for approval mode.\n * Shows a shield icon that indicates current mode.\n */\nexport const ApprovalModeToggle: FC<ApprovalModeToggleProps> = ({ className }) => {\n\tconst toolApproval = useOptionalToolApproval()\n\n\t// Don't render if no approval context\n\tif (!toolApproval) return null\n\n\tconst { mode, toggleMode } = toolApproval\n\tconst isAskMode = mode === 'ask'\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={toggleMode}\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center gap-1 rounded-md px-1.5 py-1',\n\t\t\t\t'text-[10px] font-medium uppercase tracking-wide',\n\t\t\t\t'transition-colors duration-150',\n\t\t\t\tisAskMode\n\t\t\t\t\t? 'bg-amber-500/20 text-amber-400 hover:bg-amber-500/30'\n\t\t\t\t\t: 'bg-zinc-700/50 text-white/40 hover:bg-zinc-700 hover:text-white/60',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\ttitle={\n\t\t\t\tisAskMode ? 'Ask before action (click to auto-approve)' : 'Auto-approve (click to ask)'\n\t\t\t}\n\t\t>\n\t\t\t{isAskMode ? (\n\t\t\t\t<>\n\t\t\t\t\t<Shield className=\"h-3 w-3\" />\n\t\t\t\t\t<span>Ask</span>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<ShieldOff className=\"h-3 w-3\" />\n\t\t\t\t\t<span>Auto</span>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</button>\n\t)\n}\n\n/**\n * Inline approval mode indicator for the pill header.\n * Shows current mode with ability to toggle.\n */\nexport const ApprovalModeIndicator: FC<ApprovalModeToggleProps> = ({ className }) => {\n\tconst toolApproval = useOptionalToolApproval()\n\n\t// Don't render if no approval context\n\tif (!toolApproval) return null\n\n\tconst { mode, toggleMode } = toolApproval\n\tconst isAskMode = mode === 'ask'\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={toggleMode}\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center justify-center rounded-full p-1',\n\t\t\t\t'transition-colors duration-150',\n\t\t\t\tisAskMode\n\t\t\t\t\t? 'text-amber-500 hover:bg-amber-500/20'\n\t\t\t\t\t: 'text-white/30 hover:bg-white/10 hover:text-white/50',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\ttitle={\n\t\t\t\tisAskMode\n\t\t\t\t\t? 'Ask before destructive actions (click to auto-approve)'\n\t\t\t\t\t: 'Auto-approve all actions (click to ask first)'\n\t\t\t}\n\t\t>\n\t\t\t{isAskMode ? <Shield className=\"h-3.5 w-3.5\" /> : <ShieldOff className=\"h-3.5 w-3.5\" />}\n\t\t</button>\n\t)\n}\n\nexport default ApprovalModeToggle\n","'use client'\n\nimport { AlertCircle, CheckCircle2, Circle, Loader2 } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nimport type { FC } from 'react'\nimport type { Action } from '../../hooks/useActions'\n\ninterface CurrentActivityProps {\n\tcurrentAction: Action | null\n\trecentActions?: Action[]\n\tshowRecent?: boolean\n\tclassName?: string\n}\n\n/**\n * Displays the current action the agent is performing,\n * with optional recent completed steps shown below.\n */\nexport const CurrentActivity: FC<CurrentActivityProps> = ({\n\tcurrentAction,\n\trecentActions = [],\n\tshowRecent = true,\n\tclassName,\n}) => {\n\treturn (\n\t\t<div className={cn('space-y-2', className)}>\n\t\t\t{/* Current action - prominent display */}\n\t\t\t{currentAction ? (\n\t\t\t\t<div className=\"flex items-center gap-2.5\">\n\t\t\t\t\t<ActionStatusIcon status={currentAction.status} />\n\t\t\t\t\t<span className=\"text-sm font-medium text-white\">{currentAction.label}...</span>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t/* Thinking indicator - when running but no specific action yet */\n\t\t\t\t<div className=\"flex items-center gap-2.5\">\n\t\t\t\t\t<Loader2 className=\"h-4 w-4 text-blue-400 animate-spin\" />\n\t\t\t\t\t<span className=\"text-sm font-medium text-white/80\">Thinking...</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Recent completed actions - muted, smaller */}\n\t\t\t{showRecent && recentActions.length > 0 && (\n\t\t\t\t<div className=\"ml-1 border-l border-white/20 pl-3 space-y-1\">\n\t\t\t\t\t{recentActions.map((action) => (\n\t\t\t\t\t\t<div key={action.id} className=\"flex items-center gap-2 text-xs text-white/60\">\n\t\t\t\t\t\t\t<ActionStatusIcon status={action.status} size=\"sm\" />\n\t\t\t\t\t\t\t<span className={cn(action.status === 'error' && 'text-red-400')}>\n\t\t\t\t\t\t\t\t{action.label}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\ninterface ActionStatusIconProps {\n\tstatus: Action['status']\n\tsize?: 'sm' | 'md'\n\tclassName?: string\n}\n\n/**\n * Icon component for action status\n */\nexport const ActionStatusIcon: FC<ActionStatusIconProps> = ({ status, size = 'md', className }) => {\n\tconst sizeClass = size === 'sm' ? 'h-3 w-3' : 'h-4 w-4'\n\n\tswitch (status) {\n\t\tcase 'running':\n\t\t\treturn <Loader2 className={cn(sizeClass, 'text-blue-400 animate-spin', className)} />\n\t\tcase 'pending':\n\t\t\treturn <Circle className={cn(sizeClass, 'text-amber-400', className)} />\n\t\tcase 'success':\n\t\t\treturn <CheckCircle2 className={cn(sizeClass, 'text-green-400', className)} />\n\t\tcase 'error':\n\t\t\treturn <AlertCircle className={cn(sizeClass, 'text-red-400', className)} />\n\t\tdefault:\n\t\t\treturn <Circle className={cn(sizeClass, 'text-white/40', className)} />\n\t}\n}\n\n/**\n * Idle state indicator when no actions are running\n */\nexport const IdleIndicator: FC<{ className?: string }> = ({ className }) => {\n\treturn (\n\t\t<div className={cn('flex items-center gap-2 text-white/50', className)}>\n\t\t\t<div className=\"h-2 w-2 rounded-full bg-green-400/60\" />\n\t\t\t<span className=\"text-xs\">Ready</span>\n\t\t</div>\n\t)\n}\n","/**\n * MCP Tool Registry Component\n *\n * Registers all MCP tools with the assistant-ui runtime.\n * Uses the unified callTool function which auto-routes based on tool source.\n *\n * Supports destructive tool approval when ToolApprovalProvider is present:\n * - Tools with destructiveHint: true require user confirmation before execution\n * - Approval mode can be 'ask' (require confirmation) or 'auto' (execute immediately)\n * - Approval UI is handled by UnifiedToolFallback using the HITL pattern\n *\n * Tool execution captures metadata (timing, source info) and stores it in the\n * assistant-ui thread via ToolResponse artifacts. This enables:\n * - Performance monitoring (duration tracking)\n * - Source attribution (which MCP server handled the call)\n * - Error tracking (including abort status)\n *\n * Usage:\n * <MCPToolRegistry />\n *\n * This component should be placed inside both MCPToolsProvider and AssistantRuntimeProvider.\n */\nimport { useAssistantTool } from '@assistant-ui/react'\nimport { ToolResponse } from 'assistant-stream'\n\nimport { useMCPTools } from '../providers/MCPToolsProvider'\nimport { useOptionalToolApproval } from '../providers/ToolApprovalProvider'\n\nimport type { CallToolResult, ToolCallMetadata, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { ReadonlyJSONValue } from 'assistant-stream/utils'\nimport type { FC } from 'react'\n\n// ============================================================================\n// Tool Result Formatting\n// ============================================================================\n\n/**\n * Format tool result content for the assistant\n */\nexport function formatToolResult(result: CallToolResult): string {\n\tconst textContent = result.content\n\t\t.map((c: { type: string; text?: string }) => {\n\t\t\tif ('text' in c && typeof c.text === 'string') {\n\t\t\t\treturn c.text\n\t\t\t}\n\t\t\treturn JSON.stringify(c)\n\t\t})\n\t\t.join('\\n')\n\n\treturn textContent || 'Tool executed successfully'\n}\n\n// ============================================================================\n// Tool Bridge Components\n// ============================================================================\n\n/**\n * Bridge component that registers a single tool with assistant-ui.\n * Executes the tool immediately via MCP.\n * Captures execution metadata (timing, source) and stores in thread artifacts.\n */\nconst ToolBridge: FC<{\n\ttool: ToolWithSource\n\tcallTool: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>\n}> = ({ tool, callTool }) => {\n\tuseAssistantTool({\n\t\ttoolName: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tparameters: (tool.inputSchema ?? {}) as Record<string, unknown>,\n\t\texecute: async (args) => {\n\t\t\tconst startedAt = Date.now()\n\t\t\tlet isError = false\n\t\t\tlet wasAborted = false\n\n\t\t\ttry {\n\t\t\t\tconst result = await callTool(tool.name, args)\n\n\t\t\t\t// Check if the result indicates an error\n\t\t\t\tisError = result.isError === true\n\n\t\t\t\t// Check if the call was aborted (tool removed during execution)\n\t\t\t\twasAborted = result.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\tc.type === 'text' && typeof c.text === 'string' && c.text.includes('Tool call aborted')\n\t\t\t\t)\n\n\t\t\t\t// Build metadata artifact for thread persistence\n\t\t\t\tconst metadata = {\n\t\t\t\t\tstartedAt,\n\t\t\t\t\tduration: Date.now() - startedAt,\n\t\t\t\t\tsourceId: tool._sourceId,\n\t\t\t\t\tisError,\n\t\t\t\t\twasAborted,\n\t\t\t\t} satisfies ToolCallMetadata\n\n\t\t\t\t// Return ToolResponse with artifact for thread storage\n\t\t\t\treturn new ToolResponse({\n\t\t\t\t\tresult: formatToolResult(result),\n\t\t\t\t\tartifact: metadata as unknown as ReadonlyJSONValue,\n\t\t\t\t\tisError,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[ToolBridge] Tool '${tool.name}' execution failed:`, error)\n\n\t\t\t\t// Still capture metadata for failed calls\n\t\t\t\tconst metadata = {\n\t\t\t\t\tstartedAt,\n\t\t\t\t\tduration: Date.now() - startedAt,\n\t\t\t\t\tsourceId: tool._sourceId,\n\t\t\t\t\tisError: true,\n\t\t\t\t\twasAborted: false,\n\t\t\t\t} satisfies ToolCallMetadata\n\n\t\t\t\t// Return error as ToolResponse with metadata\n\t\t\t\treturn new ToolResponse({\n\t\t\t\t\tresult: `Error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tartifact: metadata as unknown as ReadonlyJSONValue,\n\t\t\t\t\tisError: true,\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t})\n\n\treturn null\n}\n\n/**\n * Bridge component for destructive tools that require approval.\n *\n * IMPORTANT: No execute function is provided!\n * This makes assistant-ui wait for the fallback to call addResult().\n * The model pauses until the user approves/denies via the fallback UI.\n */\nconst DestructiveToolBridge: FC<{\n\ttool: ToolWithSource\n}> = ({ tool }) => {\n\t// Register tool WITHOUT execute - this is key for HITL!\n\t// The fallback component handles execution via addResult()\n\tuseAssistantTool({\n\t\ttoolName: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tparameters: (tool.inputSchema ?? {}) as Record<string, unknown>,\n\t\t// No execute function = model waits for addResult()\n\t})\n\n\treturn null\n}\n\n// ============================================================================\n// Main Registry Component\n// ============================================================================\n\n/**\n * Tool registry that registers all MCP tools with assistant-ui.\n * Routes tool calls automatically based on _sourceId.\n * Uses DestructiveToolBridge for tools that require approval.\n */\nexport const MCPToolRegistry: FC = () => {\n\tconst { tools, callTool } = useMCPTools()\n\tconst toolApproval = useOptionalToolApproval()\n\n\treturn (\n\t\t<>\n\t\t\t{tools.map((tool) => {\n\t\t\t\t// Check if this tool requires approval\n\t\t\t\tconst needsApproval = toolApproval?.requiresApproval(tool) ?? false\n\n\t\t\t\tif (needsApproval) {\n\t\t\t\t\treturn <DestructiveToolBridge key={`${tool._sourceId}-${tool.name}`} tool={tool} />\n\t\t\t\t}\n\n\t\t\t\treturn <ToolBridge key={`${tool._sourceId}-${tool.name}`} tool={tool} callTool={callTool} />\n\t\t\t})}\n\t\t</>\n\t)\n}\n","/**\n * ElicitationButtonBar Component\n *\n * Renders an approval card above the composer when a tool requires approval.\n * Shows the tool name, description, and input arguments so users know\n * exactly what they're approving.\n *\n * - Accept: Executes the tool and returns the result\n * - Deny: Stops the thread entirely (user doesn't want to continue)\n */\n'use client'\n\nimport { useThreadRuntime } from '@assistant-ui/react'\nimport { AlertTriangle, Check, Loader2, X } from 'lucide-react'\nimport { useState } from 'react'\n\nimport { usePendingToolCalls } from '../../hooks/usePendingToolCalls'\nimport { formatArgs, humanizeToolName, TOOL_DENIED_MESSAGE } from '../../lib/format'\nimport { resolveAllPendingToolCalls } from '../../lib/thread-utils'\nimport { cn } from '../../lib/utils'\nimport { useMCPTools } from '../../providers/MCPToolsProvider'\nimport { formatToolResult } from '../MCPToolRegistry'\n\nimport type { FC } from 'react'\n\nexport interface ElicitationButtonBarProps {\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Approval card for tool execution that sits above the composer.\n * Shows tool name, description, and arguments when a tool requires approval.\n *\n * Returns null if there are no pending approvals.\n */\nexport const ElicitationButtonBar: FC<ElicitationButtonBarProps> = ({ className }) => {\n\tconst [isExecuting, setIsExecuting] = useState(false)\n\tconst pendingToolCalls = usePendingToolCalls()\n\tconst threadRuntime = useThreadRuntime()\n\tconst { callTool, tools } = useMCPTools()\n\n\t// Don't render if no pending approvals\n\tif (pendingToolCalls.length === 0) {\n\t\treturn null\n\t}\n\n\t// Get the first pending tool call\n\tconst firstTool = pendingToolCalls[0]\n\n\t// Get tool metadata\n\tconst humanizedName = humanizeToolName(firstTool.toolName)\n\tconst toolDescription = tools.find((t) => t.name === firstTool.toolName)?.description\n\tconst hasArgs = Object.keys(firstTool.args).length > 0\n\tconst formattedArgs = hasArgs ? formatArgs(firstTool.args) : null\n\n\t// Get the message part runtime for this tool call\n\tconst getPartRuntime = () => {\n\t\tconst messageRuntime = threadRuntime?.getMessageById(firstTool.messageId)\n\t\treturn messageRuntime?.getMessagePartByToolCallId(firstTool.toolCallId)\n\t}\n\n\tconst handleAccept = async () => {\n\t\tsetIsExecuting(true)\n\t\ttry {\n\t\t\tconst toolResult = await callTool(firstTool.toolName, firstTool.args)\n\t\t\tconst partRuntime = getPartRuntime()\n\t\t\tpartRuntime?.addToolResult(formatToolResult(toolResult))\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\t\t\tconst partRuntime = getPartRuntime()\n\t\t\tpartRuntime?.addToolResult(`Error: ${errorMessage}`)\n\t\t} finally {\n\t\t\tsetIsExecuting(false)\n\t\t}\n\t}\n\n\tconst handleDeny = () => {\n\t\t// Resolve all pending tool calls with denial message to prevent stuck state\n\t\tresolveAllPendingToolCalls(threadRuntime, TOOL_DENIED_MESSAGE)\n\t\t// Stop the thread entirely - user doesn't want to continue\n\t\tthreadRuntime.cancelRun()\n\t}\n\n\t// Show loading state while executing\n\tif (isExecuting) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn('rounded-xl border border-blue-500/30 bg-blue-500/10 px-3 py-2.5', className)}\n\t\t\t>\n\t\t\t\t<div className=\"flex items-center justify-center gap-2\">\n\t\t\t\t\t<Loader2 className=\"h-4 w-4 animate-spin text-blue-400\" />\n\t\t\t\t\t<span className=\"text-sm text-white/80\">\n\t\t\t\t\t\tExecuting <span className=\"font-medium text-blue-400\">{humanizedName}</span>\n\t\t\t\t\t\t...\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('rounded-xl border border-amber-500/30 bg-amber-500/10 px-3 py-2.5', className)}\n\t\t>\n\t\t\t{/* Header: Warning icon + tool name */}\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<AlertTriangle className=\"h-4 w-4 shrink-0 text-amber-500\" />\n\t\t\t\t<span className=\"text-sm text-white/90\">\n\t\t\t\t\tApprove <span className=\"font-medium text-amber-400\">{humanizedName}</span>?\n\t\t\t\t</span>\n\t\t\t</div>\n\n\t\t\t{/* Tool description (if available) */}\n\t\t\t{toolDescription && (\n\t\t\t\t<p className=\"mt-1.5 pl-6 text-xs leading-relaxed text-white/50\">{toolDescription}</p>\n\t\t\t)}\n\n\t\t\t{/* Arguments preview */}\n\t\t\t{formattedArgs && (\n\t\t\t\t<pre className=\"mt-2 max-h-24 overflow-auto whitespace-pre-wrap rounded-lg bg-white/5 p-2 font-mono text-[11px] leading-relaxed text-white/60\">\n\t\t\t\t\t{formattedArgs}\n\t\t\t\t</pre>\n\t\t\t)}\n\n\t\t\t{/* Accept/Deny buttons */}\n\t\t\t<div className=\"mt-2.5 flex items-center gap-2\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleDeny}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t'border border-white/20 text-white/70',\n\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t'hover:border-red-500/50 hover:bg-red-500/10 hover:text-red-400',\n\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<X className=\"h-3.5 w-3.5\" />\n\t\t\t\t\tDeny\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleAccept}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t'border border-amber-500/50 bg-amber-500/20 text-amber-400',\n\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t'hover:border-amber-500 hover:bg-amber-500/30',\n\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Check className=\"h-3.5 w-3.5\" />\n\t\t\t\t\tApprove\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default ElicitationButtonBar\n","'use client'\n\nimport {\n\tComposerPrimitive,\n\tThreadPrimitive,\n\tuseComposer,\n\tuseComposerRuntime,\n} from '@assistant-ui/react'\nimport { Mic, Send, Square } from 'lucide-react'\nimport { useCallback, useRef } from 'react'\n\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport { COMPOSER_MAX_CHARS } from '../../lib/constants'\nimport { cn } from '../../lib/utils'\n\nimport type { FC } from 'react'\n\ninterface PillComposerProps {\n\tplaceholder?: string\n\tshowVoiceButton?: boolean\n\tisVoiceActive?: boolean\n\tonVoiceToggle?: () => void\n\tshowCharCount?: boolean\n\tclassName?: string\n\t/** Whether in elicitation mode (tool approval pending) */\n\tisEliciting?: boolean\n\t/** Called when user submits text during elicitation (denial with reason) */\n\tonElicitationSubmit?: (reason: string) => void\n}\n\n/**\n * Character count indicator\n */\nconst CharacterCount: FC = () => {\n\tconst composer = useComposer((c) => c.text)\n\tconst charCount = composer?.length ?? 0\n\n\t// Only show when approaching limit or over\n\tif (charCount < COMPOSER_MAX_CHARS * 0.8) return null\n\n\tconst isOver = charCount > COMPOSER_MAX_CHARS\n\tconst remaining = COMPOSER_MAX_CHARS - charCount\n\n\treturn (\n\t\t<span className={cn('text-[10px] tabular-nums', isOver ? 'text-red-400' : 'text-white/40')}>\n\t\t\t{remaining}\n\t\t</span>\n\t)\n}\n\n/**\n * Compact composer for the pill UI.\n * Uses assistant-ui primitives for data binding.\n * Features auto-growing textarea and character count.\n */\nexport const PillComposer: FC<PillComposerProps> = ({\n\tplaceholder = 'Ask something...',\n\tshowVoiceButton = false,\n\tisVoiceActive = false,\n\tonVoiceToggle,\n\tshowCharCount = true,\n\tclassName,\n\tisEliciting = false,\n\tonElicitationSubmit,\n}) => {\n\t// Don't auto-focus on mobile to avoid triggering the keyboard immediately\n\tconst { isMobile } = useMobileDetect()\n\tconst inputRef = useRef<HTMLTextAreaElement>(null)\n\tconst composerRuntime = useComposerRuntime()\n\n\t// Dynamic placeholder based on elicitation state\n\tconst effectivePlaceholder = isEliciting ? 'Tell Char what to do differently' : placeholder\n\n\t// Blur input on submit to dismiss mobile keyboard\n\tconst handleSubmit = useCallback(() => {\n\t\tif (isMobile && inputRef.current) {\n\t\t\tinputRef.current.blur()\n\t\t}\n\t}, [isMobile])\n\n\t// Handle elicitation submission (denial with reason)\n\tconst handleElicitationSubmit = useCallback(() => {\n\t\tconst text = composerRuntime.getState().text.trim()\n\t\tif (text && onElicitationSubmit) {\n\t\t\tonElicitationSubmit(text)\n\t\t\tcomposerRuntime.setText('')\n\t\t\tif (isMobile && inputRef.current) {\n\t\t\t\tinputRef.current.blur()\n\t\t\t}\n\t\t}\n\t}, [composerRuntime, onElicitationSubmit, isMobile])\n\n\t// Handle Enter key during elicitation - prevent normal form submission\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tif (isEliciting && e.key === 'Enter' && !e.shiftKey) {\n\t\t\t\te.preventDefault()\n\t\t\t\thandleElicitationSubmit()\n\t\t\t}\n\t\t},\n\t\t[isEliciting, handleElicitationSubmit]\n\t)\n\n\treturn (\n\t\t<ComposerPrimitive.Root\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-end gap-1.5',\n\t\t\t\t'rounded-xl',\n\t\t\t\t'bg-white/8 border border-white/8',\n\t\t\t\t'px-2 py-1',\n\t\t\t\t'focus-within:border-white/15 focus-within:bg-white/10',\n\t\t\t\t'transition-colors duration-150',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tonSubmit={handleSubmit}\n\t\t>\n\t\t\t{/* Text input - auto-grows with content */}\n\t\t\t<ComposerPrimitive.Input\n\t\t\t\tref={inputRef}\n\t\t\t\tplaceholder={effectivePlaceholder}\n\t\t\t\tminRows={1}\n\t\t\t\tmaxRows={6}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex-1 min-w-0',\n\t\t\t\t\t'bg-transparent',\n\t\t\t\t\t'text-sm leading-[21px] text-white placeholder:text-white/40',\n\t\t\t\t\t'outline-none',\n\t\t\t\t\t'resize-none',\n\t\t\t\t\t'overflow-y-auto scroll-touch'\n\t\t\t\t)}\n\t\t\t\tstyle={{ touchAction: 'pan-y' }}\n\t\t\t\tautoFocus={!isMobile}\n\t\t\t\t// Stop pointer events from bubbling to drag handler when typing\n\t\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t\t// Intercept Enter key during elicitation to call handleElicitationSubmit\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t/>\n\n\t\t\t{/* Character count */}\n\t\t\t{showCharCount && <CharacterCount />}\n\n\t\t\t{/* Voice button (optional) */}\n\t\t\t{showVoiceButton && onVoiceToggle && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onVoiceToggle}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\tisVoiceActive\n\t\t\t\t\t\t\t? 'bg-white/20 text-white'\n\t\t\t\t\t\t\t: 'hover:bg-white/10 text-white/50 hover:text-white/80'\n\t\t\t\t\t)}\n\t\t\t\t\taria-label={isVoiceActive ? 'Stop voice input' : 'Start voice input'}\n\t\t\t\t>\n\t\t\t\t\t<Mic className=\"h-4.5 w-4.5 sm:h-4 sm:w-4\" />\n\t\t\t\t</button>\n\t\t\t)}\n\n\t\t\t{/* Send button - shown when not running */}\n\t\t\t<ThreadPrimitive.If running={false}>\n\t\t\t\t{isEliciting ? (\n\t\t\t\t\t/* During elicitation: custom button that sends denial with reason */\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleElicitationSubmit}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t\t'bg-white/90 text-slate-900',\n\t\t\t\t\t\t\t'hover:bg-white',\n\t\t\t\t\t\t\t'disabled:opacity-40 disabled:cursor-not-allowed',\n\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-label=\"Send feedback\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Send className=\"h-4.5 w-4.5 sm:h-4 sm:w-4\" />\n\t\t\t\t\t</button>\n\t\t\t\t) : (\n\t\t\t\t\t/* Normal mode: use ComposerPrimitive.Send for standard message sending */\n\t\t\t\t\t<ComposerPrimitive.Send asChild>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t\t\t'bg-white/90 text-slate-900',\n\t\t\t\t\t\t\t\t'hover:bg-white',\n\t\t\t\t\t\t\t\t'disabled:opacity-40 disabled:cursor-not-allowed',\n\t\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\taria-label=\"Send message\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Send className=\"h-4.5 w-4.5 sm:h-4 sm:w-4\" />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</ComposerPrimitive.Send>\n\t\t\t\t)}\n\t\t\t</ThreadPrimitive.If>\n\n\t\t\t{/* Cancel button - shown when running */}\n\t\t\t<ThreadPrimitive.If running>\n\t\t\t\t<ComposerPrimitive.Cancel asChild>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t\t'bg-white/20 text-white',\n\t\t\t\t\t\t\t'hover:bg-white/30',\n\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-label=\"Stop generating\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Square className=\"h-4 w-4 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t</button>\n\t\t\t\t</ComposerPrimitive.Cancel>\n\t\t\t</ThreadPrimitive.If>\n\t\t</ComposerPrimitive.Root>\n\t)\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\n\n/**\n * Hook to manage aria-hidden on background content when a modal is open.\n *\n * This hook sets aria-hidden=\"true\" on all direct children of <body> except\n * the element containing the dialog, making the background inaccessible to\n * screen readers while the modal is active.\n *\n * Per WCAG, this is important because some mobile screen readers don't\n * consistently respect aria-modal=\"true\", so we need to explicitly hide\n * the background content.\n *\n * @param isActive - Whether the modal is currently active\n * @param containerRef - Ref to the modal container element\n */\nexport function useAriaHidden(\n\tisActive: boolean,\n\tcontainerRef: React.RefObject<HTMLElement | null>\n): void {\n\t// Track elements we've modified so we can restore them\n\tconst modifiedElementsRef = useRef<Map<Element, string | null>>(new Map())\n\n\tuseEffect(() => {\n\t\tif (!isActive) {\n\t\t\t// Restore all modified elements when modal closes\n\t\t\tmodifiedElementsRef.current.forEach((originalValue, element) => {\n\t\t\t\tif (originalValue === null) {\n\t\t\t\t\telement.removeAttribute('aria-hidden')\n\t\t\t\t} else {\n\t\t\t\t\telement.setAttribute('aria-hidden', originalValue)\n\t\t\t\t}\n\t\t\t})\n\t\t\tmodifiedElementsRef.current.clear()\n\t\t\treturn\n\t\t}\n\n\t\t// Find the container element's root ancestor (direct child of body)\n\t\tconst container = containerRef.current\n\t\tif (!container) return\n\n\t\t// Walk up to find the direct child of body\n\t\tlet dialogRoot: Element | null = container\n\t\twhile (dialogRoot && dialogRoot.parentElement !== document.body) {\n\t\t\tdialogRoot = dialogRoot.parentElement\n\t\t}\n\n\t\tif (!dialogRoot) return\n\n\t\t// Get all direct children of body\n\t\tconst bodyChildren = Array.from(document.body.children)\n\n\t\t// Hide all siblings of the dialog root\n\t\tbodyChildren.forEach((child) => {\n\t\t\t// Skip the dialog's root ancestor\n\t\t\tif (child === dialogRoot) return\n\n\t\t\t// Skip script and style elements\n\t\t\tif (child.tagName === 'SCRIPT' || child.tagName === 'STYLE' || child.tagName === 'LINK') {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Store the original aria-hidden value\n\t\t\tconst originalValue = child.getAttribute('aria-hidden')\n\t\t\tmodifiedElementsRef.current.set(child, originalValue)\n\n\t\t\t// Set aria-hidden to true\n\t\t\tchild.setAttribute('aria-hidden', 'true')\n\t\t})\n\n\t\t// Cleanup function to restore original values\n\t\treturn () => {\n\t\t\tmodifiedElementsRef.current.forEach((originalValue, element) => {\n\t\t\t\tif (originalValue === null) {\n\t\t\t\t\telement.removeAttribute('aria-hidden')\n\t\t\t\t} else {\n\t\t\t\t\telement.setAttribute('aria-hidden', originalValue)\n\t\t\t\t}\n\t\t\t})\n\t\t\tmodifiedElementsRef.current.clear()\n\t\t}\n\t}, [isActive, containerRef])\n}\n","'use client'\n\nimport { useCallback, useEffect, useRef } from 'react'\n\n/** Selector for all focusable elements within a container */\nconst FOCUSABLE_SELECTOR = [\n\t'a[href]',\n\t'button:not([disabled])',\n\t'input:not([disabled])',\n\t'select:not([disabled])',\n\t'textarea:not([disabled])',\n\t'[tabindex]:not([tabindex=\"-1\"])',\n\t'[contenteditable=\"true\"]',\n].join(', ')\n\ninterface UseFocusTrapOptions {\n\t/** Whether the focus trap is active */\n\tisActive: boolean\n\t/** Callback when user attempts to escape (e.g., pressing Escape) */\n\tonEscape?: () => void\n\t/** Whether to auto-focus the first focusable element when activated */\n\tautoFocus?: boolean\n\t/** Whether to return focus to the trigger element when deactivated */\n\treturnFocus?: boolean\n\t/** Whether to skip returning focus to input elements (prevents mobile keyboard re-trigger) */\n\tskipInputFocusReturn?: boolean\n}\n\ninterface UseFocusTrapReturn {\n\t/** Ref to attach to the container element */\n\tcontainerRef: React.RefObject<HTMLDivElement | null>\n\t/** Store the trigger element before activating the trap */\n\tstoreTrigger: () => void\n}\n\n/**\n * Focus trap hook for modal dialogs.\n *\n * Implements WCAG 2.4.3 Focus Order requirements:\n * - Traps Tab/Shift+Tab within the container\n * - Returns focus to trigger element on close\n * - Supports Escape key to close\n *\n * @example\n * ```tsx\n * const { containerRef, storeTrigger } = useFocusTrap({\n * isActive: isDialogOpen,\n * onEscape: () => setIsDialogOpen(false),\n * })\n *\n * // Before opening dialog:\n * storeTrigger()\n * setIsDialogOpen(true)\n *\n * // In JSX:\n * <div ref={containerRef} role=\"dialog\">...</div>\n * ```\n */\nexport function useFocusTrap({\n\tisActive,\n\tonEscape,\n\tautoFocus = true,\n\treturnFocus = true,\n\tskipInputFocusReturn = false,\n}: UseFocusTrapOptions): UseFocusTrapReturn {\n\tconst containerRef = useRef<HTMLDivElement | null>(null)\n\tconst triggerRef = useRef<HTMLElement | null>(null)\n\tconst previouslyFocusedRef = useRef<HTMLElement | null>(null)\n\n\t/** Store the currently focused element as the trigger */\n\tconst storeTrigger = useCallback(() => {\n\t\ttriggerRef.current = document.activeElement as HTMLElement\n\t}, [])\n\n\t/** Get all focusable elements within the container */\n\tconst getFocusableElements = useCallback((): HTMLElement[] => {\n\t\tif (!containerRef.current) return []\n\t\treturn Array.from(containerRef.current.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR))\n\t}, [])\n\n\t// Handle focus trap activation/deactivation\n\tuseEffect(() => {\n\t\tif (isActive) {\n\t\t\t// Store the currently focused element before trapping\n\t\t\tpreviouslyFocusedRef.current = document.activeElement as HTMLElement\n\n\t\t\t// Auto-focus the first focusable element\n\t\t\tif (autoFocus) {\n\t\t\t\t// Small delay to ensure container is mounted and visible\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\tconst focusableElements = getFocusableElements()\n\t\t\t\t\tif (focusableElements.length > 0) {\n\t\t\t\t\t\tfocusableElements[0].focus()\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no focusable elements, focus the container itself\n\t\t\t\t\t\tcontainerRef.current?.focus()\n\t\t\t\t\t}\n\t\t\t\t}, 50)\n\n\t\t\t\treturn () => clearTimeout(timeoutId)\n\t\t\t}\n\t\t} else {\n\t\t\t// Return focus to the trigger element\n\t\t\tif (returnFocus && triggerRef.current && triggerRef.current.isConnected) {\n\t\t\t\t// Skip returning focus to inputs/textareas if configured (prevents mobile keyboard re-trigger)\n\t\t\t\tconst isInputElement =\n\t\t\t\t\ttriggerRef.current.tagName === 'INPUT' || triggerRef.current.tagName === 'TEXTAREA'\n\n\t\t\t\tif (skipInputFocusReturn && isInputElement) {\n\t\t\t\t\t// Blur the input instead of focusing it\n\t\t\t\t\ttriggerRef.current.blur()\n\t\t\t\t} else {\n\t\t\t\t\ttriggerRef.current.focus()\n\t\t\t\t}\n\t\t\t} else if (returnFocus && previouslyFocusedRef.current?.isConnected) {\n\t\t\t\tconst isInputElement =\n\t\t\t\t\tpreviouslyFocusedRef.current.tagName === 'INPUT' ||\n\t\t\t\t\tpreviouslyFocusedRef.current.tagName === 'TEXTAREA'\n\n\t\t\t\tif (skipInputFocusReturn && isInputElement) {\n\t\t\t\t\tpreviouslyFocusedRef.current.blur()\n\t\t\t\t} else {\n\t\t\t\t\tpreviouslyFocusedRef.current.focus()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [isActive, autoFocus, returnFocus, skipInputFocusReturn, getFocusableElements])\n\n\t// Handle keyboard navigation\n\tuseEffect(() => {\n\t\tif (!isActive) return\n\n\t\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\t\t// Handle Escape key\n\t\t\tif (event.key === 'Escape' && onEscape) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tonEscape()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Handle Tab key for focus trapping\n\t\t\tif (event.key === 'Tab') {\n\t\t\t\tconst focusableElements = getFocusableElements()\n\t\t\t\tif (focusableElements.length === 0) return\n\n\t\t\t\tconst firstElement = focusableElements[0]\n\t\t\t\tconst lastElement = focusableElements[focusableElements.length - 1]\n\t\t\t\tconst activeElement = document.activeElement\n\n\t\t\t\t// Shift+Tab from first element -> go to last\n\t\t\t\tif (event.shiftKey && activeElement === firstElement) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tlastElement.focus()\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Tab from last element -> go to first\n\t\t\t\tif (!event.shiftKey && activeElement === lastElement) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tfirstElement.focus()\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// If focus is outside the container, bring it back\n\t\t\t\tif (!containerRef.current?.contains(activeElement)) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tfirstElement.focus()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown)\n\t}, [isActive, onEscape, getFocusableElements])\n\n\treturn {\n\t\tcontainerRef,\n\t\tstoreTrigger,\n\t}\n}\n","'use client'\n\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { useAriaHidden } from '../../hooks/useAriaHidden'\nimport { useFocusTrap } from '../../hooks/useFocusTrap'\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport {\n\tARIA_IDS,\n\tARIA_LABELS,\n\tclampSize,\n\tFULL_SCREEN_CONFIG,\n\tPILL_BORDER_RADIUS,\n\tPILL_CONTAINER_SIZES,\n\tUI_TIMING,\n} from '../../lib/constants'\nimport { cn } from '../../lib/utils'\n\nimport type { Variants } from 'motion/react'\nimport type { FC, ReactNode } from 'react'\nimport type { PillMode } from '../../core/providers/AgentUIProvider'\n\n// Re-export PillMode for consumers who import from this file\nexport type { PillMode } from '../../core/providers/AgentUIProvider'\n\ninterface PillContainerProps {\n\tmode: PillMode\n\tchildren: ReactNode\n\tonModeChange?: (mode: PillMode) => void\n\t/** Whether the pill is in full-screen expanded mode */\n\tisFullScreen?: boolean\n\tclassName?: string\n}\n\n// Spring configuration for size changes - snappy but smooth\nconst sizeSpring = {\n\ttype: 'spring' as const,\n\tstiffness: 400,\n\tdamping: 35,\n\tmass: 0.8,\n}\n\n// Smooth tween for full-screen transitions (spring is too aggressive for large viewport changes)\nconst fullScreenTween = {\n\ttype: 'tween' as const,\n\tduration: 0.35,\n\tease: [0.4, 0, 0.2, 1], // Material Design standard easing\n}\n\n// Reduced motion alternative - instant transitions\nconst reducedMotionTransition = {\n\tduration: 0,\n}\n\n// Container size variants - derived from centralized PILL_CONTAINER_SIZES config\n// See lib/constants.ts for the source of truth\n// Padding reduced for better mobile information density\nconst sizes = PILL_CONTAINER_SIZES\nconst containerVariants: Record<\n\tPillMode,\n\t{ width: string; height: string; padding: string; borderRadius: string }\n> = {\n\tcollapsed: {\n\t\twidth: clampSize(sizes.collapsed.width),\n\t\theight: clampSize(sizes.collapsed.height),\n\t\tpadding: '0px',\n\t\tborderRadius: PILL_BORDER_RADIUS.pill,\n\t},\n\thovered: {\n\t\twidth: clampSize(sizes.hovered.width),\n\t\theight: clampSize(sizes.hovered.height),\n\t\tpadding: '0px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.pill,\n\t},\n\tcomposing: {\n\t\twidth: clampSize(sizes.composing.width),\n\t\theight: 'auto',\n\t\tpadding: '8px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.rounded,\n\t},\n\tactive: {\n\t\twidth: clampSize(sizes.active.width),\n\t\theight: 'auto',\n\t\tpadding: '8px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.rounded,\n\t},\n\texpanded: {\n\t\twidth: clampSize(sizes.expanded.width),\n\t\theight: 'auto',\n\t\tpadding: '10px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.rounded,\n\t},\n}\n\n// Full-screen variant - uses the same animation system\nconst fullScreenVariant = {\n\twidth: `min(${FULL_SCREEN_CONFIG.widthPercent}vw, ${FULL_SCREEN_CONFIG.maxWidth})`,\n\theight: `${FULL_SCREEN_CONFIG.heightPercent}vh`,\n\tpadding: `${FULL_SCREEN_CONFIG.padding}px`,\n\tborderRadius: PILL_BORDER_RADIUS.rounded,\n}\n\n// Content animation variants - simple fade, no transform\nconst contentVariants: Variants = {\n\thidden: {\n\t\topacity: 0,\n\t},\n\tvisible: {\n\t\topacity: 1,\n\t\ttransition: {\n\t\t\tduration: 0.15,\n\t\t\tdelay: 0.1, // Wait for container to expand first\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\ttransition: {\n\t\t\tduration: 0.1,\n\t\t},\n\t},\n}\n\n// Hint text animation - simple fade\nconst hintVariants: Variants = {\n\thidden: { opacity: 0 },\n\tvisible: {\n\t\topacity: 1,\n\t\ttransition: { delay: 0.05, duration: 0.15 },\n\t},\n\texit: {\n\t\topacity: 0,\n\t\ttransition: { duration: 0.08 },\n\t},\n}\n\n// Collapsed bar animation\nconst barVariants: Variants = {\n\tidle: {\n\t\topacity: 0.6,\n\t\tscaleX: 1,\n\t},\n\thover: {\n\t\topacity: 1,\n\t\tscaleX: 1.1,\n\t\ttransition: { duration: 0.2 },\n\t},\n}\n\n/**\n * Morphing container that changes size and shape based on state.\n * Uses spring animations for smooth, natural transitions.\n *\n * States:\n * - collapsed: Tiny 4px tall bar (ambient)\n * - hovered: Medium pill with prompt\n * - composing: User is typing\n * - active: Agent is working\n * - expanded: Full panel with summary/forms\n */\nexport const PillContainer: FC<PillContainerProps> = ({\n\tmode,\n\tchildren,\n\tonModeChange,\n\tisFullScreen = false,\n\tclassName,\n}) => {\n\tconst [isHovered, setIsHovered] = useState(false)\n\tconst hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n\tconst prefersReducedMotion = useReducedMotion()\n\n\t// Track previous full-screen state for smooth exit animations\n\tconst wasFullScreenRef = useRef(isFullScreen)\n\tconst isTransitioningFullScreen = isFullScreen !== wasFullScreenRef.current\n\t// Update ref after render\n\tuseEffect(() => {\n\t\twasFullScreenRef.current = isFullScreen\n\t}, [isFullScreen])\n\n\t// Detect mobile/touch devices\n\tconst { isMobile } = useMobileDetect()\n\n\t// Determine if dialog mode (for focus trap)\n\tconst isDialogActive = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t// Focus trap for accessibility - traps focus when in dialog mode\n\tconst { containerRef: focusTrapRef, storeTrigger } = useFocusTrap({\n\t\tisActive: isDialogActive,\n\t\tonEscape: () => {\n\t\t\t// Only collapse if not in active mode (agent is working)\n\t\t\tif (mode !== 'active') {\n\t\t\t\tonModeChange?.('collapsed')\n\t\t\t}\n\t\t},\n\t\tautoFocus: true,\n\t\treturnFocus: true,\n\t\t// On mobile, don't return focus to inputs (prevents keyboard re-triggering)\n\t\tskipInputFocusReturn: isMobile,\n\t})\n\n\t// Store trigger element before transitioning to dialog mode\n\tconst prevModeRef = useRef(mode)\n\tuseEffect(() => {\n\t\tconst wasCollapsedOrHovered =\n\t\t\tprevModeRef.current === 'collapsed' || prevModeRef.current === 'hovered'\n\t\tconst isNowDialog = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t\tif (wasCollapsedOrHovered && isNowDialog) {\n\t\t\tstoreTrigger()\n\t\t}\n\n\t\tprevModeRef.current = mode\n\t}, [mode, storeTrigger])\n\n\t// Hide background content from screen readers when in dialog mode\n\t// This is a fallback for mobile screen readers that don't respect aria-modal\n\tuseAriaHidden(isDialogActive, focusTrapRef)\n\n\t// Handle hover with debounce - only on non-touch devices\n\tconst handleMouseEnter = useCallback(() => {\n\t\t// Skip hover behavior on touch devices\n\t\tif (isMobile) return\n\n\t\tif (hoverTimeoutRef.current) {\n\t\t\tclearTimeout(hoverTimeoutRef.current)\n\t\t}\n\t\thoverTimeoutRef.current = setTimeout(() => {\n\t\t\tsetIsHovered(true)\n\t\t\tif (mode === 'collapsed') {\n\t\t\t\tonModeChange?.('hovered')\n\t\t\t}\n\t\t}, UI_TIMING.hoverDebounce)\n\t}, [mode, onModeChange, isMobile])\n\n\tconst handleMouseLeave = useCallback(() => {\n\t\t// Skip hover behavior on touch devices\n\t\tif (isMobile) return\n\n\t\tif (hoverTimeoutRef.current) {\n\t\t\tclearTimeout(hoverTimeoutRef.current)\n\t\t}\n\t\tsetIsHovered(false)\n\t\tif (mode === 'hovered') {\n\t\t\t// Small delay before collapsing to prevent flicker\n\t\t\thoverTimeoutRef.current = setTimeout(() => {\n\t\t\t\tonModeChange?.('collapsed')\n\t\t\t}, UI_TIMING.collapseDelay)\n\t\t}\n\t}, [mode, onModeChange, isMobile])\n\n\t// Handle click/tap to expand - on mobile, skip hover and go straight to composing\n\tconst handleClick = useCallback(() => {\n\t\tif (mode === 'collapsed' || mode === 'hovered') {\n\t\t\tonModeChange?.('composing')\n\t\t}\n\t}, [mode, onModeChange])\n\n\t// Handle focus for keyboard navigation - also helps on touch\n\tconst handleFocus = useCallback(() => {\n\t\tif (mode === 'collapsed' && !isMobile) {\n\t\t\tonModeChange?.('hovered')\n\t\t}\n\t}, [mode, onModeChange, isMobile])\n\n\tconst handleBlur = useCallback(() => {\n\t\tif (mode === 'hovered' && !isMobile) {\n\t\t\tonModeChange?.('collapsed')\n\t\t}\n\t}, [mode, onModeChange, isMobile])\n\n\t// Handle keyboard shortcuts (Cmd+Shift+K to toggle, Escape to close)\n\tuseEffect(() => {\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tconst isShortcut = (e.ctrlKey || e.metaKey) && e.shiftKey && e.key.toLowerCase() === 'k'\n\t\t\tconst isEscape = e.key === 'Escape'\n\n\t\t\tif (isShortcut) {\n\t\t\t\te.preventDefault()\n\t\t\t\tif (mode === 'collapsed') {\n\t\t\t\t\tonModeChange?.('composing')\n\t\t\t\t} else if (mode === 'composing' || mode === 'hovered') {\n\t\t\t\t\tonModeChange?.('collapsed')\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Escape to close (only when expanded, not when agent is running)\n\t\t\tif (isEscape && (mode === 'composing' || mode === 'expanded' || mode === 'hovered')) {\n\t\t\t\te.preventDefault()\n\t\t\t\tonModeChange?.('collapsed')\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('keydown', handleKeyDown)\n\t\treturn () => window.removeEventListener('keydown', handleKeyDown)\n\t}, [mode, onModeChange])\n\n\t// Clean up timeout on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (hoverTimeoutRef.current) {\n\t\t\t\tclearTimeout(hoverTimeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst showContent = mode !== 'collapsed' && mode !== 'hovered'\n\t// Use full-screen variant when in full-screen mode, otherwise use mode-based variant\n\tconst currentVariant = isFullScreen ? fullScreenVariant : containerVariants[mode]\n\tconst isDialogMode = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t// Combine refs for motion.div (focus trap ref + internal needs)\n\tconst setContainerRef = useCallback(\n\t\t(node: HTMLDivElement | null) => {\n\t\t\t// Update the focus trap ref\n\t\t\tif (focusTrapRef) {\n\t\t\t\tfocusTrapRef.current = node\n\t\t\t}\n\t\t},\n\t\t[focusTrapRef]\n\t)\n\n\t// Determine glass styling class based on mode\n\tconst glassClassName = cn(\n\t\t'relative',\n\t\t// Full-screen: allow scrolling. Normal: clip overflow during animations\n\t\tisFullScreen ? 'overflow-y-auto scrollbar-thin scroll-touch' : 'overflow-hidden',\n\t\t// GPU acceleration hint (skip if reduced motion)\n\t\t!prefersReducedMotion && 'will-change-transform',\n\t\t// Focus states for keyboard navigation\n\t\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent',\n\t\t// Base glass styling (overridden by mode-specific classes)\n\t\tmode === 'collapsed' && 'glass-pill-collapsed',\n\t\tmode === 'hovered' && 'glass-pill-hovered',\n\t\t(mode === 'composing' || mode === 'expanded') && 'glass-pill',\n\t\tmode === 'active' && 'glass-pill glass-active',\n\t\tclassName\n\t)\n\n\t// Use reduced motion transition when user prefers it\n\t// Use smooth tween for full-screen transitions (spring is too aggressive for large viewport changes)\n\tconst transition = prefersReducedMotion\n\t\t? reducedMotionTransition\n\t\t: isTransitioningFullScreen || isFullScreen\n\t\t\t? fullScreenTween\n\t\t\t: sizeSpring\n\n\treturn (\n\t\t<motion.div\n\t\t\tref={setContainerRef}\n\t\t\tclassName={glassClassName}\n\t\t\tinitial={false}\n\t\t\tanimate={{\n\t\t\t\twidth: currentVariant.width,\n\t\t\t\theight: currentVariant.height,\n\t\t\t\tpadding: currentVariant.padding,\n\t\t\t\tborderRadius: currentVariant.borderRadius,\n\t\t\t}}\n\t\t\ttransition={transition}\n\t\t\tonMouseEnter={handleMouseEnter}\n\t\t\tonMouseLeave={handleMouseLeave}\n\t\t\tonClick={handleClick}\n\t\t\tonFocus={handleFocus}\n\t\t\tonBlur={handleBlur}\n\t\t\t// Button mode: collapsed/hovered - acts as a button to open\n\t\t\trole={isDialogMode ? 'dialog' : 'button'}\n\t\t\ttabIndex={isDialogMode ? -1 : 0}\n\t\t\t// Dialog mode: composing/active/expanded - acts as a modal dialog\n\t\t\taria-modal={isDialogMode ? true : undefined}\n\t\t\taria-labelledby={isDialogMode ? ARIA_IDS.pillTitle : undefined}\n\t\t\taria-label={!isDialogMode ? ARIA_LABELS.openAssistant : undefined}\n\t\t>\n\t\t\t{/* Collapsed state - glass shimmer highlight */}\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{mode === 'collapsed' && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tkey=\"collapsed-bar\"\n\t\t\t\t\t\tclassName=\"absolute inset-0\"\n\t\t\t\t\t\tvariants={barVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\tanimate={isHovered ? 'hover' : 'idle'}\n\t\t\t\t\t\texit={{ opacity: 0, transition: { duration: 0.1 } }}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent)',\n\t\t\t\t\t\t\tbackgroundSize: '200% 100%',\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Hovered state - hint text */}\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{mode === 'hovered' && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tkey=\"hover-hint\"\n\t\t\t\t\t\tclassName=\"relative z-10 flex h-full w-full items-center justify-center\"\n\t\t\t\t\t\tvariants={hintVariants}\n\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\texit=\"exit\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span className=\"text-xs text-white/70\">\n\t\t\t\t\t\t\tClick or{' '}\n\t\t\t\t\t\t\t<kbd className=\"rounded bg-white/10 px-1.5 py-0.5 font-mono text-[10px]\">⌘⇧K</kbd>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Expanded content - z-10 ensures content sits above glass highlight overlays */}\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{showContent && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tkey=\"content\"\n\t\t\t\t\t\tclassName=\"relative z-10 flex flex-col gap-1.5\"\n\t\t\t\t\t\tvariants={contentVariants}\n\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\texit=\"exit\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{/* Visually hidden title for screen readers (referenced by aria-labelledby) */}\n\t\t\t\t\t\t<span id={ARIA_IDS.pillTitle} className=\"sr-only\">\n\t\t\t\t\t\t\tAI Assistant\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\t\t</motion.div>\n\t)\n}\n","import { Slot } from '@radix-ui/react-slot'\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nimport type { VariantProps } from 'class-variance-authority'\n\nexport interface ButtonProps\n\textends React.ComponentProps<'button'>,\n\t\tVariantProps<typeof buttonVariants> {\n\tasChild?: boolean\n}\n\nconst buttonVariants = cva(\n\t\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'bg-primary text-primary-foreground hover:bg-primary/90',\n\t\t\t\tdestructive:\n\t\t\t\t\t'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n\t\t\t\toutline:\n\t\t\t\t\t'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n\t\t\t\tsecondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n\t\t\t\tghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n\t\t\t\tlink: 'text-primary underline-offset-4 hover:underline',\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: 'h-9 px-4 py-2 has-[>svg]:px-3',\n\t\t\t\tsm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',\n\t\t\t\tlg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n\t\t\t\ticon: 'size-9',\n\t\t\t\t'icon-sm': 'size-8',\n\t\t\t\t'icon-lg': 'size-10',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t\tsize: 'default',\n\t\t},\n\t}\n)\n\nfunction Button({\n\tclassName,\n\tvariant,\n\tsize,\n\tasChild = false,\n\t...props\n}: React.ComponentProps<'button'> &\n\tVariantProps<typeof buttonVariants> & {\n\t\tasChild?: boolean\n\t}) {\n\tconst Comp = asChild ? Slot : 'button'\n\n\treturn (\n\t\t<Comp\n\t\t\tdata-slot=\"button\"\n\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Button, buttonVariants }\n","/**\n * UnifiedToolFallback Component\n *\n * A unified fallback component that handles ALL tool call states:\n * - Running: Shows activity indicator with tool name\n * - Pending approval: Shows approval dialog for destructive tools\n * - Completed: Shows success indicator with collapsible args/result\n * - Error: Shows error state\n *\n * This provides an alternative to separate ActionList/CurrentActivity components\n * by rendering tool states directly in the message thread.\n */\n'use client'\n\nimport { AlertCircle, AlertTriangle, Check, ChevronDownIcon, ChevronUpIcon, X } from 'lucide-react'\nimport { useCallback, useState } from 'react'\n\nimport { formatArgs, humanizeToolName, TOOL_DENIED_MESSAGE } from '../lib/format'\nimport { cn } from '../lib/utils'\nimport { useMCPTools } from '../providers/MCPToolsProvider'\nimport { Button } from './button'\nimport { formatToolResult } from './MCPToolRegistry'\nimport { getToolIcon } from './pill/ActivityIndicator'\n\nimport type { ToolCallMessagePartComponent } from '@assistant-ui/react'\n\n// ============================================================================\n// Approval Result Types\n// ============================================================================\n\ninterface ApprovedResult {\n\tapproved: true\n\tresult: string\n}\n\nfunction isApprovedResult(result: unknown): result is ApprovedResult {\n\treturn (\n\t\ttypeof result === 'object' &&\n\t\tresult !== null &&\n\t\t'approved' in result &&\n\t\t(result as ApprovedResult).approved === true &&\n\t\t'result' in result\n\t)\n}\n\n/**\n * Check if result indicates a denied tool execution.\n * Handles both string format (legacy) and structured format.\n */\nfunction isDeniedResult(result: unknown): boolean {\n\t// Check for string denial message\n\tif (typeof result === 'string' && result === TOOL_DENIED_MESSAGE) {\n\t\treturn true\n\t}\n\t// Check for structured denial (future-proofing)\n\tif (\n\t\ttypeof result === 'object' &&\n\t\tresult !== null &&\n\t\t'approved' in result &&\n\t\t(result as { approved: boolean }).approved === false\n\t) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * Type guard for status with error property\n */\nfunction hasStatusError(status: { type: string }): status is { type: string; error: string } {\n\treturn 'error' in status && typeof (status as { error?: unknown }).error === 'string'\n}\n\n// ============================================================================\n// Sub-Components for Each State\n// ============================================================================\n\n/**\n * Running state - tool is currently executing\n */\nconst RunningToolDisplay: React.FC<{\n\ttoolName: string\n}> = ({ toolName }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-white/5 px-2 py-1.5 text-sm text-white/70\">\n\t\t\t<ToolIcon className=\"h-3.5 w-3.5 animate-pulse text-white/50\" />\n\t\t\t<span>\n\t\t\t\t<strong className=\"text-white/90\">{humanizeToolName(toolName)}</strong>\n\t\t\t</span>\n\t\t</div>\n\t)\n}\n\n/**\n * Approval dialog for destructive tools (HITL pattern)\n * Used when a tool has no execute function and requires user approval.\n */\nconst ApprovalDialog: React.FC<{\n\ttoolName: string\n\ttoolDescription?: string\n\tinputArgs: Record<string, unknown>\n\tonApprove: () => void\n\tonDeny: () => void\n\tisExecuting: boolean\n}> = ({ toolName, toolDescription, inputArgs, onApprove, onDeny, isExecuting }) => {\n\tconst [isHovered, setIsHovered] = useState<'approve' | 'deny' | null>(null)\n\tconst ToolIcon = getToolIcon(toolName)\n\n\tif (isExecuting) {\n\t\treturn (\n\t\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-white/5 px-2 py-1.5 text-sm text-white/70\">\n\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 animate-pulse text-white/50\" />\n\t\t\t\t<span>\n\t\t\t\t\t<strong className=\"text-white/90\">{humanizeToolName(toolName)}</strong>\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div className={cn('my-1 overflow-hidden rounded-lg', 'bg-white/5')}>\n\t\t\t{/* Header - compact */}\n\t\t\t<div className=\"flex items-center gap-1.5 px-2 py-1.5 border-b border-white/5\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/70\" />\n\t\t\t\t\t<AlertTriangle className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/70\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"text-xs font-medium text-white/90\">{humanizeToolName(toolName)}</span>\n\t\t\t</div>\n\n\t\t\t{/* Content */}\n\t\t\t<div className=\"px-2 py-2\">\n\t\t\t\t{toolDescription && <div className=\"mb-2 text-xs text-white/50\">{toolDescription}</div>}\n\n\t\t\t\t{/* Arguments - compact */}\n\t\t\t\t{inputArgs && Object.keys(inputArgs).length > 0 && (\n\t\t\t\t\t<div className=\"mb-2 rounded bg-white/5 p-1.5\">\n\t\t\t\t\t\t<pre className=\"whitespace-pre-wrap text-[11px] text-white/60\">\n\t\t\t\t\t\t\t{formatArgs(inputArgs)}\n\t\t\t\t\t\t</pre>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Action buttons - compact */}\n\t\t\t\t<div className=\"flex justify-end gap-1.5\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onDeny}\n\t\t\t\t\t\tonMouseEnter={() => setIsHovered('deny')}\n\t\t\t\t\t\tonMouseLeave={() => setIsHovered(null)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex items-center gap-1 rounded px-2.5 py-1.5 text-xs font-medium sm:px-2 sm:py-1',\n\t\t\t\t\t\t\t'border border-white/10 text-white/60',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisHovered === 'deny' ? 'bg-white/10 text-white/80' : 'hover:bg-white/5'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X className=\"h-3.5 w-3.5 sm:h-3 sm:w-3\" />\n\t\t\t\t\t\tDeny\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onApprove}\n\t\t\t\t\t\tonMouseEnter={() => setIsHovered('approve')}\n\t\t\t\t\t\tonMouseLeave={() => setIsHovered(null)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex items-center gap-1 rounded px-2.5 py-1.5 text-xs font-medium sm:px-2 sm:py-1',\n\t\t\t\t\t\t\t'bg-white/90 text-slate-900',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisHovered === 'approve' ? 'bg-white' : 'hover:bg-white/95'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Check className=\"h-3.5 w-3.5 sm:h-3 sm:w-3\" />\n\t\t\t\t\t\tOK\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/**\n * Completed tool display - success state with collapsible details\n */\nconst CompletedToolDisplay: React.FC<{\n\ttoolName: string\n\targsText: string\n\tresult: unknown\n}> = ({ toolName, argsText, result }) => {\n\tconst [isExpanded, setIsExpanded] = useState(false)\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-white/5\">\n\t\t\t{/* Header - compact */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setIsExpanded(!isExpanded)}\n\t\t\t\tclassName=\"flex w-full items-center gap-1.5 px-2 py-1.5 text-left transition-colors hover:bg-white/5\"\n\t\t\t>\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/50\" />\n\t\t\t\t\t<Check className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/50\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"flex-grow text-xs font-medium text-white/80\">\n\t\t\t\t\t{humanizeToolName(toolName)}\n\t\t\t\t</span>\n\t\t\t\t<Button variant=\"ghost\" size=\"sm\" className=\"h-5 w-5 p-0\" asChild>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t{isExpanded ? (\n\t\t\t\t\t\t\t<ChevronUpIcon className=\"h-3 w-3 text-white/40\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<ChevronDownIcon className=\"h-3 w-3 text-white/40\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t</button>\n\n\t\t\t{/* Expandable content */}\n\t\t\t{isExpanded && (\n\t\t\t\t<div className=\"border-t border-white/5 px-2 py-1.5\">\n\t\t\t\t\t{/* Input args */}\n\t\t\t\t\t{argsText && (\n\t\t\t\t\t\t<div className=\"mb-1.5\">\n\t\t\t\t\t\t\t<div className=\"mb-0.5 text-[10px] font-medium uppercase tracking-wide text-white/40\">\n\t\t\t\t\t\t\t\tInput\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<pre className=\"max-h-24 overflow-auto whitespace-pre-wrap rounded bg-white/5 p-1.5 font-mono text-[11px] text-white/60\">\n\t\t\t\t\t\t\t\t{argsText}\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Output result */}\n\t\t\t\t\t{result !== undefined && (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div className=\"mb-0.5 text-[10px] font-medium uppercase tracking-wide text-white/40\">\n\t\t\t\t\t\t\t\tOutput\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<pre className=\"max-h-32 overflow-auto whitespace-pre-wrap rounded bg-white/5 p-1.5 font-mono text-[11px] text-white/60\">\n\t\t\t\t\t\t\t\t{typeof result === 'string' ? result : JSON.stringify(result, null, 2)}\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/**\n * Error state display\n */\nconst ErrorToolDisplay: React.FC<{\n\ttoolName: string\n\terror?: string\n}> = ({ toolName, error }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-white/5\">\n\t\t\t<div className=\"flex items-center gap-1.5 px-2 py-1.5\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/50\" />\n\t\t\t\t\t<AlertCircle className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/50\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"text-xs font-medium text-white/70\">\n\t\t\t\t\t{humanizeToolName(toolName)} failed\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t{error && (\n\t\t\t\t<div className=\"border-t border-white/5 px-2 py-1.5\">\n\t\t\t\t\t<pre className=\"whitespace-pre-wrap font-mono text-[11px] text-white/50\">{error}</pre>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/**\n * Denied approval display\n */\nconst DeniedToolDisplay: React.FC<{\n\ttoolName: string\n}> = ({ toolName }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-white/5 px-2 py-1.5 text-xs text-white/60\">\n\t\t\t<div className=\"relative\">\n\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/40\" />\n\t\t\t\t<X className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/40\" />\n\t\t\t</div>\n\t\t\t<span>\n\t\t\t\t<strong className=\"text-white/70\">{humanizeToolName(toolName)}</strong> denied\n\t\t\t</span>\n\t\t</div>\n\t)\n}\n\n// ============================================================================\n// Main Unified Fallback Component\n// ============================================================================\n\n/**\n * Unified fallback component that handles all tool call states.\n * This is the single source of truth for tool rendering in the thread.\n *\n * HITL Pattern: For tools without an execute function (destructive tools),\n * the model pauses and waits for addResult() to be called. This component\n * shows an approval dialog and handles the execution on user approval.\n */\nexport const UnifiedToolFallback: ToolCallMessagePartComponent = ({\n\ttoolCallId: _toolCallId,\n\ttoolName,\n\targsText,\n\targs,\n\tstatus,\n\tresult,\n\taddResult,\n}) => {\n\tconst { callTool, tools } = useMCPTools()\n\tconst [isExecuting, setIsExecuting] = useState(false)\n\n\t// Parse args - use args prop if available, otherwise parse from argsText\n\tconst parsedArgs: Record<string, unknown> =\n\t\targs ??\n\t\t(() => {\n\t\t\ttry {\n\t\t\t\treturn argsText ? JSON.parse(argsText) : {}\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn(`[UnifiedToolFallback] Failed to parse args for tool \"${toolName}\":`, e)\n\t\t\t\treturn {}\n\t\t\t}\n\t\t})()\n\n\t// Get tool description from registered tools\n\tconst toolDescription = tools.find((t) => t.name === toolName)?.description\n\n\t// Handle approval - execute the tool and add result\n\tconst handleApprove = useCallback(async () => {\n\t\tsetIsExecuting(true)\n\t\ttry {\n\t\t\tconst toolResult = await callTool(toolName, parsedArgs)\n\t\t\taddResult(formatToolResult(toolResult))\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\t\t\taddResult(`Error: ${errorMessage}`)\n\t\t} finally {\n\t\t\tsetIsExecuting(false)\n\t\t}\n\t}, [toolName, parsedArgs, callTool, addResult])\n\n\t// Handle denial - add denial result using shared constant\n\tconst handleDeny = useCallback(() => {\n\t\taddResult(TOOL_DENIED_MESSAGE)\n\t}, [addResult])\n\n\t// Determine the current state and render accordingly\n\tconst statusType = status.type\n\n\t// Check if this is a pending approval\n\tconst isPendingApproval = statusType === 'requires-action' && result === undefined\n\n\t// Case 1: HITL - Tool requires action (no execute function, waiting for approval)\n\t// This is the key case for destructive tools!\n\tif (isPendingApproval) {\n\t\treturn (\n\t\t\t<ApprovalDialog\n\t\t\t\ttoolName={toolName}\n\t\t\t\ttoolDescription={toolDescription}\n\t\t\t\tinputArgs={parsedArgs}\n\t\t\t\tonApprove={handleApprove}\n\t\t\t\tonDeny={handleDeny}\n\t\t\t\tisExecuting={isExecuting}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Case 2: Tool was denied (result contains denial message)\n\tif (isDeniedResult(result)) {\n\t\treturn <DeniedToolDisplay toolName={toolName} />\n\t}\n\n\t// Case 3: Tool is currently running (has execute function)\n\tif (statusType === 'running') {\n\t\treturn <RunningToolDisplay toolName={toolName} />\n\t}\n\n\t// Case 4: Tool completed with error\n\tif (statusType === 'incomplete' || hasStatusError(status)) {\n\t\tconst errorMessage = hasStatusError(status) ? status.error : 'Tool execution failed'\n\t\treturn <ErrorToolDisplay toolName={toolName} error={errorMessage} />\n\t}\n\n\t// Case 5: Tool completed successfully\n\tif (statusType === 'complete') {\n\t\t// If it's an approved result object, show the actual result\n\t\tconst displayResult = isApprovedResult(result) ? result.result : result\n\n\t\treturn <CompletedToolDisplay toolName={toolName} argsText={argsText} result={displayResult} />\n\t}\n\n\t// Fallback - shouldn't reach here normally\n\treturn null\n}\n\nexport default UnifiedToolFallback\n","/**\n * PillMessageContent Component\n *\n * Renders assistant message content (tool calls) using assistant-ui primitives.\n * Uses UnifiedToolFallback to render ALL tool states directly in the thread:\n * - Running tools with activity indicator\n * - Pending approval dialogs for destructive tools\n * - Completed tools with collapsible args/result\n * - Error states\n *\n * This provides an alternative to separate ActionList/CurrentActivity components\n * by rendering tool state directly in the conversation flow.\n */\n'use client'\n\nimport { MessagePrimitive, ThreadPrimitive } from '@assistant-ui/react'\n\nimport { UnifiedToolFallback } from '../UnifiedToolFallback'\n\nimport type { FC } from 'react'\n\n/**\n * Renders the thread messages with tool UIs.\n * Uses UnifiedToolFallback to handle all tool call states.\n */\nexport const PillMessageContent: FC = () => {\n\treturn (\n\t\t<ThreadPrimitive.Messages\n\t\t\tcomponents={{\n\t\t\t\t// Skip user messages in pill - we only want tool UIs from assistant\n\t\t\t\tUserMessage: () => null,\n\t\t\t\tAssistantMessage: PillAssistantMessage,\n\t\t\t}}\n\t\t/>\n\t)\n}\n\n/**\n * Assistant message renderer for the pill.\n * Renders tool calls via UnifiedToolFallback.\n * Text content is skipped here (handled by SummaryBlock).\n */\nconst PillAssistantMessage: FC = () => {\n\treturn (\n\t\t<MessagePrimitive.Root>\n\t\t\t<MessagePrimitive.Parts\n\t\t\t\tcomponents={{\n\t\t\t\t\t// Text is handled by SummaryBlock, so we skip it here\n\t\t\t\t\tText: () => null,\n\t\t\t\t\t// UnifiedToolFallback handles ALL tool states:\n\t\t\t\t\t// - Running: activity indicator\n\t\t\t\t\t// - Pending approval: approval dialog\n\t\t\t\t\t// - Completed: success with collapsible details\n\t\t\t\t\t// - Error: error display\n\t\t\t\t\t// - Denied: denied indicator\n\t\t\t\t\ttools: { Fallback: UnifiedToolFallback },\n\t\t\t\t}}\n\t\t\t/>\n\t\t</MessagePrimitive.Root>\n\t)\n}\n","/**\n * PillToolsSection Component\n *\n * A collapsible, scrollable container for tool UIs in the pill.\n * Shows a header with action count that expands/collapses the tool list.\n * Contains PillMessageContent which renders tools via UnifiedToolFallback.\n *\n * Auto-expands when a tool requires approval (HITL pattern).\n */\n'use client'\n\nimport { AlertTriangle, ChevronDown } from 'lucide-react'\nimport { useEffect, useState } from 'react'\n\nimport { useActions } from '../../hooks/useActions'\nimport { cn } from '../../lib/utils'\nimport { PillMessageContent } from './PillMessageContent'\n\nimport type { FC } from 'react'\n\nexport interface PillToolsSectionProps {\n\t/** Start collapsed (default: true) */\n\tdefaultCollapsed?: boolean\n\t/** Additional class name */\n\tclassName?: string\n\t/** Full-screen mode - larger height, starts expanded */\n\tisFullScreen?: boolean\n}\n\n/**\n * Collapsible section containing all tool UIs.\n * Shows \"Actions (completed/total)\" header with expand/collapse toggle.\n * Tool cards render in a scrollable container.\n *\n * Auto-expands when approval is needed for a destructive tool.\n */\nexport const PillToolsSection: FC<PillToolsSectionProps> = ({\n\tdefaultCollapsed = false,\n\tclassName,\n\tisFullScreen = false,\n}) => {\n\t// Start expanded in full-screen mode\n\tconst [isCollapsed, setIsCollapsed] = useState(isFullScreen ? false : defaultCollapsed)\n\tconst actions = useActions()\n\n\t// Count different statuses\n\tconst completedCount = actions.filter((a) => a.status === 'success').length\n\tconst runningCount = actions.filter((a) => a.status === 'running').length\n\tconst pendingCount = actions.filter((a) => a.status === 'pending').length\n\tconst totalCount = actions.length\n\n\t// Auto-expand when approval is needed\n\tuseEffect(() => {\n\t\tif (pendingCount > 0 && isCollapsed) {\n\t\t\tsetIsCollapsed(false)\n\t\t}\n\t}, [pendingCount, isCollapsed])\n\n\t// Don't render if no actions\n\tif (actions.length === 0) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<div className={cn('mt-1.5', className)}>\n\t\t\t{/* Header - compact, no background card */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setIsCollapsed(!isCollapsed)}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex w-full items-center justify-between',\n\t\t\t\t\t'px-1 py-1',\n\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t'hover:bg-white/5 rounded'\n\t\t\t\t)}\n\t\t\t\taria-expanded={!isCollapsed}\n\t\t\t>\n\t\t\t\t<div className=\"flex items-center gap-1.5\">\n\t\t\t\t\t<span className=\"text-xs font-medium text-white/70\">Tools</span>\n\t\t\t\t\t<span className=\"text-[11px] text-white/40\">\n\t\t\t\t\t\t{completedCount}/{totalCount}\n\t\t\t\t\t</span>\n\t\t\t\t\t{/* Pending approval indicator */}\n\t\t\t\t\t{pendingCount > 0 && (\n\t\t\t\t\t\t<span className=\"flex items-center gap-1 text-[11px] font-medium text-white/90\">\n\t\t\t\t\t\t\t<AlertTriangle className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t{pendingCount}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{/* Running indicator */}\n\t\t\t\t\t{runningCount > 0 && (\n\t\t\t\t\t\t<span className=\"flex items-center gap-1 text-[11px] text-white/60\">\n\t\t\t\t\t\t\t<span className=\"h-1.5 w-1.5 animate-pulse rounded-full bg-white/60\" />\n\t\t\t\t\t\t\t{runningCount}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<ChevronDown\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'h-3.5 w-3.5 transition-transform duration-200 text-white/40',\n\t\t\t\t\t\t!isCollapsed && 'rotate-180'\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</button>\n\n\t\t\t{/* Expandable content */}\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'grid transition-[grid-template-rows] duration-300 ease-out',\n\t\t\t\t\tisCollapsed ? 'grid-rows-[0fr]' : 'grid-rows-[1fr]'\n\t\t\t\t)}\n\t\t\t\taria-hidden={isCollapsed}\n\t\t\t>\n\t\t\t\t<div className=\"overflow-hidden\">\n\t\t\t\t\t{/* Scrollable tool cards - larger height in full-screen mode */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'mt-1 overflow-y-auto scrollbar-thin scroll-touch',\n\t\t\t\t\t\t\tisFullScreen ? 'max-h-[30vh]' : 'max-h-40 sm:max-h-32'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ touchAction: 'pan-y' }}\n\t\t\t\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t\t\t>\n\t\t\t\t\t\t<PillMessageContent />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default PillToolsSection\n","import { useEffect, useRef } from 'react'\n\nimport { cn } from '../lib/utils'\n\nimport type { HTMLAttributes } from 'react'\n\nexport type LiveWaveformProps = HTMLAttributes<HTMLDivElement> & {\n\tactive?: boolean\n\tprocessing?: boolean\n\tbarWidth?: number\n\tbarGap?: number\n\tbarRadius?: number\n\tbarColor?: string\n\tfadeEdges?: boolean\n\tfadeWidth?: number\n\theight?: string | number\n\tsensitivity?: number\n\tsmoothingTimeConstant?: number\n\tmode?: 'scrolling' | 'static'\n\t/** Manual audio level (0-1) instead of using microphone */\n\tmanualAudioLevel?: number\n}\n\nexport const LiveWaveform = ({\n\tactive = false,\n\tprocessing = false,\n\tbarWidth = 3,\n\tbarGap = 1,\n\tbarRadius = 1.5,\n\tbarColor,\n\tfadeEdges = true,\n\tfadeWidth = 24,\n\theight = 64,\n\tsensitivity = 1,\n\tmode = 'static',\n\tmanualAudioLevel,\n\tclassName,\n\t...props\n}: LiveWaveformProps) => {\n\tconst canvasRef = useRef<HTMLCanvasElement>(null)\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\tconst historyRef = useRef<number[]>([])\n\tconst _animationRef = useRef<number>(0)\n\tconst lastUpdateRef = useRef<number>(0)\n\tconst processingAnimationRef = useRef<number | null>(null)\n\tconst lastActiveDataRef = useRef<number[]>([])\n\tconst transitionProgressRef = useRef(0)\n\tconst staticBarsRef = useRef<number[]>([])\n\tconst needsRedrawRef = useRef(true)\n\tconst gradientCacheRef = useRef<CanvasGradient | null>(null)\n\tconst lastWidthRef = useRef(0)\n\n\tconst heightStyle = typeof height === 'number' ? `${height}px` : height\n\tconst historySize = 60\n\tconst updateRate = 30\n\n\t// Handle canvas resizing\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current\n\t\tconst container = containerRef.current\n\t\tif (!canvas || !container) return\n\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\tconst dpr = window.devicePixelRatio || 1\n\n\t\t\tcanvas.width = rect.width * dpr\n\t\t\tcanvas.height = rect.height * dpr\n\t\t\tcanvas.style.width = `${rect.width}px`\n\t\t\tcanvas.style.height = `${rect.height}px`\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (ctx) {\n\t\t\t\tctx.scale(dpr, dpr)\n\t\t\t}\n\n\t\t\tgradientCacheRef.current = null\n\t\t\tlastWidthRef.current = rect.width\n\t\t\tneedsRedrawRef.current = true\n\t\t})\n\n\t\tresizeObserver.observe(container)\n\t\treturn () => resizeObserver.disconnect()\n\t}, [])\n\n\t// Processing animation effect\n\tuseEffect(() => {\n\t\tif (processing && !active) {\n\t\t\tlet time = 0\n\t\t\ttransitionProgressRef.current = 0\n\n\t\t\tconst animateProcessing = () => {\n\t\t\t\ttime += 0.03\n\t\t\t\ttransitionProgressRef.current = Math.min(1, transitionProgressRef.current + 0.02)\n\n\t\t\t\tconst processingData: number[] = []\n\t\t\t\tconst barCount = Math.floor(\n\t\t\t\t\t(containerRef.current?.getBoundingClientRect().width || 200) / (barWidth + barGap)\n\t\t\t\t)\n\n\t\t\t\tif (mode === 'static') {\n\t\t\t\t\tconst halfCount = Math.floor(barCount / 2)\n\n\t\t\t\t\tfor (let i = 0; i < barCount; i++) {\n\t\t\t\t\t\tconst normalizedPosition = (i - halfCount) / halfCount\n\t\t\t\t\t\tconst centerWeight = 1 - Math.abs(normalizedPosition) * 0.4\n\n\t\t\t\t\t\tconst wave1 = Math.sin(time * 1.5 + normalizedPosition * 3) * 0.25\n\t\t\t\t\t\tconst wave2 = Math.sin(time * 0.8 - normalizedPosition * 2) * 0.2\n\t\t\t\t\t\tconst wave3 = Math.cos(time * 2 + normalizedPosition) * 0.15\n\t\t\t\t\t\tconst combinedWave = wave1 + wave2 + wave3\n\t\t\t\t\t\tconst processingValue = (0.2 + combinedWave) * centerWeight\n\n\t\t\t\t\t\tlet finalValue = processingValue\n\t\t\t\t\t\tif (lastActiveDataRef.current.length > 0 && transitionProgressRef.current < 1) {\n\t\t\t\t\t\t\tconst lastDataIndex = Math.min(i, lastActiveDataRef.current.length - 1)\n\t\t\t\t\t\t\tconst lastValue = lastActiveDataRef.current[lastDataIndex] || 0\n\t\t\t\t\t\t\tfinalValue =\n\t\t\t\t\t\t\t\tlastValue * (1 - transitionProgressRef.current) +\n\t\t\t\t\t\t\t\tprocessingValue * transitionProgressRef.current\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprocessingData.push(Math.max(0.05, Math.min(1, finalValue)))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i < barCount; i++) {\n\t\t\t\t\t\tconst normalizedPosition = (i - barCount / 2) / (barCount / 2)\n\t\t\t\t\t\tconst centerWeight = 1 - Math.abs(normalizedPosition) * 0.4\n\n\t\t\t\t\t\tconst wave1 = Math.sin(time * 1.5 + i * 0.15) * 0.25\n\t\t\t\t\t\tconst wave2 = Math.sin(time * 0.8 - i * 0.1) * 0.2\n\t\t\t\t\t\tconst wave3 = Math.cos(time * 2 + i * 0.05) * 0.15\n\t\t\t\t\t\tconst combinedWave = wave1 + wave2 + wave3\n\t\t\t\t\t\tconst processingValue = (0.2 + combinedWave) * centerWeight\n\n\t\t\t\t\t\tlet finalValue = processingValue\n\t\t\t\t\t\tif (lastActiveDataRef.current.length > 0 && transitionProgressRef.current < 1) {\n\t\t\t\t\t\t\tconst lastDataIndex = Math.floor((i / barCount) * lastActiveDataRef.current.length)\n\t\t\t\t\t\t\tconst lastValue = lastActiveDataRef.current[lastDataIndex] || 0\n\t\t\t\t\t\t\tfinalValue =\n\t\t\t\t\t\t\t\tlastValue * (1 - transitionProgressRef.current) +\n\t\t\t\t\t\t\t\tprocessingValue * transitionProgressRef.current\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprocessingData.push(Math.max(0.05, Math.min(1, finalValue)))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (mode === 'static') {\n\t\t\t\t\tstaticBarsRef.current = processingData\n\t\t\t\t} else {\n\t\t\t\t\thistoryRef.current = processingData\n\t\t\t\t}\n\n\t\t\t\tneedsRedrawRef.current = true\n\t\t\t\tprocessingAnimationRef.current = requestAnimationFrame(animateProcessing)\n\t\t\t}\n\n\t\t\tanimateProcessing()\n\n\t\t\treturn () => {\n\t\t\t\tif (processingAnimationRef.current) {\n\t\t\t\t\tcancelAnimationFrame(processingAnimationRef.current)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!active && !processing) {\n\t\t\tconst hasData =\n\t\t\t\tmode === 'static' ? staticBarsRef.current.length > 0 : historyRef.current.length > 0\n\n\t\t\tif (hasData) {\n\t\t\t\tlet fadeProgress = 0\n\t\t\t\tconst fadeToIdle = () => {\n\t\t\t\t\tfadeProgress += 0.03\n\t\t\t\t\tif (fadeProgress < 1) {\n\t\t\t\t\t\tif (mode === 'static') {\n\t\t\t\t\t\t\tstaticBarsRef.current = staticBarsRef.current.map(\n\t\t\t\t\t\t\t\t(value) => value * (1 - fadeProgress)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thistoryRef.current = historyRef.current.map((value) => value * (1 - fadeProgress))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tneedsRedrawRef.current = true\n\t\t\t\t\t\trequestAnimationFrame(fadeToIdle)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (mode === 'static') {\n\t\t\t\t\t\t\tstaticBarsRef.current = []\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thistoryRef.current = []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfadeToIdle()\n\t\t\t}\n\t\t}\n\t}, [processing, active, barWidth, barGap, mode])\n\n\t// Animation loop\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current\n\t\tif (!canvas) return\n\n\t\tconst ctx = canvas.getContext('2d')\n\t\tif (!ctx) return\n\n\t\tlet rafId: number\n\n\t\tconst animate = (currentTime: number) => {\n\t\t\tconst rect = canvas.getBoundingClientRect()\n\n\t\t\t// Update audio data if active\n\t\t\tif (active && currentTime - lastUpdateRef.current > updateRate) {\n\t\t\t\tlastUpdateRef.current = currentTime\n\n\t\t\t\t// Use manual audio level if provided\n\t\t\t\tif (manualAudioLevel !== undefined) {\n\t\t\t\t\tconst level = Math.max(0.05, Math.min(1, manualAudioLevel * sensitivity))\n\n\t\t\t\t\tif (mode === 'static') {\n\t\t\t\t\t\tconst barCount = Math.floor(rect.width / (barWidth + barGap))\n\t\t\t\t\t\tconst halfCount = Math.floor(barCount / 2)\n\t\t\t\t\t\tconst newBars: number[] = []\n\n\t\t\t\t\t\t// Create symmetric bars based on manual level\n\t\t\t\t\t\tfor (let i = halfCount - 1; i >= 0; i--) {\n\t\t\t\t\t\t\tconst distanceFromCenter = Math.abs(i - halfCount / 2) / (halfCount / 2)\n\t\t\t\t\t\t\tconst value = level * (1 - distanceFromCenter * 0.3)\n\t\t\t\t\t\t\tnewBars.push(Math.max(0.05, value))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (let i = 0; i < halfCount; i++) {\n\t\t\t\t\t\t\tconst distanceFromCenter = Math.abs(i - halfCount / 2) / (halfCount / 2)\n\t\t\t\t\t\t\tconst value = level * (1 - distanceFromCenter * 0.3)\n\t\t\t\t\t\t\tnewBars.push(Math.max(0.05, value))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstaticBarsRef.current = newBars\n\t\t\t\t\t\tlastActiveDataRef.current = newBars\n\t\t\t\t\t} else {\n\t\t\t\t\t\thistoryRef.current.push(level)\n\t\t\t\t\t\tlastActiveDataRef.current = [...historyRef.current]\n\n\t\t\t\t\t\tif (historyRef.current.length > historySize) {\n\t\t\t\t\t\t\thistoryRef.current.shift()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tneedsRedrawRef.current = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Only redraw if needed\n\t\t\tif (!needsRedrawRef.current && !active) {\n\t\t\t\trafId = requestAnimationFrame(animate)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tneedsRedrawRef.current = active\n\t\t\tctx.clearRect(0, 0, rect.width, rect.height)\n\n\t\t\tconst computedBarColor =\n\t\t\t\tbarColor ||\n\t\t\t\t(() => {\n\t\t\t\t\tconst style = getComputedStyle(canvas)\n\t\t\t\t\tconst color = style.color\n\t\t\t\t\treturn color || '#000'\n\t\t\t\t})()\n\n\t\t\tconst step = barWidth + barGap\n\t\t\tconst barCount = Math.floor(rect.width / step)\n\t\t\tconst centerY = rect.height / 2\n\n\t\t\t// Draw bars based on mode\n\t\t\tif (mode === 'static') {\n\t\t\t\tconst dataToRender = processing\n\t\t\t\t\t? staticBarsRef.current\n\t\t\t\t\t: active\n\t\t\t\t\t\t? staticBarsRef.current\n\t\t\t\t\t\t: staticBarsRef.current.length > 0\n\t\t\t\t\t\t\t? staticBarsRef.current\n\t\t\t\t\t\t\t: []\n\n\t\t\t\tfor (let i = 0; i < barCount && i < dataToRender.length; i++) {\n\t\t\t\t\tconst value = dataToRender[i] || 0.1\n\t\t\t\t\tconst x = i * step\n\t\t\t\t\tconst barHeight = Math.max(4, value * rect.height * 0.8)\n\t\t\t\t\tconst y = centerY - barHeight / 2\n\n\t\t\t\t\tctx.fillStyle = computedBarColor\n\t\t\t\t\tctx.globalAlpha = 0.4 + value * 0.6\n\n\t\t\t\t\tif (barRadius > 0) {\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.roundRect(x, y, barWidth, barHeight, barRadius)\n\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.fillRect(x, y, barWidth, barHeight)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Scrolling mode\n\t\t\t\tfor (let i = 0; i < barCount && i < historyRef.current.length; i++) {\n\t\t\t\t\tconst dataIndex = historyRef.current.length - 1 - i\n\t\t\t\t\tconst value = historyRef.current[dataIndex] || 0.1\n\t\t\t\t\tconst x = rect.width - (i + 1) * step\n\t\t\t\t\tconst barHeight = Math.max(4, value * rect.height * 0.8)\n\t\t\t\t\tconst y = centerY - barHeight / 2\n\n\t\t\t\t\tctx.fillStyle = computedBarColor\n\t\t\t\t\tctx.globalAlpha = 0.4 + value * 0.6\n\n\t\t\t\t\tif (barRadius > 0) {\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.roundRect(x, y, barWidth, barHeight, barRadius)\n\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.fillRect(x, y, barWidth, barHeight)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply edge fading\n\t\t\tif (fadeEdges && fadeWidth > 0 && rect.width > 0) {\n\t\t\t\tif (!gradientCacheRef.current || lastWidthRef.current !== rect.width) {\n\t\t\t\t\tconst gradient = ctx.createLinearGradient(0, 0, rect.width, 0)\n\t\t\t\t\tconst fadePercent = Math.min(0.3, fadeWidth / rect.width)\n\n\t\t\t\t\tgradient.addColorStop(0, 'rgba(255,255,255,1)')\n\t\t\t\t\tgradient.addColorStop(fadePercent, 'rgba(255,255,255,0)')\n\t\t\t\t\tgradient.addColorStop(1 - fadePercent, 'rgba(255,255,255,0)')\n\t\t\t\t\tgradient.addColorStop(1, 'rgba(255,255,255,1)')\n\n\t\t\t\t\tgradientCacheRef.current = gradient\n\t\t\t\t\tlastWidthRef.current = rect.width\n\t\t\t\t}\n\n\t\t\t\tctx.globalCompositeOperation = 'destination-out'\n\t\t\t\tctx.fillStyle = gradientCacheRef.current\n\t\t\t\tctx.fillRect(0, 0, rect.width, rect.height)\n\t\t\t\tctx.globalCompositeOperation = 'source-over'\n\t\t\t}\n\n\t\t\tctx.globalAlpha = 1\n\n\t\t\trafId = requestAnimationFrame(animate)\n\t\t}\n\n\t\trafId = requestAnimationFrame(animate)\n\n\t\treturn () => {\n\t\t\tif (rafId) {\n\t\t\t\tcancelAnimationFrame(rafId)\n\t\t\t}\n\t\t}\n\t}, [\n\t\tactive,\n\t\tprocessing,\n\t\tsensitivity,\n\t\tbarWidth,\n\t\tbarGap,\n\t\tbarRadius,\n\t\tbarColor,\n\t\tfadeEdges,\n\t\tfadeWidth,\n\t\tmode,\n\t\tmanualAudioLevel,\n\t\thistorySize,\n\t\tupdateRate,\n\t])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('relative h-full w-full', className)}\n\t\t\tref={containerRef}\n\t\t\tstyle={{ height: heightStyle }}\n\t\t\taria-label={\n\t\t\t\tactive ? 'Live audio waveform' : processing ? 'Processing audio' : 'Audio waveform idle'\n\t\t\t}\n\t\t\trole=\"img\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{!active && !processing && (\n\t\t\t\t<div className=\"border-muted-foreground/20 absolute top-1/2 right-0 left-0 -translate-y-1/2 border-t-2 border-dotted\" />\n\t\t\t)}\n\t\t\t<canvas className=\"block h-full w-full\" ref={canvasRef} />\n\t\t</div>\n\t)\n}\n","/**\n * PillVoiceApprovalBar Component\n *\n * Approval UI for voice mode. Shows when a destructive tool needs approval.\n * Audio is paused while waiting for the user to tap approve or deny.\n *\n * Features:\n * - Pauses audio playback when approval is pending\n * - Displays tool name and countdown timer\n * - Approve/Deny buttons\n * - Amber warning styling consistent with text mode approval\n * - Resumes audio after approval/denial\n */\n'use client'\n\nimport { AlertTriangle, Check, Loader2, Pause, X } from 'lucide-react'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useEffect, useState } from 'react'\n\nimport { humanizeToolName } from '../../lib/format'\nimport { cn } from '../../lib/utils'\nimport { useOptionalVoiceThread } from '../../providers/VoiceThreadBridge'\nimport { useOptionalVoiceToolApproval } from '../../providers/VoiceToolApprovalProvider'\n\nimport type { FC } from 'react'\n\n// Animation variants\nconst approvalBarVariants = {\n\thidden: {\n\t\topacity: 0,\n\t\theight: 0,\n\t\ty: -8,\n\t},\n\tvisible: {\n\t\topacity: 1,\n\t\theight: 'auto',\n\t\ty: 0,\n\t\ttransition: {\n\t\t\ttype: 'spring' as const,\n\t\t\tstiffness: 400,\n\t\t\tdamping: 30,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\theight: 0,\n\t\ty: -8,\n\t\ttransition: {\n\t\t\tduration: 0.15,\n\t\t},\n\t},\n}\n\nconst countdownVariants = {\n\tpulse: {\n\t\tscale: [1, 1.1, 1],\n\t\ttransition: {\n\t\t\tduration: 1,\n\t\t\trepeat: Infinity,\n\t\t},\n\t},\n}\n\nexport interface PillVoiceApprovalBarProps {\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Voice mode approval bar component.\n *\n * Shows when a destructive tool is waiting for approval in voice mode.\n * Pauses audio while waiting for approval, resumes after user responds.\n */\nexport const PillVoiceApprovalBar: FC<PillVoiceApprovalBarProps> = ({ className }) => {\n\tconst voiceThread = useOptionalVoiceThread()\n\tconst voiceApproval = useOptionalVoiceToolApproval()\n\tconst [isExecuting, setIsExecuting] = useState(false)\n\n\t// Pause audio when approval is pending, resume when resolved\n\tuseEffect(() => {\n\t\tif (voiceApproval?.pendingApproval && voiceThread) {\n\t\t\t// Pause audio when this component mounts (approval pending)\n\t\t\tvoiceThread.pauseAudio()\n\n\t\t\t// Resume audio when this component unmounts (approval resolved)\n\t\t\treturn () => {\n\t\t\t\tvoiceThread.resumeAudio()\n\t\t\t}\n\t\t}\n\t}, [voiceApproval?.pendingApproval, voiceThread])\n\n\t// Don't render if no pending approval\n\tif (!voiceApproval?.pendingApproval) {\n\t\treturn null\n\t}\n\n\tconst { pendingApproval, timeoutRemaining, approve, deny } = voiceApproval\n\tconst toolName = humanizeToolName(pendingApproval.toolName)\n\n\t// Handle approve button click\n\tconst handleApprove = () => {\n\t\tsetIsExecuting(true)\n\t\tapprove()\n\t}\n\n\t// Handle deny button click\n\tconst handleDeny = () => {\n\t\tdeny()\n\t}\n\n\treturn (\n\t\t<AnimatePresence>\n\t\t\t<motion.div\n\t\t\t\tclassName={cn('overflow-hidden', className)}\n\t\t\t\tvariants={approvalBarVariants}\n\t\t\t\tinitial=\"hidden\"\n\t\t\t\tanimate=\"visible\"\n\t\t\t\texit=\"exit\"\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex flex-col gap-2 rounded-xl px-4 py-3',\n\t\t\t\t\t\t'border border-amber-500/30 bg-amber-500/10'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{/* Header row: Warning icon, tool name, countdown */}\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<AlertTriangle className=\"h-4 w-4 flex-shrink-0 text-amber-500\" />\n\t\t\t\t\t\t<span className=\"min-w-0 flex-1 truncate text-sm text-white/90\">\n\t\t\t\t\t\t\t<span className=\"font-medium text-amber-400\">Approve</span> {toolName}?\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{/* Countdown timer */}\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium',\n\t\t\t\t\t\t\t\ttimeoutRemaining <= 10\n\t\t\t\t\t\t\t\t\t? 'bg-red-500/20 text-red-400'\n\t\t\t\t\t\t\t\t\t: 'bg-amber-500/20 text-amber-400'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tvariants={timeoutRemaining <= 10 ? countdownVariants : undefined}\n\t\t\t\t\t\t\tanimate={timeoutRemaining <= 10 ? 'pulse' : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{timeoutRemaining}\n\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Audio paused indicator */}\n\t\t\t\t\t<div className=\"flex items-center gap-1.5 text-xs text-white/50\">\n\t\t\t\t\t\t<Pause className=\"h-3 w-3\" />\n\t\t\t\t\t\t<span>Audio paused. Tap to approve or deny.</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Action buttons */}\n\t\t\t\t\t{isExecuting ? (\n\t\t\t\t\t\t<div className=\"flex items-center justify-center gap-2 rounded-lg bg-blue-500/10 px-3 py-2 text-sm text-blue-400\">\n\t\t\t\t\t\t\t<Loader2 className=\"h-4 w-4 animate-spin\" />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tExecuting <strong>{toolName}</strong>...\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleDeny}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t\t\t\t'border border-zinc-600 text-white/70',\n\t\t\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\t\t\t'hover:border-red-500/50 hover:bg-red-500/20 hover:text-red-400',\n\t\t\t\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<X className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\tDeny\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleApprove}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t\t\t\t'border border-amber-500/50 bg-amber-500/20 text-amber-400',\n\t\t\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\t\t\t'hover:border-amber-500 hover:bg-amber-500/30',\n\t\t\t\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Check className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\tApprove\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</motion.div>\n\t\t</AnimatePresence>\n\t)\n}\n\nexport default PillVoiceApprovalBar\n","'use client'\n\nimport { Mic, MicOff, PhoneOff } from 'lucide-react'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useCallback } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { useOptionalVoiceThread } from '../../providers/VoiceThreadBridge'\nimport { useOptionalVoiceToolApproval } from '../../providers/VoiceToolApprovalProvider'\nimport { LiveWaveform } from '../live-waveform'\nimport { PillVoiceApprovalBar } from './PillVoiceApprovalBar'\n\nimport type { FC } from 'react'\nimport type { ToolBorderStatus } from './ToolStatusBorder'\n\ninterface PillVoiceProps {\n\t/** Callback when voice mode ends */\n\tonEnd?: () => void\n\t/** Whether to show a compact version */\n\tcompact?: boolean\n\t/** Additional class name */\n\tclassName?: string\n}\n\n// Animation variants for the voice UI\nconst voiceVariants = {\n\thidden: {\n\t\topacity: 0,\n\t\tscale: 0.95,\n\t\ty: 4,\n\t},\n\tvisible: {\n\t\topacity: 1,\n\t\tscale: 1,\n\t\ty: 0,\n\t\ttransition: {\n\t\t\ttype: 'spring' as const,\n\t\t\tstiffness: 400,\n\t\t\tdamping: 30,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\tscale: 0.95,\n\t\ty: -4,\n\t\ttransition: {\n\t\t\tduration: 0.15,\n\t\t},\n\t},\n}\n\n// Button animation\nconst buttonVariants = {\n\tidle: { scale: 1 },\n\thover: { scale: 1.05 },\n\ttap: { scale: 0.95 },\n}\n\n// Transcript animation\nconst transcriptVariants = {\n\thidden: { opacity: 0, height: 0 },\n\tvisible: {\n\t\topacity: 1,\n\t\theight: 'auto',\n\t\ttransition: {\n\t\t\ttype: 'spring' as const,\n\t\t\tstiffness: 300,\n\t\t\tdamping: 25,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\theight: 0,\n\t\ttransition: {\n\t\t\tduration: 0.1,\n\t\t},\n\t},\n}\n\n/**\n * Convert voice mode tool call status to border status\n */\nexport function voiceToolCallToBorderStatus(toolCall?: {\n\tstatus: 'started' | 'completed'\n\terror?: string\n}): ToolBorderStatus {\n\tif (!toolCall) return 'idle'\n\tif (toolCall.status === 'started') return 'calling'\n\tif (toolCall.status === 'completed') {\n\t\treturn toolCall.error ? 'error' : 'success'\n\t}\n\treturn 'idle'\n}\n\n/**\n * Compact voice mode UI for the pill.\n * Shows waveforms, controls, and transcript preview.\n * Uses motion animations for smooth transitions.\n *\n * Uses VoiceThreadBridge for voice state (integrated with thread).\n */\nexport const PillVoice: FC<PillVoiceProps> = ({ onEnd, compact = false, className }) => {\n\tconst voiceThread = useOptionalVoiceThread()\n\tconst voiceToolApproval = useOptionalVoiceToolApproval()\n\n\tconst handleEnd = useCallback(() => {\n\t\t// Clear any pending voice approvals\n\t\tvoiceToolApproval?.clearPendingApproval()\n\n\t\t// Stop the voice session\n\t\tvoiceThread?.stop()\n\t\tonEnd?.()\n\t}, [voiceThread, voiceToolApproval, onEnd])\n\n\tconst handleToggleMute = useCallback(() => {\n\t\tvoiceThread?.toggleMute()\n\t}, [voiceThread])\n\n\t// Don't render if no voice context or not active/connecting/error\n\tif (\n\t\t!voiceThread ||\n\t\t(!voiceThread.isActive && !voiceThread.isConnecting && !voiceThread.isError)\n\t) {\n\t\treturn null\n\t}\n\n\tconst { isActive, isConnecting, isMuted, isError, error, audioLevel, transcript, toolCall } =\n\t\tvoiceThread\n\n\t// Check if we're waiting for approval\n\tconst isWaitingForApproval = voiceToolApproval?.isWaitingForApproval ?? false\n\tconst micLevel = audioLevel?.micLevel ?? 0\n\tconst speakerLevel = audioLevel?.speakerLevel ?? 0\n\n\treturn (\n\t\t<motion.div\n\t\t\tclassName={cn('flex flex-col gap-3', className)}\n\t\t\tvariants={voiceVariants}\n\t\t\tinitial=\"hidden\"\n\t\t\tanimate=\"visible\"\n\t\t\texit=\"exit\"\n\t\t>\n\t\t\t{/* Waveforms row */}\n\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t{/* User mic indicator */}\n\t\t\t\t<div className=\"flex flex-1 items-center gap-2\">\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-11 w-11 shrink-0 items-center justify-center rounded-full sm:h-7 sm:w-7',\n\t\t\t\t\t\t\tisMuted ? 'bg-red-500/20 text-red-400' : 'bg-white/10 text-white/80'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tanimate={{ opacity: isMuted ? 0.6 : 1 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isMuted ? (\n\t\t\t\t\t\t\t<MicOff className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Mic className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</motion.div>\n\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn('h-5 flex-1', compact ? 'max-w-24 sm:max-w-16' : 'max-w-32 sm:max-w-24')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LiveWaveform\n\t\t\t\t\t\t\tactive={isActive && !isMuted}\n\t\t\t\t\t\t\tprocessing={isConnecting}\n\t\t\t\t\t\t\tmanualAudioLevel={micLevel}\n\t\t\t\t\t\t\tbarWidth={2}\n\t\t\t\t\t\t\tbarGap={1}\n\t\t\t\t\t\t\tbarRadius={1}\n\t\t\t\t\t\t\tbarColor=\"rgba(255, 255, 255, 0.7)\"\n\t\t\t\t\t\t\theight={20}\n\t\t\t\t\t\t\tmode=\"static\"\n\t\t\t\t\t\t\tsensitivity={2.0}\n\t\t\t\t\t\t\tfadeEdges={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Separator */}\n\t\t\t\t<div className=\"h-5 w-px bg-white/10\" />\n\n\t\t\t\t{/* Agent speaker indicator */}\n\t\t\t\t<div className=\"flex flex-1 items-center gap-2\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn('h-5 flex-1', compact ? 'max-w-24 sm:max-w-16' : 'max-w-32 sm:max-w-24')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LiveWaveform\n\t\t\t\t\t\t\tactive={isActive}\n\t\t\t\t\t\t\tprocessing={isConnecting}\n\t\t\t\t\t\t\tmanualAudioLevel={speakerLevel}\n\t\t\t\t\t\t\tbarWidth={2}\n\t\t\t\t\t\t\tbarGap={1}\n\t\t\t\t\t\t\tbarRadius={1}\n\t\t\t\t\t\t\tbarColor=\"rgba(255, 255, 255, 0.4)\"\n\t\t\t\t\t\t\theight={20}\n\t\t\t\t\t\t\tmode=\"static\"\n\t\t\t\t\t\t\tsensitivity={2.0}\n\t\t\t\t\t\t\tfadeEdges={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Agent avatar */}\n\t\t\t\t\t<div className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-white/10 sm:h-7 sm:w-7\">\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tclassName=\"h-2.5 w-2.5 rounded-full bg-green-400\"\n\t\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\t\tscale: speakerLevel > 0.1 ? [1, 1.2, 1] : 1,\n\t\t\t\t\t\t\t\topacity: speakerLevel > 0.1 ? 1 : 0.5,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ttransition={{ duration: 0.2 }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Separator */}\n\t\t\t\t<div className=\"h-5 w-px bg-white/10\" />\n\n\t\t\t\t{/* Controls */}\n\t\t\t\t<div className=\"flex shrink-0 items-center gap-2 sm:gap-1.5\">\n\t\t\t\t\t{/* Mute button */}\n\t\t\t\t\t<motion.button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleToggleMute}\n\t\t\t\t\t\tdisabled={!isActive}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-11 w-11 items-center justify-center rounded-full sm:h-7 sm:w-7',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisMuted\n\t\t\t\t\t\t\t\t? 'bg-red-500/20 text-red-400 hover:bg-red-500/30'\n\t\t\t\t\t\t\t\t: 'bg-white/10 text-white/70 hover:bg-white/20 hover:text-white'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tvariants={buttonVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\twhileHover=\"hover\"\n\t\t\t\t\t\twhileTap=\"tap\"\n\t\t\t\t\t\taria-label={isMuted ? 'Unmute microphone' : 'Mute microphone'}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isMuted ? (\n\t\t\t\t\t\t\t<MicOff className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Mic className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</motion.button>\n\n\t\t\t\t\t{/* End button */}\n\t\t\t\t\t<motion.button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleEnd}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-11 w-11 items-center justify-center rounded-full sm:h-7 sm:w-7',\n\t\t\t\t\t\t\t'bg-red-500/20 text-red-400',\n\t\t\t\t\t\t\t'hover:bg-red-500/30 hover:text-red-300',\n\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tvariants={buttonVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\twhileHover=\"hover\"\n\t\t\t\t\t\twhileTap=\"tap\"\n\t\t\t\t\t\taria-label=\"End voice session\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<PhoneOff className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t</motion.button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Voice Tool Approval Bar - shows when a destructive tool needs approval */}\n\t\t\t<AnimatePresence>{isWaitingForApproval && <PillVoiceApprovalBar />}</AnimatePresence>\n\n\t\t\t{/* Tool call indicator - only show when NOT waiting for approval */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{toolCall && !isWaitingForApproval && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex max-w-full items-center gap-2 rounded-full px-3 py-1.5',\n\t\t\t\t\t\t\t'text-xs',\n\t\t\t\t\t\t\ttoolCall.status === 'started' && 'bg-blue-500/10 text-blue-400',\n\t\t\t\t\t\t\ttoolCall.status === 'completed' &&\n\t\t\t\t\t\t\t\t!toolCall.error &&\n\t\t\t\t\t\t\t\t'bg-green-500/10 text-green-400',\n\t\t\t\t\t\t\ttoolCall.status === 'completed' && toolCall.error && 'bg-red-500/10 text-red-400'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tinitial={{ opacity: 0, y: -4 }}\n\t\t\t\t\t\tanimate={{ opacity: 1, y: 0 }}\n\t\t\t\t\t\texit={{ opacity: 0, y: -4 }}\n\t\t\t\t\t\ttransition={{ type: 'spring', stiffness: 400, damping: 30 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<motion.span\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'h-1.5 w-1.5 shrink-0 rounded-full',\n\t\t\t\t\t\t\t\ttoolCall.status === 'started' && 'bg-blue-500',\n\t\t\t\t\t\t\t\ttoolCall.status === 'completed' && !toolCall.error && 'bg-green-500',\n\t\t\t\t\t\t\t\ttoolCall.status === 'completed' && toolCall.error && 'bg-red-500'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tanimate={toolCall.status === 'started' ? { opacity: [1, 0.5, 1] } : {}}\n\t\t\t\t\t\t\ttransition={{ duration: 0.8, repeat: Infinity }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<span className=\"min-w-0 truncate\">{toolCall.toolName}</span>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Transcript preview */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{transcript && transcript.text && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName=\"overflow-hidden\"\n\t\t\t\t\t\tvariants={transcriptVariants}\n\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\texit=\"exit\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'rounded-lg px-3 py-2 text-xs',\n\t\t\t\t\t\t\t\ttranscript.type === 'user'\n\t\t\t\t\t\t\t\t\t? 'bg-white/10 text-white/80'\n\t\t\t\t\t\t\t\t\t: 'bg-white/5 text-white/60'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"mr-1.5 shrink-0 text-white/40\">\n\t\t\t\t\t\t\t\t{transcript.type === 'user' ? 'You:' : 'Agent:'}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span className={cn('line-clamp-3', !transcript.isDone && 'animate-pulse')}>\n\t\t\t\t\t\t\t\t{transcript.text}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Connecting state */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{isConnecting && !isActive && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName=\"flex items-center justify-center gap-2 py-2 text-xs text-white/50\"\n\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<motion.span\n\t\t\t\t\t\t\tclassName=\"h-1.5 w-1.5 rounded-full bg-amber-500\"\n\t\t\t\t\t\t\tanimate={{ opacity: [1, 0.5, 1] }}\n\t\t\t\t\t\t\ttransition={{ duration: 0.8, repeat: Infinity }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<span>Connecting...</span>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Error state */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{isError && error && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2 text-xs text-red-400\"\n\t\t\t\t\t\tinitial={{ opacity: 0, y: -4 }}\n\t\t\t\t\t\tanimate={{ opacity: 1, y: 0 }}\n\t\t\t\t\t\texit={{ opacity: 0, y: -4 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<span className=\"h-1.5 w-1.5 shrink-0 rounded-full bg-red-500\" />\n\t\t\t\t\t\t<span className=\"line-clamp-2\">{error}</span>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleEnd}\n\t\t\t\t\t\t\tclassName=\"ml-auto shrink-0 text-red-300 hover:text-red-200\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tDismiss\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\t\t</motion.div>\n\t)\n}\n\n/**\n * Hook to get voice border status for the pill container\n */\nexport function useVoiceBorderStatus(): ToolBorderStatus {\n\tconst voiceThread = useOptionalVoiceThread()\n\n\tif (!voiceThread) return 'idle'\n\n\treturn voiceToolCallToBorderStatus(voiceThread.toolCall)\n}\n\nexport default PillVoice\n","/**\n * PromptBadge\n *\n * Intercom-style floating prompt bubbles that appear above the collapsed pill.\n * Shows up to MAX_PROMPT_BUBBLES in a triangular layout with staggered animations.\n *\n * Accessibility:\n * - Focus-visible rings for keyboard navigation\n * - Screen reader live region announces suggestions\n * - Touch-friendly dismiss targets on mobile\n */\nimport { X } from 'lucide-react'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useCallback, useState } from 'react'\n\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport { MAX_PROMPT_BUBBLES } from '../../lib/constants'\nimport { cn } from '../../lib/utils'\n\nimport type { Prompt } from '@mcp-b/cloud-mirror-types'\nimport type { Variants } from 'motion/react'\nimport type { FC, MouseEvent } from 'react'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PromptBadgeProps {\n\t/** Available prompts to display */\n\tprompts: Prompt[]\n\t/** Callback when a prompt is selected */\n\tonSelect: (prompt: Prompt) => void\n\t/** Additional class name */\n\tclassName?: string\n}\n\n// ============================================================================\n// Animation Configuration\n// ============================================================================\n\n/** Stagger timing for bubble animations (seconds) */\nconst STAGGER_DELAY = 0.08\nconst STAGGER_DELAY_INITIAL = 0.05\nconst STAGGER_DELAY_EXIT = 0.03\n\n/** Container animation variants for staggered children */\nconst containerVariants: Variants = {\n\thidden: { opacity: 0 },\n\tvisible: {\n\t\topacity: 1,\n\t\ttransition: {\n\t\t\tstaggerChildren: STAGGER_DELAY,\n\t\t\tdelayChildren: STAGGER_DELAY_INITIAL,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\ttransition: {\n\t\t\tstaggerChildren: STAGGER_DELAY_EXIT,\n\t\t\tstaggerDirection: -1,\n\t\t},\n\t},\n}\n\n/** Individual bubble animation variants */\nconst bubbleVariants: Variants = {\n\thidden: { opacity: 0, y: 10, scale: 0.9 },\n\tvisible: {\n\t\topacity: 1,\n\t\ty: 0,\n\t\tscale: 1,\n\t\ttransition: { type: 'spring', stiffness: 400, damping: 25 },\n\t},\n\texit: { opacity: 0, y: 5, scale: 0.95, transition: { duration: 0.1 } },\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\n/** Bubble button styles */\nconst bubbleStyles = cn(\n\t'flex items-center px-3 py-1.5',\n\t'bg-white dark:bg-zinc-800',\n\t'rounded-full',\n\t'shadow-lg shadow-black/10 dark:shadow-black/30',\n\t'border border-zinc-200/80 dark:border-zinc-700/80',\n\t'text-sm text-zinc-700 dark:text-zinc-200',\n\t'hover:bg-zinc-50 dark:hover:bg-zinc-700',\n\t'transition-colors duration-100',\n\t'whitespace-nowrap',\n\t// Focus state for keyboard navigation\n\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1'\n)\n\n/** Dismiss badge base styles (shared between mobile and desktop) */\nconst dismissBadgeBaseStyles = cn(\n\t'absolute -top-1.5 -right-1.5',\n\t'flex items-center justify-center',\n\t'rounded-full',\n\t'bg-zinc-100 dark:bg-zinc-700',\n\t'border border-zinc-200 dark:border-zinc-600',\n\t'text-zinc-400 dark:text-zinc-400',\n\t'hover:bg-zinc-200 dark:hover:bg-zinc-600',\n\t'hover:text-zinc-600 dark:hover:text-zinc-200',\n\t'shadow-sm',\n\t'transition-all duration-150',\n\t// Focus state for keyboard navigation\n\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500'\n)\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Floating prompt bubbles above the pill.\n * Positioned absolutely above parent - parent should be relative.\n */\nexport const PromptBadge: FC<PromptBadgeProps> = ({ prompts, onSelect, className }) => {\n\tconst [isDismissed, setIsDismissed] = useState(false)\n\tconst { isMobile } = useMobileDetect()\n\n\tconst handleSelect = useCallback(\n\t\t(prompt: Prompt) => {\n\t\t\tonSelect(prompt)\n\t\t},\n\t\t[onSelect]\n\t)\n\n\tconst handleDismiss = useCallback((e: MouseEvent) => {\n\t\te.stopPropagation()\n\t\tsetIsDismissed(true)\n\t}, [])\n\n\t// Early return if no prompts or dismissed\n\tif (prompts.length === 0 || isDismissed) {\n\t\treturn null\n\t}\n\n\t// Take up to MAX_PROMPT_BUBBLES prompts\n\tconst visiblePrompts = prompts.slice(0, MAX_PROMPT_BUBBLES)\n\n\t// Dynamic dismiss badge styles based on device type\n\tconst dismissBadgeStyles = cn(\n\t\tdismissBadgeBaseStyles,\n\t\t// Size: 24px on mobile (WCAG AA), 16px on desktop\n\t\tisMobile ? 'w-6 h-6' : 'w-4 h-4',\n\t\t// Visibility: always visible on mobile, hover-only on desktop\n\t\tisMobile\n\t\t\t? 'opacity-100 scale-100'\n\t\t\t: 'opacity-0 group-hover:opacity-100 scale-75 group-hover:scale-100'\n\t)\n\n\treturn (\n\t\t<div className={cn('absolute bottom-full left-1/2 -translate-x-1/2 mb-3 z-20', className)}>\n\t\t\t{/* Screen reader announcement */}\n\t\t\t<div role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n\t\t\t\t{visiblePrompts.length} suggestion{visiblePrompts.length !== 1 ? 's' : ''} available\n\t\t\t</div>\n\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t<motion.div\n\t\t\t\t\tkey=\"bubbles\"\n\t\t\t\t\tvariants={containerVariants}\n\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\texit=\"exit\"\n\t\t\t\t\tclassName=\"flex items-end gap-2\"\n\t\t\t\t\trole=\"group\"\n\t\t\t\t\taria-label=\"Suggested prompts\"\n\t\t\t\t>\n\t\t\t\t\t{visiblePrompts.map((prompt, index) => {\n\t\t\t\t\t\t// Triangular offset: middle bubble (index 1) is raised when showing 3 bubbles\n\t\t\t\t\t\tconst isMiddleBubble = visiblePrompts.length === 3 && index === 1\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div key={prompt.name} className={cn('group relative', isMiddleBubble && 'mb-3')}>\n\t\t\t\t\t\t\t\t<motion.button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariants={bubbleVariants}\n\t\t\t\t\t\t\t\t\tonClick={() => handleSelect(prompt)}\n\t\t\t\t\t\t\t\t\tclassName={bubbleStyles}\n\t\t\t\t\t\t\t\t\ttitle={prompt.description || prompt.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span>{prompt.name}</span>\n\t\t\t\t\t\t\t\t</motion.button>\n\n\t\t\t\t\t\t\t\t{/* Dismiss badge - always visible on mobile, hover on desktop */}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={handleDismiss}\n\t\t\t\t\t\t\t\t\tclassName={dismissBadgeStyles}\n\t\t\t\t\t\t\t\t\taria-label=\"Dismiss suggestions\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X size={isMobile ? 12 : 10} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t</motion.div>\n\t\t\t</AnimatePresence>\n\t\t</div>\n\t)\n}\n\nexport default PromptBadge\n","/**\n * PromptSuggestions\n *\n * Inline prompt suggestions shown inside the expanded pill.\n * Compact horizontal scrollable list of prompt chips.\n */\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useCallback, useRef } from 'react'\n\nimport { cn } from '../../lib/utils'\n\nimport type { Prompt } from '@mcp-b/cloud-mirror-types'\nimport type { FC } from 'react'\n\nexport interface PromptSuggestionsProps {\n\t/** Available prompts to display */\n\tprompts: Prompt[]\n\t/** Callback when a prompt is selected */\n\tonSelect: (prompt: Prompt) => void\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Inline prompt suggestions for the expanded pill.\n * Horizontally scrollable list of compact prompt chips.\n */\nexport const PromptSuggestions: FC<PromptSuggestionsProps> = ({ prompts, onSelect, className }) => {\n\tconst scrollRef = useRef<HTMLDivElement>(null)\n\n\tconst handleClick = useCallback(\n\t\t(prompt: Prompt) => {\n\t\t\tonSelect(prompt)\n\t\t},\n\t\t[onSelect]\n\t)\n\n\tif (prompts.length === 0) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<motion.div\n\t\t\tinitial={{ opacity: 0, height: 0 }}\n\t\t\tanimate={{ opacity: 1, height: 'auto' }}\n\t\t\texit={{ opacity: 0, height: 0 }}\n\t\t\tclassName={cn('overflow-hidden', className)}\n\t\t>\n\t\t\t<div\n\t\t\t\tref={scrollRef}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex gap-2 overflow-x-auto scrollbar-hide',\n\t\t\t\t\t'pb-1 -mb-1' // Padding for focus ring visibility\n\t\t\t\t)}\n\t\t\t\t// Allow horizontal scrolling within draggable parent\n\t\t\t\tstyle={{ touchAction: 'pan-x' }}\n\t\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t>\n\t\t\t\t<AnimatePresence mode=\"popLayout\">\n\t\t\t\t\t{prompts.map((prompt, index) => (\n\t\t\t\t\t\t<motion.button\n\t\t\t\t\t\t\tkey={prompt.name}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\t\t\t\t\texit={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\t\ttransition={{\n\t\t\t\t\t\t\t\ttype: 'spring',\n\t\t\t\t\t\t\t\tstiffness: 400,\n\t\t\t\t\t\t\t\tdamping: 25,\n\t\t\t\t\t\t\t\tdelay: index * 0.03,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={() => handleClick(prompt)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t\t'px-2.5 py-1 rounded-full',\n\t\t\t\t\t\t\t\t'bg-white/10 hover:bg-white/20',\n\t\t\t\t\t\t\t\t'text-white/80 hover:text-white',\n\t\t\t\t\t\t\t\t'text-xs font-medium',\n\t\t\t\t\t\t\t\t'border border-white/10 hover:border-white/20',\n\t\t\t\t\t\t\t\t'transition-all duration-150',\n\t\t\t\t\t\t\t\t'cursor-pointer',\n\t\t\t\t\t\t\t\t'whitespace-nowrap'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\ttitle={prompt.description || prompt.name}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{prompt.name}\n\t\t\t\t\t\t</motion.button>\n\t\t\t\t\t))}\n\t\t\t\t</AnimatePresence>\n\t\t\t</div>\n\t\t</motion.div>\n\t)\n}\n\nexport default PromptSuggestions\n","/**\n * StreamingResponse Component\n *\n * Shows the streaming text response from the agent as it's being generated.\n * This provides real-time visibility into what the agent is writing,\n * rather than waiting for the complete response.\n *\n * Features:\n * - Shows text as it streams in\n * - Typing cursor animation\n * - Compact, scrollable container\n * - Fades in/out smoothly\n */\n'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { PillMarkdown } from './PillMarkdown'\n\nimport type { FC } from 'react'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface TextPart {\n\ttype: 'text'\n\ttext: string\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to get the current streaming text from the thread.\n * Returns null if not currently streaming or no text content.\n */\nexport function useStreamingText(): string | null {\n\tconst messages = useThread((thread) => thread.messages)\n\tconst isRunning = useThread((thread) => thread.isRunning)\n\n\treturn useMemo(() => {\n\t\tif (!isRunning) return null\n\n\t\t// Find the last assistant message\n\t\tconst lastAssistantMessage = messages\n\t\t\t? [...messages].reverse().find((m) => m.role === 'assistant')\n\t\t\t: null\n\n\t\tif (!lastAssistantMessage) return null\n\n\t\t// Get text parts\n\t\tconst textParts = lastAssistantMessage.content.filter(\n\t\t\t(part): part is TextPart => part.type === 'text'\n\t\t)\n\t\tconst lastText = textParts.at(-1)?.text\n\n\t\t// Only return if there's actual text content\n\t\tif (!lastText || lastText.trim().length === 0) return null\n\n\t\treturn lastText\n\t}, [messages, isRunning])\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface StreamingResponseProps {\n\t/** Maximum height before scrolling (ignored when isFullScreen) */\n\tmaxHeight?: string\n\t/** Additional class name */\n\tclassName?: string\n\t/** Full-screen mode - larger text, no height constraints (parent handles scrolling) */\n\tisFullScreen?: boolean\n}\n\n/**\n * Displays the streaming response text as it's being generated.\n * Shows a typing cursor and scrolls to keep latest content visible.\n */\nexport const StreamingResponse: FC<StreamingResponseProps> = ({\n\tmaxHeight = '8rem',\n\tclassName,\n\tisFullScreen = false,\n}) => {\n\tconst streamingText = useStreamingText()\n\n\tif (!streamingText) return null\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'rounded-lg bg-white/5 border border-white/10 p-3',\n\t\t\t\t'overflow-y-auto scrollbar-thin scroll-touch',\n\t\t\t\t// Bottom margin for spacing from tool section\n\t\t\t\t'mb-1.5',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={isFullScreen ? undefined : { maxHeight }}\n\t\t>\n\t\t\t<div className=\"relative\">\n\t\t\t\t<PillMarkdown content={streamingText} className=\"text-white/90\" compact={!isFullScreen} />\n\t\t\t\t{/* Typing cursor */}\n\t\t\t\t<span className=\"inline-block w-0.5 h-4 bg-blue-400 ml-0.5 animate-pulse align-middle\" />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default StreamingResponse\n","'use client'\n\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { cn } from '../../lib/utils'\n\nimport type { FC, ReactNode } from 'react'\n\n// Minimalist: only idle, calling, and error states\n// Success is the default - no special treatment needed\nexport type ToolBorderStatus = 'idle' | 'calling' | 'success' | 'error'\n\ninterface ToolStatusBorderProps {\n\tstatus: ToolBorderStatus\n\tchildren: ReactNode\n\tclassName?: string\n\tborderRadius?: string\n}\n\n// Animation variants for the border glow\nconst borderVariants = {\n\tidle: {\n\t\topacity: 0,\n\t\tscale: 1,\n\t},\n\tcalling: {\n\t\topacity: 1,\n\t\tscale: 1,\n\t\ttransition: {\n\t\t\topacity: { duration: 0.15 },\n\t\t},\n\t},\n\terror: {\n\t\topacity: 1,\n\t\tscale: 1,\n\t\ttransition: {\n\t\t\topacity: { duration: 0.1 },\n\t\t},\n\t},\n}\n\n// Subtle shake animation for errors only\nconst shakeAnimation = {\n\tx: [0, -2, 2, -2, 2, 0],\n\ttransition: {\n\t\tduration: 0.3,\n\t\tease: [0.25, 0.1, 0.25, 1] as const,\n\t},\n}\n\n/**\n * Minimal animated border for tool execution status.\n *\n * - idle/success: clean, no border (success is the default state)\n * - calling: subtle animated gradient\n * - error: brief red flash with shake\n */\nexport const ToolStatusBorder: FC<ToolStatusBorderProps> = ({\n\tstatus,\n\tchildren,\n\tclassName,\n\tborderRadius = '20px',\n}) => {\n\t// Treat success as idle - no special visual treatment\n\tconst effectiveStatus = status === 'success' ? 'idle' : status\n\n\treturn (\n\t\t<motion.div\n\t\t\tclassName={cn('relative', className)}\n\t\t\tanimate={effectiveStatus === 'error' ? shakeAnimation : undefined}\n\t\t>\n\t\t\t{/* Animated border layer - only for calling and error */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{effectiveStatus !== 'idle' && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'absolute -inset-[1px] pointer-events-none',\n\t\t\t\t\t\t\teffectiveStatus === 'calling' && 'tool-border-calling',\n\t\t\t\t\t\t\teffectiveStatus === 'error' && 'tool-border-error'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ borderRadius }}\n\t\t\t\t\t\tvariants={borderVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\tanimate={effectiveStatus}\n\t\t\t\t\t\texit={{ opacity: 0, transition: { duration: 0.15 } }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Inner content container - no ring for cleaner look */}\n\t\t\t<div className=\"relative\" style={{ borderRadius }}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</motion.div>\n\t)\n}\n\n/**\n * Hook to manage tool border status based on actions.\n * Minimalist approach: success returns to idle immediately.\n */\nexport function useToolBorderStatus(\n\thasRunningAction: boolean,\n\tlastActionStatus?: 'success' | 'error' | null\n): ToolBorderStatus {\n\tconst [status, setStatus] = useState<ToolBorderStatus>('idle')\n\tconst timeoutRef = useRef<NodeJS.Timeout | null>(null)\n\n\tuseEffect(() => {\n\t\tif (timeoutRef.current) {\n\t\t\tclearTimeout(timeoutRef.current)\n\t\t\ttimeoutRef.current = null\n\t\t}\n\n\t\tif (hasRunningAction) {\n\t\t\tsetStatus('calling')\n\t\t} else if (lastActionStatus === 'error') {\n\t\t\tsetStatus('error')\n\t\t\t// Brief error flash, then back to idle\n\t\t\ttimeoutRef.current = setTimeout(() => {\n\t\t\t\tsetStatus('idle')\n\t\t\t}, 400)\n\t\t} else {\n\t\t\t// Success or no action = idle (clean state)\n\t\t\tsetStatus('idle')\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (timeoutRef.current) {\n\t\t\t\tclearTimeout(timeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [hasRunningAction, lastActionStatus])\n\n\treturn status\n}\n","'use client'\n\nimport { ThreadPrimitive, useComposerRuntime, useThreadRuntime } from '@assistant-ui/react'\nimport { Expand, GripHorizontal, Minimize, X } from 'lucide-react'\nimport { AnimatePresence, motion, useDragControls } from 'motion/react'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { useAgent } from '../../core/hooks/useAgent'\nimport { useOptionalAgentUI } from '../../core/providers/AgentUIProvider'\nimport { useKeyboardAware } from '../../hooks/useKeyboardAware'\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport { useHasPendingToolCalls, usePendingToolCalls } from '../../hooks/usePendingToolCalls'\nimport { usePinchGesture } from '../../hooks/usePinchGesture'\nimport {\n\tARIA_LABELS,\n\tAUTO_COLLAPSE_TIMEOUT_MS,\n\tdebugLog,\n\tDRAG_OPACITY,\n\tGESTURE_CONFIG,\n\tKEYBOARD_GAP_PX,\n\tPILL_BORDER_RADIUS,\n} from '../../lib/constants'\nimport { formatToolDenialWithReason } from '../../lib/format'\nimport { resolvePendingToolCall } from '../../lib/thread-utils'\nimport { cn } from '../../lib/utils'\nimport { ActivityIndicator } from './ActivityIndicator'\nimport { ApprovalModeIndicator } from './ApprovalModeToggle'\nimport { IdleIndicator } from './CurrentActivity'\nimport { ElicitationButtonBar } from './ElicitationButtonBar'\nimport { PillComposer } from './PillComposer'\nimport { PillContainer } from './PillContainer'\nimport { PillToolsSection } from './PillToolsSection'\nimport { PillVoice, useVoiceBorderStatus } from './PillVoice'\nimport { PromptBadge } from './PromptBadge'\nimport { PromptSuggestions } from './PromptSuggestions'\nimport { StreamingResponse } from './StreamingResponse'\nimport { SummaryBlock, WelcomeMessage } from './SummaryBlock'\nimport { ToolStatusBorder, useToolBorderStatus } from './ToolStatusBorder'\n\nimport type { Prompt } from '@mcp-b/cloud-mirror-types'\nimport type { FC } from 'react'\nimport type { PillMode } from './PillContainer'\n\n/** Position of the pill on screen */\nexport type PillPosition = 'bottom-center' | 'bottom-right'\n\nexport interface AgentPillProps {\n\t/** Position of the pill on screen */\n\tposition?: PillPosition\n\t/** Show voice button in composer */\n\tshowVoiceButton?: boolean\n\t/** Voice mode active state (external control) */\n\tisVoiceActive?: boolean\n\t/** Voice toggle callback */\n\tonVoiceToggle?: () => void\n\t/** Auto-collapse after inactivity (default: true) */\n\tautoCollapse?: boolean\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Action-first agent pill UI.\n *\n * A compact, morphing interface that shows:\n * - Current activity when agent is working\n * - Action list (collapsible)\n * - Summary when complete\n * - Input composer\n *\n * Uses assistant-ui primitives for data binding.\n * UI state (mode, position, hasUnread) comes from AgentUIProvider.\n * Thread state (messages, actions) comes from assistant-ui.\n */\nexport const AgentPill: FC<AgentPillProps> = ({\n\tposition = 'bottom-center',\n\tshowVoiceButton = false,\n\tisVoiceActive = false,\n\tonVoiceToggle,\n\tautoCollapse = true,\n\tclassName,\n}) => {\n\t// Get agent state (unified facade over thread, actions, voice, tools)\n\tconst agent = useAgent()\n\n\t// Destructure agent state for convenience\n\tconst {\n\t\tmessages,\n\t\tisRunning,\n\t\thasMessages,\n\t\tcurrentAction,\n\t\tlastCompletedAction,\n\t\tsummary,\n\t\tvoice,\n\t\ttools,\n\t\tisVoiceActive: agentVoiceActive,\n\t} = agent\n\n\t// Check if there are pending approvals (HITL tools) - derived from thread state\n\tconst hasPendingApproval = useHasPendingToolCalls()\n\tconst pendingToolCalls = usePendingToolCalls()\n\tconst threadRuntime = useThreadRuntime()\n\n\t// Get UI state from AgentUIProvider (falls back to local state if not wrapped)\n\tconst agentUI = useOptionalAgentUI()\n\n\t// UI state - prefer provider state, fallback to default\n\tconst userMode = agentUI?.userMode ?? 'collapsed'\n\tconst setUserMode = agentUI?.setUserMode ?? (() => {})\n\tconst hasUnread = agentUI?.hasUnread ?? false\n\tconst markRead = agentUI?.markRead ?? (() => {})\n\tconst markUnread = agentUI?.markUnread ?? (() => {})\n\tconst dragPosition = agentUI?.position ?? { x: 0, y: 0 }\n\tconst setDragPosition = agentUI?.setPosition ?? (() => {})\n\tconst resetPosition = agentUI?.resetPosition ?? (() => {})\n\n\t// Full-screen mode state\n\tconst isFullScreen = agentUI?.isFullScreen ?? false\n\tconst enterFullScreen = agentUI?.enterFullScreen ?? (() => {})\n\tconst exitFullScreen = agentUI?.exitFullScreen ?? (() => {})\n\n\tconst dragControls = useDragControls()\n\tconst constraintsRef = useRef<HTMLDivElement>(null)\n\tconst autoCollapseTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n\tconst lastMessageCountRef = useRef(0)\n\n\t// Keyboard-aware positioning for mobile\n\tconst { isKeyboardVisible, keyboardHeight } = useKeyboardAware()\n\n\t// Mobile detection for gesture handling\n\tconst { isMobile } = useMobileDetect()\n\n\t// Get prompts from tools (if available)\n\tconst prompts = tools?.prompts ?? []\n\tconst getPrompt = tools?.getPrompt\n\n\t// Get composer runtime for programmatic message sending\n\tconst composerRuntime = useComposerRuntime()\n\n\t/**\n\t * Handle drag end - processes both drag-to-reposition and swipe-to-dismiss gestures.\n\t *\n\t * Behavior:\n\t * - Desktop: Drag to reposition only (no swipe gestures)\n\t * - Mobile: Drag to reposition + aggressive swipe-up to dismiss\n\t */\n\tconst handleDragEnd = useCallback(\n\t\t(_: unknown, info: { offset: { x: number; y: number }; velocity: { y: number } }) => {\n\t\t\tconst { offset, velocity } = info\n\t\t\tconst dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2)\n\n\t\t\t// Check if pill is in an expanded state (not collapsed or hovered)\n\t\t\tconst isExpanded =\n\t\t\t\tuserMode === 'composing' || userMode === 'active' || userMode === 'expanded'\n\n\t\t\t// === MOBILE: Check for swipe-to-dismiss (aggressive upward swipe) ===\n\t\t\tif (isMobile && isExpanded) {\n\t\t\t\tconst swipeDistance = -offset.y // Positive = upward swipe\n\t\t\t\tconst swipeVelocity = -velocity.y // Positive = upward velocity\n\n\t\t\t\tconst { swipe } = GESTURE_CONFIG\n\t\t\t\tconst isAggressiveSwipe =\n\t\t\t\t\t// Either: distance AND velocity both exceed thresholds\n\t\t\t\t\t(swipeDistance > swipe.minDistance && swipeVelocity > swipe.minVelocity) ||\n\t\t\t\t\t// Or: extremely fast swipe (regardless of distance)\n\t\t\t\t\tswipeVelocity > swipe.velocityOnlyThreshold\n\n\t\t\t\tif (isAggressiveSwipe) {\n\t\t\t\t\tsetUserMode('collapsed')\n\t\t\t\t\tresetPosition()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// === DRAG: Only update position if drag exceeded activation threshold ===\n\t\t\tif (dragDistance >= GESTURE_CONFIG.dragActivationDistance) {\n\t\t\t\tsetDragPosition({\n\t\t\t\t\tx: dragPosition.x + offset.x,\n\t\t\t\t\ty: dragPosition.y + offset.y,\n\t\t\t\t})\n\t\t\t}\n\t\t\t// If drag distance is below threshold, ignore it (allows clean taps)\n\t\t},\n\t\t[\n\t\t\tdragPosition.x,\n\t\t\tdragPosition.y,\n\t\t\tsetDragPosition,\n\t\t\tisMobile,\n\t\t\tuserMode,\n\t\t\tsetUserMode,\n\t\t\tresetPosition,\n\t\t]\n\t)\n\n\t// Track unread messages when collapsed\n\tuseEffect(() => {\n\t\tconst currentCount = messages?.length ?? 0\n\t\tif (userMode === 'collapsed' && currentCount > lastMessageCountRef.current) {\n\t\t\tmarkUnread()\n\t\t}\n\t\tlastMessageCountRef.current = currentCount\n\t}, [messages?.length, userMode, markUnread])\n\n\t// Clear unread when expanded\n\tuseEffect(() => {\n\t\tif (userMode !== 'collapsed') {\n\t\t\tmarkRead()\n\t\t}\n\t}, [userMode, markRead])\n\n\t// Voice border status for animations\n\tconst voiceBorderStatus = useVoiceBorderStatus()\n\n\t// Voice mode is active when connected, connecting, or showing an error\n\tconst isVoiceModeActive = agentVoiceActive || isVoiceActive\n\n\t// Get border status - use voice status when in voice mode\n\tconst textBorderStatus = useToolBorderStatus(\n\t\t!!currentAction,\n\t\tlastCompletedAction?.status === 'success'\n\t\t\t? 'success'\n\t\t\t: lastCompletedAction?.status === 'error'\n\t\t\t\t? 'error'\n\t\t\t\t: null\n\t)\n\tconst borderStatus = isVoiceModeActive ? voiceBorderStatus : textBorderStatus\n\n\t// Determine actual mode based on state\n\tconst mode = useMemo((): PillMode => {\n\t\t// Voice mode is active - always show as active\n\t\tif (isVoiceModeActive) return 'active'\n\n\t\t// User explicitly collapsed\n\t\tif (userMode === 'collapsed') return 'collapsed'\n\t\tif (userMode === 'hovered') return 'hovered'\n\n\t\t// Agent is running or pending approval - show active mode\n\t\tif (isRunning || hasPendingApproval) return 'active'\n\n\t\t// Has messages (completed)\n\t\tif (hasMessages) return 'expanded'\n\n\t\t// User is composing\n\t\tif (userMode === 'composing') return 'composing'\n\n\t\treturn 'collapsed'\n\t}, [userMode, isRunning, hasMessages, isVoiceModeActive, hasPendingApproval])\n\n\t// Handle mode changes\n\tconst handleModeChange = useCallback(\n\t\t(newMode: PillMode) => {\n\t\t\tsetUserMode(newMode)\n\t\t},\n\t\t[setUserMode]\n\t)\n\n\t// Handle collapse - close back to collapsed state\n\tconst handleCollapse = useCallback(() => {\n\t\tsetUserMode('collapsed')\n\t}, [setUserMode])\n\n\t// Reset position when pill collapses (position only applies to expanded state)\n\tuseEffect(() => {\n\t\tif (mode === 'collapsed' || mode === 'hovered') {\n\t\t\tresetPosition()\n\t\t}\n\t}, [mode, resetPosition])\n\n\t// Auto-collapse after inactivity (only when expanded/composing and not running)\n\tuseEffect(() => {\n\t\tif (!autoCollapse) return\n\n\t\t// Clear existing timeout\n\t\tif (autoCollapseTimeoutRef.current) {\n\t\t\tclearTimeout(autoCollapseTimeoutRef.current)\n\t\t\tautoCollapseTimeoutRef.current = null\n\t\t}\n\n\t\t// Only auto-collapse when in composing or expanded mode (not active/running)\n\t\tif (mode === 'composing' || (mode === 'expanded' && !isRunning)) {\n\t\t\tautoCollapseTimeoutRef.current = setTimeout(() => {\n\t\t\t\tsetUserMode('collapsed')\n\t\t\t}, AUTO_COLLAPSE_TIMEOUT_MS)\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (autoCollapseTimeoutRef.current) {\n\t\t\t\tclearTimeout(autoCollapseTimeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [mode, isRunning, autoCollapse, setUserMode])\n\n\t// Handle voice toggle\n\tconst handleVoiceToggle = useCallback(() => {\n\t\tif (voice) {\n\t\t\tif (voice.isActive || voice.isConnecting) {\n\t\t\t\tvoice.stop()\n\t\t\t} else {\n\t\t\t\tvoid voice.start()\n\t\t\t}\n\t\t}\n\t\tonVoiceToggle?.()\n\t}, [voice, onVoiceToggle])\n\n\t// Handle prompt selection - expand pill and send prompt content\n\tconst handlePromptSelect = useCallback(\n\t\tasync (prompt: Prompt) => {\n\t\t\t// Expand the pill to composing mode\n\t\t\tsetUserMode('composing')\n\n\t\t\tif (!getPrompt) return\n\n\t\t\ttry {\n\t\t\t\t// Get the expanded prompt content\n\t\t\t\tconst result = await getPrompt(prompt.name)\n\n\t\t\t\t// Find the first user message in the prompt result\n\t\t\t\tconst userMessage = result.messages?.find(\n\t\t\t\t\t(m: { role: string; content: unknown }) => m.role === 'user'\n\t\t\t\t)\n\t\t\t\tif (userMessage) {\n\t\t\t\t\t// Extract text content from the message\n\t\t\t\t\tlet textContent = ''\n\t\t\t\t\tif (typeof userMessage.content === 'string') {\n\t\t\t\t\t\ttextContent = userMessage.content\n\t\t\t\t\t} else if (userMessage.content.type === 'text') {\n\t\t\t\t\t\ttextContent = userMessage.content.text\n\t\t\t\t\t}\n\n\t\t\t\t\tif (textContent) {\n\t\t\t\t\t\t// Set the composer text and send\n\t\t\t\t\t\tcomposerRuntime.setText(textContent)\n\t\t\t\t\t\tcomposerRuntime.send()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tdebugLog('AgentPill', 'Failed to get prompt', err)\n\t\t\t}\n\t\t},\n\t\t[getPrompt, composerRuntime, setUserMode]\n\t)\n\n\t// Handle elicitation denial with reason (user tells Char what to do differently)\n\tconst handleElicitationDeny = useCallback(\n\t\t(reason: string) => {\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tconst firstTool = pendingToolCalls[0]\n\t\t\t\tconst message = formatToolDenialWithReason(reason)\n\t\t\t\tresolvePendingToolCall(threadRuntime, firstTool.messageId, firstTool.toolCallId, message)\n\t\t\t}\n\t\t},\n\t\t[pendingToolCalls, threadRuntime]\n\t)\n\n\t// Get border radius for current mode\n\tconst borderRadius =\n\t\tmode === 'collapsed' || mode === 'hovered'\n\t\t\t? PILL_BORDER_RADIUS.pill\n\t\t\t: PILL_BORDER_RADIUS.rounded\n\n\t// Check if pill is expanded (can be collapsed and can be dragged)\n\tconst isExpanded = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t// Pinch gesture for mobile expand/collapse to full-screen\n\tconst { handlers: pinchHandlers } = usePinchGesture({\n\t\tonPinchOut: () => {\n\t\t\tif (isExpanded && !isFullScreen && !isVoiceModeActive) {\n\t\t\t\tenterFullScreen()\n\t\t\t}\n\t\t},\n\t\tonPinchIn: () => {\n\t\t\tif (isFullScreen) {\n\t\t\t\texitFullScreen()\n\t\t\t}\n\t\t},\n\t\tenabled: isMobile && (isExpanded || isFullScreen),\n\t})\n\n\t// Deferred composer mount - delays rendering PillComposer until container animation settles\n\t// This fixes a bug where react-textarea-autosize measures wrong height during width animation\n\tconst [isComposerReady, setComposerReady] = useState(false)\n\tuseEffect(() => {\n\t\tif (isExpanded) {\n\t\t\tconst timer = setTimeout(() => setComposerReady(true), 200) // Wait for spring to settle\n\t\t\treturn () => {\n\t\t\t\tclearTimeout(timer)\n\t\t\t\tsetComposerReady(false)\n\t\t\t}\n\t\t} else {\n\t\t\tsetComposerReady(false)\n\t\t}\n\t}, [isExpanded])\n\n\t// Handle Escape key to exit full-screen\n\tuseEffect(() => {\n\t\tif (!isFullScreen) return\n\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\te.preventDefault()\n\t\t\t\texitFullScreen()\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('keydown', handleKeyDown)\n\t\treturn () => window.removeEventListener('keydown', handleKeyDown)\n\t}, [isFullScreen, exitFullScreen])\n\n\treturn (\n\t\t<>\n\t\t\t{/* Drag constraints - full viewport */}\n\t\t\t<div ref={constraintsRef} className=\"fixed inset-0 pointer-events-none\" />\n\n\t\t\t<ThreadPrimitive.Root\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'fixed z-50 bottom-safe pb-safe',\n\t\t\t\t\tposition === 'bottom-center' && 'left-1/2 -translate-x-1/2',\n\t\t\t\t\tposition === 'bottom-right' && 'right-4',\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<motion.div\n\t\t\t\t\t// Allow dragging when expanded (including full-screen mode)\n\t\t\t\t\tdrag={isExpanded}\n\t\t\t\t\tdragControls={dragControls}\n\t\t\t\t\tdragConstraints={constraintsRef}\n\t\t\t\t\tdragElastic={0.15}\n\t\t\t\t\tdragMomentum={false}\n\t\t\t\t\t// High transparency while dragging lets user see underlying content (useful for reference)\n\t\t\t\t\twhileDrag={{ scale: 1.02, opacity: DRAG_OPACITY.dragging }}\n\t\t\t\t\tonDragEnd={handleDragEnd}\n\t\t\t\t\t// Keyboard positioning: snap to fixed center position above keyboard\n\t\t\t\t\t// This ensures consistent, predictable placement every time keyboard appears\n\t\t\t\t\t// When keyboard hides: restore the user's previous drag position\n\t\t\t\t\tinitial={false}\n\t\t\t\t\tanimate={{\n\t\t\t\t\t\tx: isExpanded ? (isKeyboardVisible ? 0 : dragPosition.x) : 0,\n\t\t\t\t\t\ty: isExpanded\n\t\t\t\t\t\t\t? isKeyboardVisible\n\t\t\t\t\t\t\t\t? -keyboardHeight - KEYBOARD_GAP_PX\n\t\t\t\t\t\t\t\t: dragPosition.y\n\t\t\t\t\t\t\t: 0,\n\t\t\t\t\t}}\n\t\t\t\t\ttransition={{ type: 'spring', stiffness: 400, damping: 30 }}\n\t\t\t\t\tclassName={cn('relative', isExpanded && 'cursor-grab active:cursor-grabbing')}\n\t\t\t\t\t// Prevent touch events from affecting underlying page scroll (only when expanded)\n\t\t\t\t\tstyle={{ touchAction: isExpanded || isFullScreen ? 'none' : 'auto' }}\n\t\t\t\t\t// Pinch gesture handlers for mobile\n\t\t\t\t\t{...pinchHandlers}\n\t\t\t\t>\n\t\t\t\t\t{/* Prompt badge - floating above collapsed pill when prompts exist */}\n\t\t\t\t\t{mode === 'collapsed' && prompts.length > 0 && (\n\t\t\t\t\t\t<PromptBadge prompts={prompts} onSelect={handlePromptSelect} />\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Unread indicator dot - shown when collapsed with unread messages */}\n\t\t\t\t\t{mode === 'collapsed' && hasUnread && (\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tinitial={{ scale: 0 }}\n\t\t\t\t\t\t\tanimate={{ scale: 1 }}\n\t\t\t\t\t\t\tclassName=\"absolute -top-1 -right-1 w-2 h-2 bg-blue-500 rounded-full z-10\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<ToolStatusBorder status={borderStatus} borderRadius={borderRadius}>\n\t\t\t\t\t\t<PillContainer mode={mode} onModeChange={handleModeChange} isFullScreen={isFullScreen}>\n\t\t\t\t\t\t\t{/* Header with drag handle and close button - shown when expanded or in voice mode */}\n\t\t\t\t\t\t\t{(isVoiceModeActive || isExpanded) && (\n\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between mb-1 -mt-1\">\n\t\t\t\t\t\t\t\t\t{/* Drag handle - visual affordance for repositioning */}\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center text-white/30 p-1 -m-1 cursor-grab active:cursor-grabbing\"\n\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => dragControls.start(e)}\n\t\t\t\t\t\t\t\t\t\taria-label={ARIA_LABELS.dragHandle}\n\t\t\t\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\t\t\t\ttabIndex={0}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<GripHorizontal className=\"h-4 w-4 sm:h-3 sm:w-3\" />\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t{/* Right side controls */}\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2 sm:gap-1\">\n\t\t\t\t\t\t\t\t\t\t{/* Expand/Minimize button - desktop only, not in voice mode */}\n\t\t\t\t\t\t\t\t\t\t{!isMobile && !isVoiceModeActive && (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={isFullScreen ? exitFullScreen : enterFullScreen}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'min-w-7 min-h-7',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'p-1 rounded-full',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'hover:bg-white/10 active:bg-white/20',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'text-white/40 hover:text-white/70',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\t\tisFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ARIA_LABELS.collapseFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ARIA_LABELS.expandFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{isFullScreen ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Minimize className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Expand className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{/* Approval mode toggle */}\n\t\t\t\t\t\t\t\t\t\t<ApprovalModeIndicator />\n\n\t\t\t\t\t\t\t\t\t\t{/* Close button - larger touch target on mobile (min 44px for AAA) */}\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={\n\t\t\t\t\t\t\t\t\t\t\t\tisVoiceModeActive\n\t\t\t\t\t\t\t\t\t\t\t\t\t? handleVoiceToggle\n\t\t\t\t\t\t\t\t\t\t\t\t\t: isFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? exitFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: handleCollapse\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t// Touch target: 44px on mobile (AAA), 28px on desktop\n\t\t\t\t\t\t\t\t\t\t\t\t'min-w-11 min-h-11 sm:min-w-7 sm:min-h-7',\n\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center',\n\t\t\t\t\t\t\t\t\t\t\t\t'p-2 sm:p-1 rounded-full',\n\t\t\t\t\t\t\t\t\t\t\t\t'hover:bg-white/10 active:bg-white/20',\n\t\t\t\t\t\t\t\t\t\t\t\t'text-white/40 hover:text-white/70',\n\t\t\t\t\t\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\tisVoiceModeActive\n\t\t\t\t\t\t\t\t\t\t\t\t\t? ARIA_LABELS.endVoiceSession\n\t\t\t\t\t\t\t\t\t\t\t\t\t: isFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ARIA_LABELS.collapseFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ARIA_LABELS.closeAssistant\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<X className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Voice mode UI - when voice is active (not in full-screen) */}\n\t\t\t\t\t\t\t{!isFullScreen && (\n\t\t\t\t\t\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t\t\t\t\t\t{isVoiceModeActive && <PillVoice key=\"voice-mode\" onEnd={handleVoiceToggle} />}\n\t\t\t\t\t\t\t\t</AnimatePresence>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Main content - simple flex column, scrolling handled by PillContainer */}\n\t\t\t\t\t\t\t{!isVoiceModeActive && (\n\t\t\t\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t\t\t\t{/* Welcome message - composing without messages */}\n\t\t\t\t\t\t\t\t\t{mode === 'composing' && !hasMessages && <WelcomeMessage />}\n\n\t\t\t\t\t\t\t\t\t{/* Summary - when completed */}\n\t\t\t\t\t\t\t\t\t{mode === 'expanded' && !isRunning && summary && (\n\t\t\t\t\t\t\t\t\t\t<SummaryBlock\n\t\t\t\t\t\t\t\t\t\t\tsummary={summary}\n\t\t\t\t\t\t\t\t\t\t\tisSuccess={!lastCompletedAction?.error}\n\t\t\t\t\t\t\t\t\t\t\tisFullScreen={isFullScreen}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Streaming response - shows text as it's being generated */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') && isRunning && (\n\t\t\t\t\t\t\t\t\t\t<StreamingResponse isFullScreen={isFullScreen} />\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Idle indicator - when expanded but no activity */}\n\t\t\t\t\t\t\t\t\t{mode === 'expanded' && !isRunning && !summary && <IdleIndicator />}\n\n\t\t\t\t\t\t\t\t\t{/* Tool UIs in collapsible, scrollable section */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') && (\n\t\t\t\t\t\t\t\t\t\t<PillToolsSection\n\t\t\t\t\t\t\t\t\t\t\tdefaultCollapsed={mode === 'active' && !isFullScreen}\n\t\t\t\t\t\t\t\t\t\t\tisFullScreen={isFullScreen}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Prompt suggestions - inline chips when expanded and not running (hidden in full-screen) */}\n\t\t\t\t\t\t\t\t\t{!isFullScreen &&\n\t\t\t\t\t\t\t\t\t\t(mode === 'composing' || mode === 'expanded') &&\n\t\t\t\t\t\t\t\t\t\t!isRunning &&\n\t\t\t\t\t\t\t\t\t\t!hasPendingApproval &&\n\t\t\t\t\t\t\t\t\t\tprompts.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<PromptSuggestions prompts={prompts} onSelect={handlePromptSelect} />\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Elicitation buttons - above composer when approval is needed */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') && hasPendingApproval && (\n\t\t\t\t\t\t\t\t\t\t<ElicitationButtonBar />\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Activity indicator - shows what agent is doing when running */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') &&\n\t\t\t\t\t\t\t\t\t\tisRunning &&\n\t\t\t\t\t\t\t\t\t\t!hasPendingApproval && <ActivityIndicator />}\n\n\t\t\t\t\t\t\t\t\t{/* Composer - always visible when expanded (no longer hidden during approval) */}\n\t\t\t\t\t\t\t\t\t<AnimatePresence>\n\t\t\t\t\t\t\t\t\t\t{isComposerReady &&\n\t\t\t\t\t\t\t\t\t\t\t(mode === 'composing' || mode === 'active' || mode === 'expanded') && (\n\t\t\t\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttransition={{ duration: 0.15 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"mt-1.5\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<PillComposer\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowVoiceButton={showVoiceButton || !!voice?.isSupported}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisVoiceActive={isVoiceActive}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonVoiceToggle={handleVoiceToggle}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisEliciting={hasPendingApproval}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonElicitationSubmit={handleElicitationDeny}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</AnimatePresence>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</PillContainer>\n\t\t\t\t\t</ToolStatusBorder>\n\t\t\t\t</motion.div>\n\t\t\t</ThreadPrimitive.Root>\n\t\t</>\n\t)\n}\n\nexport default AgentPill\n","/**\n * AgentProvider\n *\n * Unified provider that wraps all agent infrastructure:\n * - AgentUIProvider (non-thread UI state: open/close, position)\n * - MCPToolsProvider (tool registry and execution)\n * - AssistantRuntimeProvider (chat runtime - single source of truth for thread)\n * - VoiceThreadBridge (voice mode integrated with thread)\n *\n * This is the single entry point for setting up agent capabilities.\n * Widgets (Pill, Modal) and custom UIs should be wrapped by this provider.\n *\n * Architecture:\n * ```\n * AgentUIProvider (UI state - persists across threads)\n * └── MCPToolsProvider (tools - shared across threads)\n * └── AssistantRuntimeProvider (thread state - single source of truth)\n * └── VoiceThreadBridge (voice → thread integration)\n * └── MCPToolRegistry\n * └── children\n * ```\n *\n * @example Basic usage\n * ```tsx\n * import { AgentProvider, AgentPill } from '@mcp-b/embedded-agent'\n *\n * function App() {\n * return (\n * <AgentProvider apiBase=\"https://your-worker.workers.dev\">\n * <AgentPill />\n * </AgentProvider>\n * )\n * }\n * ```\n *\n * @example Headless usage (custom UI)\n * ```tsx\n * import { AgentProvider, useAgent } from '@mcp-b/embedded-agent'\n *\n * function CustomUI() {\n * const agent = useAgent()\n * return <div>{agent.messages.map(m => ...)}</div>\n * }\n *\n * function App() {\n * return (\n * <AgentProvider apiBase=\"https://...\">\n * <CustomUI />\n * </AgentProvider>\n * )\n * }\n * ```\n */\n\nimport { AssistantRuntimeProvider } from '@assistant-ui/react'\nimport { AssistantChatTransport, useChatRuntime } from '@assistant-ui/react-ai-sdk'\nimport { lastAssistantMessageIsCompleteWithToolCalls } from 'ai'\nimport { useMemo } from 'react'\n\nimport { MCPToolRegistry } from '../../components/MCPToolRegistry'\nimport { WEBMCP_PRODUCTION_API_BASE } from '../../lib/constants'\nimport { MCPToolsProvider } from '../../providers/MCPToolsProvider'\nimport { ToolApprovalProvider } from '../../providers/ToolApprovalProvider'\nimport { VoiceThreadBridge } from '../../providers/VoiceThreadBridge'\nimport { AgentUIProvider } from './AgentUIProvider'\n\nimport type { ToolApprovalMode, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { FC, ReactNode } from 'react'\nimport type { PillMode } from './AgentUIProvider'\n\nexport interface AgentProviderProps {\n\tchildren: ReactNode\n\n\t/** API base URL for chat and token endpoints (defaults to production WebMCP API) */\n\tapiBase?: string\n\n\t/** Voice mode token endpoint (defaults to {apiBase}/api/realtime/session) */\n\ttokenEndpoint?: string\n\n\t/** Auto-connect to local MCP source (default: true) */\n\tautoConnectLocal?: boolean\n\n\t/** Initial open state for UI (default: false) */\n\tdefaultOpen?: boolean\n\n\t/** Initial pill mode (default: 'collapsed') */\n\tdefaultMode?: PillMode\n\n\t/** Initial tool approval mode: 'ask' requires confirmation, 'auto' executes immediately (default: 'ask') */\n\tdefaultApprovalMode?: ToolApprovalMode\n\n\t/** Callback when MCP tools change */\n\tonToolsChange?: (tools: ToolWithSource[]) => void\n\n\t/** Callback when voice mode errors */\n\tonVoiceError?: (error: string) => void\n\n\t/** Callback when voice mode connects */\n\tonVoiceConnect?: () => void\n\n\t/** Callback when voice mode disconnects */\n\tonVoiceDisconnect?: (duration: number) => void\n\n\t/** Callback when UI open state changes */\n\tonOpenChange?: (open: boolean) => void\n\n\t/** Callback when pill mode changes */\n\tonModeChange?: (mode: PillMode) => void\n\n\t/** Callback when tool approval mode changes */\n\tonApprovalModeChange?: (mode: ToolApprovalMode) => void\n}\n\n/**\n * Internal component that sets up the chat runtime and voice bridge.\n * Must be inside MCPToolsProvider so VoiceThreadBridge can access tools.\n */\ninterface AgentRuntimeProps {\n\tchildren: ReactNode\n\tapiBase?: string\n\ttokenEndpoint?: string\n\tonVoiceError?: (error: string) => void\n\tonVoiceConnect?: () => void\n\tonVoiceDisconnect?: (duration: number) => void\n}\n\nconst AgentRuntime: FC<AgentRuntimeProps> = ({\n\tchildren,\n\tapiBase,\n\ttokenEndpoint,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n}) => {\n\t// Resolve API base (defaults to production)\n\tconst resolvedApiBase = apiBase ?? WEBMCP_PRODUCTION_API_BASE\n\n\t// Create transport with API endpoint\n\tconst transport = useMemo(() => {\n\t\tconst chatApi = `${resolvedApiBase}/api/chat`\n\t\treturn new AssistantChatTransport({ api: chatApi })\n\t}, [resolvedApiBase])\n\n\tconst runtime = useChatRuntime({\n\t\ttransport,\n\t\tsendAutomaticallyWhen: (messages) => {\n\t\t\treturn lastAssistantMessageIsCompleteWithToolCalls(messages)\n\t\t},\n\t})\n\n\t// Compute token endpoint from apiBase if not explicitly provided\n\tconst resolvedTokenEndpoint = tokenEndpoint || `${resolvedApiBase}/api/realtime/session`\n\n\treturn (\n\t\t<AssistantRuntimeProvider runtime={runtime}>\n\t\t\t<VoiceThreadBridge\n\t\t\t\ttokenEndpoint={resolvedTokenEndpoint}\n\t\t\t\tonError={onVoiceError}\n\t\t\t\tonConnect={onVoiceConnect}\n\t\t\t\tonDisconnect={onVoiceDisconnect}\n\t\t\t>\n\t\t\t\t<MCPToolRegistry />\n\t\t\t\t{children}\n\t\t\t</VoiceThreadBridge>\n\t\t</AssistantRuntimeProvider>\n\t)\n}\n\n/**\n * Unified provider for all agent capabilities.\n *\n * Provides:\n * - UI state (open/close, position) via AgentUIProvider\n * - MCP tool registry and execution via MCPToolsProvider\n * - Tool approval settings via ToolApprovalProvider\n * - Chat runtime (via @assistant-ui/react) - single source of truth for thread\n * - Voice mode integrated with thread (via VoiceThreadBridge)\n *\n * Use the `useAgent` hook to access agent state and capabilities.\n * Use the `useAgentUI` hook to access UI state (open/close, mode, position).\n * Use the `useToolApproval` hook to access tool approval settings.\n */\nexport const AgentProvider: FC<AgentProviderProps> = ({\n\tchildren,\n\tapiBase,\n\ttokenEndpoint,\n\tautoConnectLocal = true,\n\tdefaultOpen = false,\n\tdefaultMode = 'collapsed',\n\tdefaultApprovalMode,\n\tonToolsChange,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n\tonOpenChange,\n\tonModeChange,\n\tonApprovalModeChange,\n}) => {\n\treturn (\n\t\t<AgentUIProvider\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tdefaultMode={defaultMode}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tonModeChange={onModeChange}\n\t\t>\n\t\t\t<ToolApprovalProvider defaultMode={defaultApprovalMode} onModeChange={onApprovalModeChange}>\n\t\t\t\t<MCPToolsProvider autoConnectLocal={autoConnectLocal} onToolsChange={onToolsChange}>\n\t\t\t\t\t<AgentRuntime\n\t\t\t\t\t\tapiBase={apiBase}\n\t\t\t\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\t\t\t\tonVoiceError={onVoiceError}\n\t\t\t\t\t\tonVoiceConnect={onVoiceConnect}\n\t\t\t\t\t\tonVoiceDisconnect={onVoiceDisconnect}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</AgentRuntime>\n\t\t\t\t</MCPToolsProvider>\n\t\t\t</ToolApprovalProvider>\n\t\t</AgentUIProvider>\n\t)\n}\n","/**\n * Auto-generated file - DO NOT EDIT\n * Generated by scripts/generate-inline-styles.js\n *\n * Contains the compiled CSS for the web component standalone build.\n */\n\nexport const WEBMCP_STYLES = \"/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tool-border-angle:0deg}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\",\\\"Noto Color Emoji\\\";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\\\"Liberation Mono\\\",\\\"Courier New\\\",monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-indigo-500:oklch(58.5% .233 277.117);--color-purple-600:oklch(55.8% .288 302.321);--color-slate-900:oklch(20.8% .042 265.755);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-xs:.125rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\",\\\"Noto Color Emoji\\\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\\\"Liberation Mono\\\",\\\"Courier New\\\",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--radius:.75rem;--background:oklch(100% 0 0);--foreground:oklch(14.1% .005 285.823);--card:oklch(100% 0 0);--card-foreground:oklch(14.1% .005 285.823);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.1% .005 285.823);--primary:oklch(21% .006 285.885);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(96.7% .001 286.375);--secondary-foreground:oklch(21% .006 285.885);--muted:oklch(96.7% .001 286.375);--muted-foreground:oklch(55.2% .016 285.938);--accent:oklch(96.7% .001 286.375);--accent-foreground:oklch(21% .006 285.885);--destructive:oklch(57.7% .245 27.325);--destructive-foreground:oklch(98.5% 0 0);--border:oklch(92% .004 286.32);--input:oklch(92% .004 286.32);--ring:oklch(70.5% .015 286.067)}.dark{--background:oklch(14.1% .005 285.823);--foreground:oklch(98.5% 0 0);--card:oklch(21% .006 285.885);--card-foreground:oklch(98.5% 0 0);--popover:oklch(21% .006 285.885);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92% .004 286.32);--primary-foreground:oklch(21% .006 285.885);--secondary:oklch(27.4% .006 286.033);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(27.4% .006 286.033);--muted-foreground:oklch(70.5% .015 286.067);--accent:oklch(27.4% .006 286.033);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--destructive-foreground:oklch(98.5% 0 0);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.2% .016 285.938)}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklch,var(--ring),transparent 50%)}}body{background-color:var(--background);color:var(--foreground)}}@layer components{.app-shell{z-index:0;background-color:var(--background);background-image:radial-gradient(80% 60% at -10% -10%,oklch(82% .15 270/.15),#0000),radial-gradient(60% 50% at 110% 10%,oklch(85% .1 220/.12),#0000),radial-gradient(50% 45% at 50% 120%,oklch(95% .02 250/.08),#0000);position:relative}.dark .app-shell{background-image:radial-gradient(80% 60% at -10% -10%,oklch(55% .14 270/.25),#0000),radial-gradient(60% 50% at 110% 15%,oklch(60% .12 220/.22),#0000),radial-gradient(50% 45% at 50% 120%,oklch(35% .04 250/.16),#0000)}.app-shell:before,.app-shell:after{content:\\\"\\\";pointer-events:none;filter:blur(32px);opacity:.6;z-index:-1;border-radius:9999px;position:absolute;inset:auto}.app-shell:before{background:radial-gradient(60% 60% at 40% 40%,oklch(80% .12 270/.3),#0000);width:260px;height:260px;top:-60px;left:-80px}.app-shell:after{background:radial-gradient(60% 60% at 60% 60%,oklch(84% .1 220/.25),#0000);width:300px;height:300px;bottom:-80px;right:-60px}.toolbar-surface{border-top:1px solid var(--border);background:linear-gradient(to right,var(--background),var(--background),var(--background))}@supports (color:color-mix(in lab, red, red)){.toolbar-surface{background:linear-gradient(to right,var(--background),color-mix(in oklch,var(--background),transparent 5%),var(--background))}}.toolbar-surface{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.toolbar-surface{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.toolbar-surface{background:color-mix(in oklch,var(--background),transparent 20%)}}}.toolbar-surface-top{border-bottom:1px solid var(--border);background:linear-gradient(to right,var(--background),var(--background),var(--background))}@supports (color:color-mix(in lab, red, red)){.toolbar-surface-top{background:linear-gradient(to right,var(--background),color-mix(in oklch,var(--background),transparent 5%),var(--background))}}.toolbar-surface-top{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.toolbar-surface-top{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.toolbar-surface-top{background:color-mix(in oklch,var(--background),transparent 20%)}}}.toolbar-inner{justify-content:space-between;align-items:center;padding:.5rem .75rem;display:flex}.toolbar-card{background:var(--card);justify-content:space-between;align-items:center;gap:.5rem;display:flex}@supports (color:color-mix(in lab, red, red)){.toolbar-card{background:color-mix(in oklch,var(--card),transparent 60%)}}.toolbar-card{border:1px solid var(--border);border-radius:.75rem;padding:.5rem .75rem}.toolbar-group{align-items:center;gap:.25rem;display:flex}.btn-toolbar-primary{background:linear-gradient(to right,var(--primary),var(--primary));border-radius:.75rem;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;display:flex}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary{background:linear-gradient(to right,color-mix(in oklch,var(--primary),transparent 95%),color-mix(in oklch,var(--primary),transparent 90%))}}.btn-toolbar-primary{border:1px solid var(--primary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary{border:1px solid color-mix(in oklch,var(--primary),transparent 80%)}}.btn-toolbar-primary{transition:all .2s}.btn-toolbar-primary:hover{background:linear-gradient(to right,var(--primary),var(--primary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary:hover{background:linear-gradient(to right,color-mix(in oklch,var(--primary),transparent 90%),color-mix(in oklch,var(--primary),transparent 80%))}}.btn-toolbar-icon-primary{background:linear-gradient(to bottom right,var(--primary),var(--primary));border-radius:9999px;width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--primary),transparent 90%),color-mix(in oklch,var(--primary),transparent 80%))}}.btn-toolbar-icon-primary{border:1px solid var(--primary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary{border:1px solid color-mix(in oklch,var(--primary),transparent 70%)}}.btn-toolbar-icon-primary{transition:all .2s;box-shadow:0 1px 2px #0000000d}.btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,var(--primary),var(--primary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--primary),transparent 80%),color-mix(in oklch,var(--primary),transparent 70%))}}.btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,var(--secondary),var(--secondary));border-radius:9999px;width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--secondary),transparent 90%),color-mix(in oklch,var(--secondary),transparent 80%))}}.btn-toolbar-icon-secondary{border:1px solid var(--secondary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary{border:1px solid color-mix(in oklch,var(--secondary),transparent 70%)}}.btn-toolbar-icon-secondary{transition:all .2s;box-shadow:0 1px 2px #0000000d}.btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,var(--secondary),var(--secondary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--secondary),transparent 80%),color-mix(in oklch,var(--secondary),transparent 70%))}}.badge-compact{height:1.25rem;padding:0 .5rem;font-size:10px}.badge-mini{height:1rem;padding:0 .375rem;font-size:10px}@keyframes shimmer-bg{0%{background-position:-1000px 0}to{background-position:1000px 0}}.shimmer{background:linear-gradient(90deg,#0000,#ffffff1a,#0000) 0 0/1000px 100%;animation:3s linear infinite shimmer-bg}.animate-shimmer{animation:2s linear infinite shimmer}@keyframes pulse-glow{0%,to{box-shadow:0 0 20px rgba(var(--primary),.1)}50%{box-shadow:0 0 30px rgba(var(--primary),.2)}}.pulse-glow{animation:2s ease-in-out infinite pulse-glow}@keyframes gradient-x{0%,to{background-position:0%}50%{background-position:100%}}.animate-gradient-x{animation:8s ease-in-out infinite gradient-x}.gradient-text{background:linear-gradient(to right,var(--foreground),var(--foreground))}@supports (color:color-mix(in lab, red, red)){.gradient-text{background:linear-gradient(to right,var(--foreground),color-mix(in oklch,var(--foreground),transparent 30%))}}.gradient-text{-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.glass{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.glass{background:color-mix(in oklch,var(--background),transparent 50%)}}.glass{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border)}@supports (color:color-mix(in lab, red, red)){.glass{border:1px solid color-mix(in oklch,var(--border),transparent 50%)}}.tool-card{transition:all .3s ease-out}.tool-card:hover{transform:scale(1.02);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.scrollbar-thin{scrollbar-width:thin}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-track{background:0 0}.scrollbar-thin::-webkit-scrollbar-thumb{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.scrollbar-thin::-webkit-scrollbar-thumb{background-color:color-mix(in oklch,var(--primary),transparent 80%)}}.scrollbar-thin::-webkit-scrollbar-thumb{border-radius:3px}.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:color-mix(in oklch,var(--primary),transparent 70%)}}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.-inset-\\\\[1px\\\\]{inset:-1px}.inset-0{inset:calc(var(--spacing)*0)}.-top-1{top:calc(var(--spacing)*-1)}.-top-1\\\\.5{top:calc(var(--spacing)*-1.5)}.top-1\\\\.5{top:calc(var(--spacing)*1.5)}.top-1\\\\/2{top:50%}.top-4{top:calc(var(--spacing)*4)}.top-\\\\[50\\\\%\\\\]{top:50%}.-right-0\\\\.5{right:calc(var(--spacing)*-.5)}.-right-1{right:calc(var(--spacing)*-1)}.-right-1\\\\.5{right:calc(var(--spacing)*-1.5)}.right-0{right:calc(var(--spacing)*0)}.right-1\\\\.5{right:calc(var(--spacing)*1.5)}.right-4{right:calc(var(--spacing)*4)}.-bottom-0\\\\.5{bottom:calc(var(--spacing)*-.5)}.bottom-full{bottom:100%}.left-0{left:calc(var(--spacing)*0)}.left-1\\\\/2,.left-\\\\[50\\\\%\\\\]{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.col-span-full{grid-column:1/-1}.col-start-1{grid-column-start:1}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-m-1{margin:calc(var(--spacing)*-1)}.m-0{margin:calc(var(--spacing)*0)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.my-2{margin-block:calc(var(--spacing)*2)}.-mt-1{margin-top:calc(var(--spacing)*-1)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-2\\\\.5{margin-top:calc(var(--spacing)*2.5)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-1\\\\.5{margin-right:calc(var(--spacing)*1.5)}.-mb-1{margin-bottom:calc(var(--spacing)*-1)}.mb-0\\\\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-0\\\\.5{margin-left:calc(var(--spacing)*.5)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-2\\\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-14{width:calc(var(--spacing)*14);height:calc(var(--spacing)*14)}.size-\\\\[34px\\\\]{width:34px;height:34px}.size-full{width:100%;height:100%}.h-1\\\\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\\\\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\\\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-4\\\\.5{height:calc(var(--spacing)*4.5)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-auto{height:auto}.h-full{height:100%}.max-h-24{max-height:calc(var(--spacing)*24)}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-40{max-height:calc(var(--spacing)*40)}.max-h-64{max-height:calc(var(--spacing)*64)}.max-h-\\\\[30vh\\\\]{max-height:30vh}.max-h-\\\\[80dvh\\\\]{max-height:80dvh}.max-h-\\\\[80vh\\\\]{max-height:80vh}.min-h-7{min-height:calc(var(--spacing)*7)}.min-h-11{min-height:calc(var(--spacing)*11)}.min-h-screen{min-height:100vh}.w-0\\\\.5{width:calc(var(--spacing)*.5)}.w-1\\\\.5{width:calc(var(--spacing)*1.5)}.w-2{width:calc(var(--spacing)*2)}.w-2\\\\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\\\\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-4\\\\.5{width:calc(var(--spacing)*4.5)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-11{width:calc(var(--spacing)*11)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-24{max-width:calc(var(--spacing)*24)}.max-w-32{max-width:calc(var(--spacing)*32)}.max-w-\\\\[100px\\\\]{max-width:100px}.max-w-\\\\[calc\\\\(100\\\\%-2rem\\\\)\\\\]{max-width:calc(100% - 2rem)}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-7{min-width:calc(var(--spacing)*7)}.min-w-11{min-width:calc(var(--spacing)*11)}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.border-separate{border-collapse:separate}.border-spacing-0{--tw-border-spacing-x:calc(var(--spacing)*0);--tw-border-spacing-y:calc(var(--spacing)*0);border-spacing:var(--tw-border-spacing-x)var(--tw-border-spacing-y)}.origin-\\\\(--radix-tooltip-content-transform-origin\\\\){transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-1\\\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-\\\\[-50\\\\%\\\\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\\\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\\\\[-50\\\\%\\\\]{--tw-translate-y:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\\\\[calc\\\\(-50\\\\%_-_2px\\\\)\\\\]{--tw-translate-y:calc(-50% - 2px);translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-75{--tw-scale-x:75%;--tw-scale-y:75%;--tw-scale-z:75%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.rotate-45{rotate:45deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.resize-none{resize:none}.scroll-m-20{scroll-margin:calc(var(--spacing)*20)}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-rows-\\\\[0fr\\\\]{grid-template-rows:0fr}.grid-rows-\\\\[1fr\\\\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\\\\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\\\\[2px\\\\]{border-radius:2px}.rounded-\\\\[14px\\\\]{border-radius:14px}.rounded-\\\\[inherit\\\\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-none{border-radius:0}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-xs{border-radius:var(--radius-xs)}.\\\\!rounded-t-none{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-t-lg{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius)}.rounded-b-lg{border-bottom-right-radius:var(--radius);border-bottom-left-radius:var(--radius)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-amber-500\\\\/30{border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\\\/30{border-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.border-amber-500\\\\/50{border-color:#f99c0080}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\\\/50{border-color:color-mix(in oklab,var(--color-amber-500)50%,transparent)}}.border-blue-500\\\\/20{border-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\\\/20{border-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.border-blue-500\\\\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\\\/30{border-color:color-mix(in oklab,var(--color-blue-500)30%,transparent)}}.border-border{border-color:var(--border)}.border-foreground\\\\/20{border-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.border-foreground\\\\/20{border-color:color-mix(in oklab,var(--foreground)20%,transparent)}}.border-input{border-color:var(--input)}.border-muted-foreground\\\\/20{border-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-muted-foreground\\\\/20{border-color:color-mix(in oklab,var(--muted-foreground)20%,transparent)}}.border-transparent{border-color:#0000}.border-white\\\\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/5{border-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.border-white\\\\/8{border-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/8{border-color:color-mix(in oklab,var(--color-white)8%,transparent)}}.border-white\\\\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.border-white\\\\/20{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/20{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.border-zinc-200{border-color:var(--color-zinc-200)}.border-zinc-200\\\\/80{border-color:#e4e4e7cc}@supports (color:color-mix(in lab, red, red)){.border-zinc-200\\\\/80{border-color:color-mix(in oklab,var(--color-zinc-200)80%,transparent)}}.border-zinc-600{border-color:var(--color-zinc-600)}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\\\\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\\\/10{background-color:color-mix(in oklab,var(--color-amber-500)10%,transparent)}}.bg-amber-500\\\\/20{background-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\\\/20{background-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-black\\\\/30{background-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.bg-black\\\\/30{background-color:color-mix(in oklab,var(--color-black)30%,transparent)}}.bg-black\\\\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\\\\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-500\\\\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\\\\/10{background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.bg-border{background-color:var(--border)}.bg-destructive{background-color:var(--destructive)}.bg-foreground{background-color:var(--foreground)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-400\\\\/60{background-color:#05df7299}@supports (color:color-mix(in lab, red, red)){.bg-green-400\\\\/60{background-color:color-mix(in oklab,var(--color-green-400)60%,transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\\\\/10{background-color:#00c7581a}@supports (color:color-mix(in lab, red, red)){.bg-green-500\\\\/10{background-color:color-mix(in oklab,var(--color-green-500)10%,transparent)}}.bg-muted{background-color:var(--muted)}.bg-muted-foreground\\\\/15{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\\\/15{background-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.bg-muted\\\\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/50{background-color:color-mix(in oklab,var(--muted)50%,transparent)}}.bg-primary{background-color:var(--primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\\\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\\\/10{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.bg-red-500\\\\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\\\/20{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\\\\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/5{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.bg-white\\\\/8{background-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/8{background-color:color-mix(in oklab,var(--color-white)8%,transparent)}}.bg-white\\\\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/10{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-white\\\\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/20{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.bg-white\\\\/60{background-color:#fff9}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/60{background-color:color-mix(in oklab,var(--color-white)60%,transparent)}}.bg-white\\\\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/90{background-color:color-mix(in oklab,var(--color-white)90%,transparent)}}.bg-yellow-500{background-color:var(--color-yellow-500)}.bg-zinc-100{background-color:var(--color-zinc-100)}.bg-zinc-700\\\\/50{background-color:#3f3f4680}@supports (color:color-mix(in lab, red, red)){.bg-zinc-700\\\\/50{background-color:color-mix(in oklab,var(--color-zinc-700)50%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-indigo-500{--tw-gradient-from:var(--color-indigo-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-purple-600{--tw-gradient-to:var(--color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.fill-foreground{fill:var(--foreground)}.stroke-\\\\[1\\\\.5px\\\\]{stroke-width:1.5px}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.p-px{padding:1px}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\\\\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\\\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.pt-0\\\\.5{padding-top:calc(var(--spacing)*.5)}.pt-1\\\\.5{padding-top:calc(var(--spacing)*1.5)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-6{padding-left:calc(var(--spacing)*6)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\\\[10px\\\\]{font-size:10px}.text-\\\\[11px\\\\]{font-size:11px}.text-\\\\[13px\\\\]{font-size:13px}.text-\\\\[15px\\\\]{font-size:15px}.text-\\\\[17px\\\\]{font-size:17px}.text-\\\\[19px\\\\]{font-size:19px}.text-\\\\[21px\\\\]{font-size:21px}.text-\\\\[25px\\\\]{font-size:25px}.leading-\\\\[21px\\\\]{--tw-leading:21px;line-height:21px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-background{color:var(--background)}.text-blue-400{color:var(--color-blue-400)}.text-blue-400\\\\/60{color:#54a2ff99}@supports (color:color-mix(in lab, red, red)){.text-blue-400\\\\/60{color:color-mix(in oklab,var(--color-blue-400)60%,transparent)}}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-foreground{color:var(--foreground)}.text-green-400{color:var(--color-green-400)}.text-green-600{color:var(--color-green-600)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.text-white\\\\/30{color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/30{color:color-mix(in oklab,var(--color-white)30%,transparent)}}.text-white\\\\/40{color:#fff6}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/40{color:color-mix(in oklab,var(--color-white)40%,transparent)}}.text-white\\\\/50{color:#ffffff80}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/50{color:color-mix(in oklab,var(--color-white)50%,transparent)}}.text-white\\\\/60{color:#fff9}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/60{color:color-mix(in oklab,var(--color-white)60%,transparent)}}.text-white\\\\/70{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/70{color:color-mix(in oklab,var(--color-white)70%,transparent)}}.text-white\\\\/80{color:#fffc}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/80{color:color-mix(in oklab,var(--color-white)80%,transparent)}}.text-white\\\\/90{color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/90{color:color-mix(in oklab,var(--color-white)90%,transparent)}}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-700{color:var(--color-zinc-700)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-100{opacity:1}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-black\\\\/10{--tw-shadow-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.shadow-black\\\\/10{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)10%,transparent)var(--tw-shadow-alpha),transparent)}}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\\\[color\\\\,box-shadow\\\\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\\\[grid-template-rows\\\\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.will-change-transform{will-change:transform}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\\\\:scale-100:is(:where(.group):hover *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\\\\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\\\\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.placeholder\\\\:text-white\\\\/40::placeholder{color:#fff6}@supports (color:color-mix(in lab, red, red)){.placeholder\\\\:text-white\\\\/40::placeholder{color:color-mix(in oklab,var(--color-white)40%,transparent)}}.first\\\\:mt-0:first-child{margin-top:calc(var(--spacing)*0)}.first\\\\:rounded-tl-lg:first-child{border-top-left-radius:var(--radius)}.first\\\\:border-t:first-child{border-top-style:var(--tw-border-style);border-top-width:1px}.last\\\\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}.last\\\\:rounded-tr-lg:last-child{border-top-right-radius:var(--radius)}.last\\\\:border-r:last-child{border-right-style:var(--tw-border-style);border-right-width:1px}.empty\\\\:hidden:empty{display:none}.focus-within\\\\:border-white\\\\/15:focus-within{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.focus-within\\\\:border-white\\\\/15:focus-within{border-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.focus-within\\\\:bg-white\\\\/10:focus-within{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.focus-within\\\\:bg-white\\\\/10:focus-within{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}@media (hover:hover){.hover\\\\:border-amber-500:hover{border-color:var(--color-amber-500)}.hover\\\\:border-red-500\\\\/50:hover{border-color:#fb2c3680}@supports (color:color-mix(in lab, red, red)){.hover\\\\:border-red-500\\\\/50:hover{border-color:color-mix(in oklab,var(--color-red-500)50%,transparent)}}.hover\\\\:border-white\\\\/20:hover{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\\\\:border-white\\\\/20:hover{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.hover\\\\:\\\\!bg-white:hover{background-color:var(--color-white)!important}.hover\\\\:bg-accent:hover,.hover\\\\:bg-accent\\\\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-accent\\\\/50:hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.hover\\\\:bg-amber-500\\\\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-amber-500\\\\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.hover\\\\:bg-amber-500\\\\/30:hover{background-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-amber-500\\\\/30:hover{background-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.hover\\\\:bg-destructive\\\\/10:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/10:hover{background-color:color-mix(in oklab,var(--destructive)10%,transparent)}}.hover\\\\:bg-destructive\\\\/80:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/80:hover{background-color:color-mix(in oklab,var(--destructive)80%,transparent)}}.hover\\\\:bg-destructive\\\\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}}.hover\\\\:bg-muted-foreground\\\\/15:hover{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-muted-foreground\\\\/15:hover{background-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.hover\\\\:bg-primary\\\\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-primary\\\\/80:hover{background-color:color-mix(in oklab,var(--primary)80%,transparent)}}.hover\\\\:bg-primary\\\\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-primary\\\\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}}.hover\\\\:bg-red-500\\\\/10:hover{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-red-500\\\\/10:hover{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.hover\\\\:bg-red-500\\\\/20:hover{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-red-500\\\\/20:hover{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.hover\\\\:bg-red-500\\\\/30:hover{background-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-red-500\\\\/30:hover{background-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.hover\\\\:bg-secondary\\\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-secondary\\\\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}}.hover\\\\:bg-white:hover{background-color:var(--color-white)}.hover\\\\:bg-white\\\\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/5:hover{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.hover\\\\:bg-white\\\\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/10:hover{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.hover\\\\:bg-white\\\\/15:hover{background-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/15:hover{background-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.hover\\\\:bg-white\\\\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/20:hover{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.hover\\\\:bg-white\\\\/30:hover{background-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/30:hover{background-color:color-mix(in oklab,var(--color-white)30%,transparent)}}.hover\\\\:bg-white\\\\/95:hover{background-color:#fffffff2}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/95:hover{background-color:color-mix(in oklab,var(--color-white)95%,transparent)}}.hover\\\\:bg-zinc-50:hover{background-color:var(--color-zinc-50)}.hover\\\\:bg-zinc-200:hover{background-color:var(--color-zinc-200)}.hover\\\\:bg-zinc-700:hover{background-color:var(--color-zinc-700)}.hover\\\\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\\\\:text-destructive:hover{color:var(--destructive)}.hover\\\\:text-foreground:hover{color:var(--foreground)}.hover\\\\:text-primary\\\\/80:hover{color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-primary\\\\/80:hover{color:color-mix(in oklab,var(--primary)80%,transparent)}}.hover\\\\:text-red-200:hover{color:var(--color-red-200)}.hover\\\\:text-red-300:hover{color:var(--color-red-300)}.hover\\\\:text-red-400:hover{color:var(--color-red-400)}.hover\\\\:text-white:hover{color:var(--color-white)}.hover\\\\:text-white\\\\/50:hover{color:#ffffff80}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/50:hover{color:color-mix(in oklab,var(--color-white)50%,transparent)}}.hover\\\\:text-white\\\\/60:hover{color:#fff9}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/60:hover{color:color-mix(in oklab,var(--color-white)60%,transparent)}}.hover\\\\:text-white\\\\/70:hover{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/70:hover{color:color-mix(in oklab,var(--color-white)70%,transparent)}}.hover\\\\:text-white\\\\/80:hover{color:#fffc}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/80:hover{color:color-mix(in oklab,var(--color-white)80%,transparent)}}.hover\\\\:text-zinc-600:hover{color:var(--color-zinc-600)}.hover\\\\:underline:hover{text-decoration-line:underline}.hover\\\\:opacity-75:hover{opacity:.75}.hover\\\\:opacity-100:hover{opacity:1}}.focus\\\\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\\\\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\\\\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\\\\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\\\\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus\\\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\\\:ring-\\\\[3px\\\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(3px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\\\:ring-blue-500:focus-visible{--tw-ring-color:var(--color-blue-500)}.focus-visible\\\\:ring-destructive\\\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-destructive\\\\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.focus-visible\\\\:ring-ring:focus-visible,.focus-visible\\\\:ring-ring\\\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-ring\\\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.focus-visible\\\\:ring-white\\\\/30:focus-visible{--tw-ring-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-white\\\\/30:focus-visible{--tw-ring-color:color-mix(in oklab,var(--color-white)30%,transparent)}}.focus-visible\\\\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\\\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\\\\:ring-offset-transparent:focus-visible{--tw-ring-offset-color:transparent}.focus-visible\\\\:outline-1:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}.focus-visible\\\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\\\\:scale-\\\\[0\\\\.98\\\\]:active{scale:.98}.active\\\\:cursor-grabbing:active{cursor:grabbing}.active\\\\:bg-white\\\\/15:active{background-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.active\\\\:bg-white\\\\/15:active{background-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.active\\\\:bg-white\\\\/20:active{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.active\\\\:bg-white\\\\/20:active{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.disabled\\\\:pointer-events-none:disabled{pointer-events:none}.disabled\\\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\\\:opacity-40:disabled{opacity:.4}.disabled\\\\:opacity-50:disabled{opacity:.5}.has-\\\\[\\\\>svg\\\\]\\\\:px-2\\\\.5:has(>svg){padding-inline:calc(var(--spacing)*2.5)}.has-\\\\[\\\\>svg\\\\]\\\\:px-3:has(>svg){padding-inline:calc(var(--spacing)*3)}.has-\\\\[\\\\>svg\\\\]\\\\:px-4:has(>svg){padding-inline:calc(var(--spacing)*4)}.aria-invalid\\\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\\\:ring-destructive\\\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\\\\:ring-destructive\\\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.data-\\\\[orientation\\\\=horizontal\\\\]\\\\:h-px[data-orientation=horizontal]{height:1px}.data-\\\\[orientation\\\\=horizontal\\\\]\\\\:w-full[data-orientation=horizontal]{width:100%}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:h-full[data-orientation=vertical]{height:100%}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:w-px[data-orientation=vertical]{width:1px}.data-\\\\[state\\\\=open\\\\]\\\\:bg-accent[data-state=open]{background-color:var(--accent)}.data-\\\\[state\\\\=open\\\\]\\\\:text-muted-foreground[data-state=open]{color:var(--muted-foreground)}@media (min-width:40rem){.sm\\\\:flex{display:flex}.sm\\\\:h-3{height:calc(var(--spacing)*3)}.sm\\\\:h-3\\\\.5{height:calc(var(--spacing)*3.5)}.sm\\\\:h-4{height:calc(var(--spacing)*4)}.sm\\\\:h-7{height:calc(var(--spacing)*7)}.sm\\\\:max-h-24{max-height:calc(var(--spacing)*24)}.sm\\\\:max-h-32{max-height:calc(var(--spacing)*32)}.sm\\\\:max-h-48{max-height:calc(var(--spacing)*48)}.sm\\\\:min-h-7{min-height:calc(var(--spacing)*7)}.sm\\\\:w-3{width:calc(var(--spacing)*3)}.sm\\\\:w-3\\\\.5{width:calc(var(--spacing)*3.5)}.sm\\\\:w-4{width:calc(var(--spacing)*4)}.sm\\\\:w-7{width:calc(var(--spacing)*7)}.sm\\\\:max-w-3xl{max-width:var(--container-3xl)}.sm\\\\:max-w-16{max-width:calc(var(--spacing)*16)}.sm\\\\:max-w-24{max-width:calc(var(--spacing)*24)}.sm\\\\:max-w-lg{max-width:var(--container-lg)}.sm\\\\:max-w-md{max-width:var(--container-md)}.sm\\\\:min-w-7{min-width:calc(var(--spacing)*7)}.sm\\\\:flex-row{flex-direction:row}.sm\\\\:justify-end{justify-content:flex-end}.sm\\\\:gap-1{gap:calc(var(--spacing)*1)}.sm\\\\:gap-1\\\\.5{gap:calc(var(--spacing)*1.5)}.sm\\\\:p-1{padding:calc(var(--spacing)*1)}.sm\\\\:p-1\\\\.5{padding:calc(var(--spacing)*1.5)}.sm\\\\:px-2{padding-inline:calc(var(--spacing)*2)}.sm\\\\:py-1{padding-block:calc(var(--spacing)*1)}.sm\\\\:text-left{text-align:left}.sm\\\\:opacity-0{opacity:0}@media (hover:hover){.sm\\\\:group-hover\\\\:opacity-100:is(:where(.group):hover *){opacity:1}}}.dark\\\\:border-input:is(.dark *){border-color:var(--input)}.dark\\\\:border-muted-foreground\\\\/15:is(.dark *){border-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:border-muted-foreground\\\\/15:is(.dark *){border-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.dark\\\\:border-zinc-600:is(.dark *){border-color:var(--color-zinc-600)}.dark\\\\:border-zinc-700\\\\/80:is(.dark *){border-color:#3f3f46cc}@supports (color:color-mix(in lab, red, red)){.dark\\\\:border-zinc-700\\\\/80:is(.dark *){border-color:color-mix(in oklab,var(--color-zinc-700)80%,transparent)}}.dark\\\\:bg-destructive\\\\/60:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-destructive\\\\/60:is(.dark *){background-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.dark\\\\:bg-input\\\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-input\\\\/30:is(.dark *){background-color:color-mix(in oklab,var(--input)30%,transparent)}}.dark\\\\:bg-muted-foreground\\\\/20:is(.dark *){background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-muted-foreground\\\\/20:is(.dark *){background-color:color-mix(in oklab,var(--muted-foreground)20%,transparent)}}.dark\\\\:bg-zinc-700:is(.dark *){background-color:var(--color-zinc-700)}.dark\\\\:bg-zinc-800:is(.dark *){background-color:var(--color-zinc-800)}.dark\\\\:stroke-\\\\[2\\\\.5px\\\\]:is(.dark *){stroke-width:2.5px}.dark\\\\:text-green-400:is(.dark *){color:var(--color-green-400)}.dark\\\\:text-zinc-200:is(.dark *){color:var(--color-zinc-200)}.dark\\\\:text-zinc-400:is(.dark *){color:var(--color-zinc-400)}.dark\\\\:shadow-black\\\\/30:is(.dark *){--tw-shadow-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.dark\\\\:shadow-black\\\\/30:is(.dark *){--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)30%,transparent)var(--tw-shadow-alpha),transparent)}}@media (hover:hover){.dark\\\\:hover\\\\:bg-accent\\\\/50:is(.dark *):hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-accent\\\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.dark\\\\:hover\\\\:bg-input\\\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-input\\\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--input)50%,transparent)}}.dark\\\\:hover\\\\:bg-muted-foreground\\\\/30:is(.dark *):hover{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-muted-foreground\\\\/30:is(.dark *):hover{background-color:color-mix(in oklab,var(--muted-foreground)30%,transparent)}}.dark\\\\:hover\\\\:bg-zinc-600:is(.dark *):hover{background-color:var(--color-zinc-600)}.dark\\\\:hover\\\\:bg-zinc-700:is(.dark *):hover{background-color:var(--color-zinc-700)}.dark\\\\:hover\\\\:text-zinc-200:is(.dark *):hover{color:var(--color-zinc-200)}}.dark\\\\:focus-visible\\\\:ring-destructive\\\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:focus-visible\\\\:ring-destructive\\\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.dark\\\\:aria-invalid\\\\:ring-destructive\\\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:aria-invalid\\\\:ring-destructive\\\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.\\\\[\\\\&_svg\\\\]\\\\:pointer-events-none svg{pointer-events:none}.\\\\[\\\\&_svg\\\\]\\\\:shrink-0 svg{flex-shrink:0}.\\\\[\\\\&_svg\\\\]\\\\:text-background svg{color:var(--background)}.\\\\[\\\\&_svg\\\\]\\\\:text-black svg{color:var(--color-black)}@media (hover:hover){.hover\\\\:\\\\[\\\\&_svg\\\\]\\\\:text-destructive:hover svg{color:var(--destructive)}}.\\\\[\\\\&_svg\\\\:not\\\\(\\\\[class\\\\*\\\\=\\\\'size-\\\\'\\\\]\\\\)\\\\]\\\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\\\[\\\\&\\\\:last-child\\\\>td\\\\:first-child\\\\]\\\\:rounded-bl-lg:last-child>td:first-child{border-bottom-left-radius:var(--radius)}.\\\\[\\\\&\\\\:last-child\\\\>td\\\\:last-child\\\\]\\\\:rounded-br-lg:last-child>td:last-child{border-bottom-right-radius:var(--radius)}.only\\\\:\\\\[\\\\&\\\\>\\\\#attachment-tile\\\\]\\\\:size-24:only-child>#attachment-tile{width:calc(var(--spacing)*24);height:calc(var(--spacing)*24)}.\\\\[\\\\&\\\\>a\\\\]\\\\:text-xs>a{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\\\[\\\\&\\\\>a\\\\]\\\\:no-underline>a{text-decoration-line:none}.\\\\[\\\\&\\\\>button\\\\]\\\\:rounded-full>button{border-radius:3.40282e38px}.\\\\[\\\\&\\\\>button\\\\]\\\\:bg-foreground\\\\/60>button{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.\\\\[\\\\&\\\\>button\\\\]\\\\:bg-foreground\\\\/60>button{background-color:color-mix(in oklab,var(--foreground)60%,transparent)}}.\\\\[\\\\&\\\\>button\\\\]\\\\:p-1>button{padding:calc(var(--spacing)*1)}.\\\\[\\\\&\\\\>button\\\\]\\\\:opacity-100>button{opacity:1}.\\\\[\\\\&\\\\>button\\\\]\\\\:\\\\!ring-0>button{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)!important}@media (hover:hover){.\\\\[\\\\&\\\\>button\\\\]\\\\:hover\\\\:\\\\[\\\\&_svg\\\\]\\\\:text-destructive>button:hover svg{color:var(--destructive)}}.\\\\[\\\\&\\\\>li\\\\]\\\\:mt-0\\\\.5>li{margin-top:calc(var(--spacing)*.5)}.\\\\[\\\\&\\\\>li\\\\]\\\\:mt-1>li{margin-top:calc(var(--spacing)*1)}.\\\\[\\\\&\\\\>span\\\\]\\\\:text-xs>span{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\\\[\\\\&\\\\[align\\\\=center\\\\]\\\\]\\\\:text-center[align=center]{text-align:center}.\\\\[\\\\&\\\\[align\\\\=right\\\\]\\\\]\\\\:text-right[align=right]{text-align:right}}@keyframes shimmer{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes subtle-pulse{0%,to{opacity:1}50%{opacity:.85}}@keyframes smooth-slide-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes gradient-shift{0%,to{transform:translate(0%)translateY(0%)}25%{transform:translate(100%)translateY(100%)}50%{transform:translate(100%)translateY(0%)}75%{transform:translate(0%)translateY(100%)}}@keyframes float{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(-30px)translate(20px)}66%{transform:translateY(20px)translate(-20px)}}@keyframes float-delayed{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(30px)translate(-30px)}66%{transform:translateY(-20px)translate(20px)}}.tool-card-transition{transition:all .4s cubic-bezier(.34,1.56,.64,1)}.tool-card-smooth{transition:all .35s cubic-bezier(.4,0,.2,1)}.animate-fadeInUp{opacity:0;animation:.5s ease-out forwards fadeInUp}.animate-gradient-shift{background-size:200% 200%;animation:20s ease-in-out infinite gradient-shift}.animate-float-slow{animation:20s ease-in-out infinite float}.animate-float-delayed{animation:25s ease-in-out 5s infinite float-delayed}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@keyframes tool-border-rotate{0%{--tool-border-angle:0deg}to{--tool-border-angle:360deg}}@property --tool-border-angle{syntax:\\\"<angle>\\\";inherits:false;initial-value:0deg}.tool-border-calling{background:conic-gradient(from var(--tool-border-angle),transparent 0deg,transparent 60deg,#3b82f680 90deg,#60a5fab3 120deg,#93c5fd80 150deg,transparent 180deg,transparent 360deg);animation:1.5s linear infinite tool-border-rotate}.tool-border-success{background:#22c55e66;box-shadow:0 0 12px #22c55e4d,inset 0 0 8px #22c55e1a}.tool-border-error{background:#ef444466;box-shadow:0 0 12px #ef44444d,inset 0 0 8px #ef44441a}@keyframes pulse-success{0%,to{box-shadow:0 0 #22c55e66}50%{box-shadow:0 0 0 8px #22c55e00}}@keyframes shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.animate-pulse-success{animation:.6s ease-out pulse-success}.animate-shake{animation:.3s ease-out shake}@keyframes aui-pulse{50%{opacity:.5}}:where(.aui-md[data-status=running]):empty:after,:where(.aui-md[data-status=running])>:where(:not(ol):not(ul):not(pre)):last-child:after,:where(.aui-md[data-status=running])>pre:last-child code:after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child:not(:has(*>li))):after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child:not(:has(*>li))):after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child):after{--aui-content:\\\"●\\\";content:var(--aui-content);margin-left:.25rem;margin-right:.25rem;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;animation:2s cubic-bezier(.4,0,.6,1) infinite aui-pulse}.glass-pill{-webkit-backdrop-filter:blur(20px)saturate(150%);background:#0f172ad9;border:1px solid #ffffff0f;box-shadow:0 4px 16px #0003,inset 0 .5px #ffffff14}.glass-pill:before{content:\\\"\\\";border-radius:inherit;pointer-events:none;z-index:1;background:linear-gradient(#ffffff0a 0%,#0000 40%);position:absolute;inset:0}.glass-pill:after{display:none}.glass-pill-collapsed{-webkit-backdrop-filter:blur(20px)saturate(150%);background:#0f172ad9;border:1px solid #ffffff0f;box-shadow:0 2px 8px #0003,inset 0 .5px #ffffff14}.glass-pill-collapsed:before,.glass-pill-collapsed:after{display:none}.glass-pill-hovered{-webkit-backdrop-filter:blur(16px)saturate(140%);background:#0f172acc;border:1px solid #ffffff0f;box-shadow:0 2px 12px #0000002e}.glass-pill-hovered:before,.glass-pill-hovered:after{display:none}@keyframes glass-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.glass-shimmer{background:linear-gradient(90deg,#ffffff14 0%,#ffffff26 50%,#ffffff14 100%) 0 0/200% 100%;animation:4s ease-in-out infinite glass-shimmer}.scrollbar-thin{scrollbar-width:thin;scrollbar-color:#fff3 transparent}.scrollbar-thin::-webkit-scrollbar{width:4px;height:4px}.scrollbar-thin::-webkit-scrollbar-thumb{background-color:#fff3;border-radius:9999px}.scrollbar-thin::-webkit-scrollbar-track{background-color:#0000}.scroll-touch{-webkit-overflow-scrolling:touch;overscroll-behavior:contain}@media (hover:none){.scrollbar-thin{scrollbar-width:none}.scrollbar-thin::-webkit-scrollbar{display:none}}.scroll-fade-y{-webkit-mask-image:linear-gradient(#0000,#000 8px calc(100% - 8px),#0000);mask-image:linear-gradient(#0000,#000 8px calc(100% - 8px),#0000)}.pb-safe{padding-bottom:env(safe-area-inset-bottom,0px)}.mb-safe{margin-bottom:env(safe-area-inset-bottom,0px)}.bottom-safe{bottom:max(1rem,env(safe-area-inset-bottom,0px))}@supports (padding-bottom:env(safe-area-inset-bottom)){.pill-safe-bottom{padding-bottom:calc(env(safe-area-inset-bottom,0px) + .5rem)}}@property --tw-border-spacing-x{syntax:\\\"<length>\\\";inherits:false;initial-value:0}@property --tw-border-spacing-y{syntax:\\\"<length>\\\";inherits:false;initial-value:0}@property --tw-translate-x{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-translate-y{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-translate-z{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-scale-x{syntax:\\\"*\\\";inherits:false;initial-value:1}@property --tw-scale-y{syntax:\\\"*\\\";inherits:false;initial-value:1}@property --tw-scale-z{syntax:\\\"*\\\";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:\\\"*\\\";inherits:false}@property --tw-rotate-y{syntax:\\\"*\\\";inherits:false}@property --tw-rotate-z{syntax:\\\"*\\\";inherits:false}@property --tw-skew-x{syntax:\\\"*\\\";inherits:false}@property --tw-skew-y{syntax:\\\"*\\\";inherits:false}@property --tw-space-y-reverse{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-border-style{syntax:\\\"*\\\";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:\\\"*\\\";inherits:false}@property --tw-gradient-from{syntax:\\\"<color>\\\";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:\\\"<color>\\\";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:\\\"<color>\\\";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:\\\"*\\\";inherits:false}@property --tw-gradient-via-stops{syntax:\\\"*\\\";inherits:false}@property --tw-gradient-from-position{syntax:\\\"<length-percentage>\\\";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:\\\"<length-percentage>\\\";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:\\\"<length-percentage>\\\";inherits:false;initial-value:100%}@property --tw-leading{syntax:\\\"*\\\";inherits:false}@property --tw-font-weight{syntax:\\\"*\\\";inherits:false}@property --tw-tracking{syntax:\\\"*\\\";inherits:false}@property --tw-ordinal{syntax:\\\"*\\\";inherits:false}@property --tw-slashed-zero{syntax:\\\"*\\\";inherits:false}@property --tw-numeric-figure{syntax:\\\"*\\\";inherits:false}@property --tw-numeric-spacing{syntax:\\\"*\\\";inherits:false}@property --tw-numeric-fraction{syntax:\\\"*\\\";inherits:false}@property --tw-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\\\"*\\\";inherits:false}@property --tw-shadow-alpha{syntax:\\\"<percentage>\\\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\\\"*\\\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\\\"<percentage>\\\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\\\"*\\\";inherits:false}@property --tw-ring-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\\\"*\\\";inherits:false}@property --tw-inset-ring-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\\\"*\\\";inherits:false}@property --tw-ring-offset-width{syntax:\\\"<length>\\\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\\\"*\\\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\\\"*\\\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\\\"*\\\";inherits:false}@property --tw-brightness{syntax:\\\"*\\\";inherits:false}@property --tw-contrast{syntax:\\\"*\\\";inherits:false}@property --tw-grayscale{syntax:\\\"*\\\";inherits:false}@property --tw-hue-rotate{syntax:\\\"*\\\";inherits:false}@property --tw-invert{syntax:\\\"*\\\";inherits:false}@property --tw-opacity{syntax:\\\"*\\\";inherits:false}@property --tw-saturate{syntax:\\\"*\\\";inherits:false}@property --tw-sepia{syntax:\\\"*\\\";inherits:false}@property --tw-drop-shadow{syntax:\\\"*\\\";inherits:false}@property --tw-drop-shadow-color{syntax:\\\"*\\\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\\\"<percentage>\\\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\\\"*\\\";inherits:false}@property --tw-duration{syntax:\\\"*\\\";inherits:false}@property --tw-ease{syntax:\\\"*\\\";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}\";\n\n/**\n * Inject the WebMCP styles into the document head.\n * This is called automatically when registering the web component.\n */\nexport function injectStyles(): void {\n\tif (typeof document === 'undefined') return\n\n\tconst styleId = 'webmcp-agent-styles'\n\tif (document.getElementById(styleId)) return\n\n\tconst style = document.createElement('style')\n\tstyle.id = styleId\n\tstyle.textContent = WEBMCP_STYLES\n\tdocument.head.appendChild(style)\n}\n","/**\n * WebMCP Agent\n *\n * An Intercom-like AI chat widget with MCP tool support and voice mode.\n * Drop it into your app and you're done - no configuration needed.\n *\n * @example Web Component (simplest)\n * ```html\n * <script src=\"https://cdn.webmcp.ai/agent.js\"></script>\n * <webmcp-agent app-id=\"your-app-id\"></webmcp-agent>\n * ```\n *\n * @example React Component\n * ```tsx\n * import { EmbeddedAgent } from '@mcp-b/embedded-agent'\n * import '@mcp-b/embedded-agent/styles'\n *\n * function App() {\n * return <EmbeddedAgent appId=\"your-app-id\" />\n * }\n * ```\n *\n * @example Development mode (use your own API keys)\n * ```tsx\n * <EmbeddedAgent\n * appId=\"your-app-id\"\n * devMode={{\n * anthropicApiKey: \"sk-ant-...\",\n * openaiApiKey: \"sk-...\" // Optional, for voice mode\n * }}\n * />\n * ```\n *\n */\n\nimport r2wc from '@r2wc/react-to-web-component'\n\nimport { AgentPill } from './components/pill'\nimport { AgentProvider } from './core/providers/AgentProvider'\nimport { injectStyles } from './generated/inline-styles'\nimport { WEBMCP_PRODUCTION_API_BASE } from './lib/constants'\n\nimport type { FC } from 'react'\n\n/**\n * Get the default API base URL based on build environment.\n * - Production builds: use the production WebMCP API\n * - Development builds: use current origin (for local dev server)\n */\nconst getDefaultApiBase = (): string => {\n\tif (process.env.NODE_ENV === 'production') {\n\t\treturn WEBMCP_PRODUCTION_API_BASE\n\t}\n\t// In development, use current origin (works with local dev server)\n\treturn typeof window !== 'undefined' ? window.location.origin : WEBMCP_PRODUCTION_API_BASE\n}\n\n/**\n * Development mode configuration\n *\n * In dev mode, you provide your own API keys for testing.\n * Requests still go through WebMCP infrastructure (Cloudflare Workers),\n * but use your keys so there's no cost to us during development.\n */\nexport interface DevModeConfig {\n\t/** Your Anthropic API key for chat (required for dev mode) */\n\tanthropicApiKey: string\n\t/** Your OpenAI API key for voice mode (optional) */\n\topenaiApiKey?: string\n}\n\n/**\n * Props for the EmbeddedAgent component\n */\nexport interface EmbeddedAgentProps {\n\t/** Your WebMCP app ID - get one at webmcp.ai */\n\tappId: string\n\n\t/**\n\t * Development mode - use your own API keys for testing.\n\t * In production, leave this undefined to use your WebMCP plan.\n\t */\n\tdevMode?: DevModeConfig\n}\n\n/**\n * EmbeddedAgent - Drop-in AI chat widget\n *\n * A fully self-contained chat widget with:\n * - MCP tool support (connect to any MCP server)\n * - Voice mode (talk to your AI assistant)\n * - Action-first UI (shows what the AI is doing, not just typing)\n *\n * Just add your app ID and you're done. Everything else is handled.\n */\nexport const EmbeddedAgent: FC<EmbeddedAgentProps> = ({ appId, devMode }) => {\n\t// API base: production URL in prod builds, current origin in dev builds\n\tconst apiBase = getDefaultApiBase()\n\n\t// Log initialization\n\tif (typeof window !== 'undefined') {\n\t\tconsole.debug('[WebMCP] Initialized', {\n\t\t\tappId,\n\t\t\tmode: devMode ? 'development' : 'production',\n\t\t\tapiBase,\n\t\t})\n\t}\n\n\t// Voice is enabled if we have an OpenAI key in dev mode, or in production (uses plan)\n\tconst voiceEnabled = !devMode || !!devMode.openaiApiKey\n\n\treturn (\n\t\t<AgentProvider\n\t\t\tapiBase={apiBase}\n\t\t\ttokenEndpoint={voiceEnabled ? `${apiBase}/api/realtime/session` : undefined}\n\t\t\tautoConnectLocal={true}\n\t\t>\n\t\t\t<AgentPill position=\"bottom-center\" showVoiceButton={voiceEnabled} />\n\t\t</AgentProvider>\n\t)\n}\n\n/**\n * Web Component wrapper\n *\n * Converts EmbeddedAgent to a <webmcp-agent> custom element.\n * Attributes map to props in kebab-case (app-id -> appId).\n */\nconst WebMCPAgentElement = r2wc(EmbeddedAgent as unknown as Parameters<typeof r2wc>[0], {\n\tprops: {\n\t\tappId: 'string',\n\t\t// Note: devMode is JSON-stringified when passed as attribute\n\t\t// <webmcp-agent dev-mode='{\"anthropicApiKey\": \"sk-...\"}'>\n\t\tdevMode: 'json',\n\t},\n})\n\n/**\n * Register the <webmcp-agent> custom element\n *\n * Called automatically when importing this module.\n * Styles are injected into the document head.\n */\nexport function registerWebMCPAgent(tagName = 'webmcp-agent'): void {\n\tif (typeof window === 'undefined') return\n\n\tinjectStyles()\n\n\tif (!customElements.get(tagName)) {\n\t\tcustomElements.define(tagName, WebMCPAgentElement)\n\t}\n}\n\n// Auto-register on import\nregisterWebMCPAgent()\n"],"mappings":"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"}
1
+ {"version":3,"file":"web-component.js","names":["GESTURE_CONFIG","dragActivationDistance","swipe","minDistance","minVelocity","velocityOnlyThreshold","const","PILL_CONTAINER_SIZES","collapsed","width","min","vw","max","height","hovered","composing","active","expanded","clampSize","config","AUTO_COLLAPSE_TIMEOUT_MS","COMPOSER_MAX_CHARS","PILL_BORDER_RADIUS","pill","rounded","inner","small","PILL_SPACING","xs","sm","md","lg","xl","PILL_MAX_HEIGHTS","tools","mobile","desktop","summary","composer","MAX_PROMPT_BUBBLES","UI_TIMING","hoverDebounce","collapseDelay","copyFeedback","KEYBOARD_VISIBILITY_THRESHOLD_PX","KEYBOARD_GAP_PX","DRAG_OPACITY","dragging","normal","FULL_SCREEN_CONFIG","maxWidth","widthPercent","heightPercent","padding","PINCH_GESTURE_CONFIG","threshold","minInitialDistance","ARIA_IDS","pillTitle","pillDescription","liveRegion","ARIA_LABELS","openAssistant","closeAssistant","endVoiceSession","dragHandle","sendMessage","voiceInput","expandFullScreen","collapseFullScreen","WEBMCP_PRODUCTION_API_BASE","MCP_MAX_RECONNECT_ATTEMPTS","MCP_BASE_RECONNECT_DELAY_MS","MCP_MAX_RECONNECT_DELAY_MS","MCP_TAB_CONNECT_DELAY_MS","AUDIO_FREQUENCY_BINS","REALTIME_DEFAULT_MODEL","REALTIME_DEFAULT_VOICE","REALTIME_DEFAULT_API_URL","AUDIO_VISUALIZATION_INTERVAL_MS","RESPONSE_REQUEST_DELAY_MS","TOOL_CALL_DISPLAY_DURATION_MS","TOOL_CALL_ERROR_DISPLAY_DURATION_MS","VOICE_ACTIONS_RETENTION_MS","VOICE_SUMMARY_RETENTION_MS","VOICE_APPROVAL_TIMEOUT_MS","VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS","VOICE_APPROVAL_KEYWORDS","approve","deny","VOICE_TOOL_RESULT_MESSAGES","handled","sessionEnded","WAVEFORM_HISTORY_SIZE","WAVEFORM_UPDATE_RATE_MS","WEBSOCKET_OPEN","DEBUG_LOGGING_ENABLED","window","__WEBMCP_DEBUG__","debugLog","component","message","data","isDebugEnabled","undefined","console","log","clsx","twMerge","ClassValue","cn","inputs","c","_c","memo","ReactMarkdown","remarkGfm","cn","FC","HTMLAttributes","Components","PillMarkdownProps","content","className","compact","ElementProps","HTMLElement","PillMarkdown","t0","$","t1","t2","t3","t4","t5","t6","t7","t8","cn_","props","t9","cn__0","props_0","t10","cn__1","props_1","t11","cn__2","props_2","t12","cn__3","props_3","t13","cn__4","props_4","t14","cn__5","props_5","cn__7","props_7","cn__8","props_8","isInline","includes","cn__9","props_9","h1","h2","h3","p","a","ul","ol","li","_temp","blockquote","code","pre","hr","_temp2","strong","_temp3","em","_temp4","components","Symbol","for","t15","t16","displayName","cn__6","props_6","cn__10","props_10","cn__11","props_11","cn__12","props_12","c","_c","useThread","AlertCircle","Check","CheckCircle2","Copy","useCallback","useMemo","useState","UI_TIMING","cn","PillMarkdown","FC","ReactNode","SummaryBlockProps","summary","isSuccess","isError","actions","QuickAction","className","isFullScreen","label","onClick","variant","SummaryBlock","t0","$","t1","undefined","copied","setCopied","t2","navigator","clipboard","writeText","setTimeout","copyFeedback","handleCopy","t3","t4","e","stopPropagation","t5","Symbol","for","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","length","map","_temp","t16","TextPart","type","text","useLatestSummary","messages","_temp2","bb0","lastAssistantMessage","reverse","find","_temp3","textParts","content","filter","_temp4","lastText","at","m","role","thread","WelcomeMessage","ThreadContent","empty","running","complete","_temp5","lastMessage","isRunning","status","action","i","e_0","humanizeToolName","name","progressive","words","replace","toLowerCase","split","length","verb","progressiveVerb","endsWith","slice","charAt","toUpperCase","join","formatArgs","args","Record","entries","Object","map","key","value","displayValue","JSON","stringify","TOOL_DENIED_MESSAGE","formatToolDenialWithReason","reason","useThread","useMemo","humanizeToolName","ToolCallMetadata","Action","id","label","toolName","status","args","result","error","startedAt","duration","sourceId","wasAborted","ToolCallPart","type","toolCallId","artifact","isError","isToolCallMetadata","a","Record","useActions","$","_c","messages","_temp","t0","bb0","length","t1","Symbol","for","actions","message","role","part","content","toolPart","isComplete","undefined","hasError","requiresAction","metadata","push","String","thread","useCurrentAction","find","_temp2","useRecentActions","limit","filter","_temp3","slice","useLastCompletedAction","completed","_temp4","at","TabClientTransport","SSEClientTransport","StreamableHTTPClientTransport","MCPSourceConfig","Transport","TransportType","createMCPTransport","config","transportType","type","targetOrigin","window","location","origin","channelId","serverUrl","URL","url","headers","Record","Accept","customHeaders","authToken","Authorization","transportOptions","requestInit","shouldFallbackToSSE","error","Error","message","includes","calculateReconnectDelay","attempt","baseDelay","maxDelay","Math","min","pow","Client","PromptListChangedNotificationSchema","ToolListChangedNotificationSchema","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","MCP_TAB_CONNECT_DELAY_MS","createMCPTransport","CallToolResult","GetPromptResult","MCPSource","MCPSourceConfig","Prompt","Resource","ResourceTemplate","ToolWithSource","Transport","ReactNode","SOURCE_LOCAL","SOURCE_REMOTE","SourceState","Omit","client","transport","resources","resourceTemplates","prompts","InflightToolCall","toolName","sourceId","abortController","AbortController","MCPToolsContextValue","tools","sources","Map","addSource","id","config","Promise","removeSource","getSource","isConnected","callTool","name","args","Record","callToolOnSource","getPrompt","MCPToolsContext","MCPToolsProviderProps","children","autoConnectLocal","onToolsChange","onPromptsChange","MCPToolsProvider","sourcesRef","inflightCallsRef","callIdCounterRef","forceUpdate","toolsList","setToolsList","promptsList","setPromptsList","abortOrphanedCalls","currentTools","currentToolNames","Set","map","t","current","forEach","call","callId","has","console","warn","abort","Error","delete","rebuildTools","allTools","source","tool","push","_sourceId","rebuildPrompts","allPrompts","prompt","getPublicSource","state","error","sourceState","set","version","connect","listTools","listPrompts","err","setNotificationHandler","updated","String","get","close","undefined","abortPromise","_","reject","signal","aborted","reason","addEventListener","once","result","race","arguments","content","type","const","text","message","isError","find","values","hasPrompt","some","p","publicSources","timer","setTimeout","clearTimeout","inflightCalls","clear","catch","value","useMCPTools","context","useOptionalMCPTools","ThreadAssistantMessage","ThreadRuntime","PendingToolCallInfo","messageId","toolCallId","toolName","args","Record","getPendingToolCalls","threadRuntime","messages","getState","result","msg","role","assistantMsg","status","type","part","content","undefined","push","id","getPendingToolCallsByName","filter","tc","resolvePendingToolCall","messageRuntime","getMessageById","partRuntime","getMessagePartByToolCallId","addToolResult","resolveAllPendingToolCallsByName","pendingCalls","resolved","call","resolveAllPendingToolCalls","createContext","useCallback","useContext","useEffect","useMemo","useState","Tool","ToolApprovalMode","ToolApprovalSettings","ReactNode","STORAGE_KEY","DEFAULT_MODE","ToolApprovalContextValue","setMode","mode","toggleMode","requiresApproval","tool","isDestructive","ToolApprovalContext","ToolApprovalProviderProps","children","defaultMode","disablePersistence","onModeChange","checkIsDestructive","annotations","readOnlyHint","destructiveHint","ToolApprovalProvider","setModeState","stored","localStorage","getItem","setItem","newMode","value","useToolApproval","context","Error","useOptionalToolApproval","debugLog","AudioAnalyzer","audioContext","AudioContext","analyser","AnalyserNode","source","MediaStreamAudioSourceNode","dataArray","Uint8Array","ArrayBuffer","animationId","initialize","stream","MediaStream","Promise","audioTracks","getAudioTracks","streamId","id","length","trackInfo","map","t","label","enabled","muted","readyState","state","resume","err","console","warn","createAnalyser","fftSize","smoothingTimeConstant","createMediaStreamSource","connect","bufferLength","frequencyBinCount","sampleRate","contextState","getAudioLevel","getByteFrequencyData","sum","i","average","Math","min","getFrequencyData","bins","Array","fill","result","samplesPerBin","floor","j","push","startAnalysis","callback","level","frequencies","analyze","requestAnimationFrame","stopAnalysis","cancelAnimationFrame","destroy","disconnect","close","EventCallback","IEventEmitter","EventEmitter","listeners","Map","Set","on","event","callback","has","set","get","add","off","delete","emit","data","forEach","error","console","removeAllListeners","clear","listenerCount","size","RESPONSE_REQUEST_DELAY_MS","EventEmitter","ToolManager","FunctionCall","RealtimeMessage","ResponseOutputItem","type","status","name","call_id","arguments","isCompletedFunctionCall","item","MessageHandler","isProcessingResponse","pendingFunctionCalls","Set","responseRequestTimer","ReturnType","setTimeout","hasRequestedResponse","constructor","toolManager","eventEmitter","handleMessage","data","dataChannel","RTCDataChannel","Promise","msg","JSON","parse","error","console","handleResponseCreated","handleResponseDone","handleFunctionCallArguments","handleSpeechEvents","handleAudioEvents","handleTranscriptEvents","handleUserTranscript","handleError","handleSessionEvents","_msg","outputItems","extractResponseOutput","response","hasFunctionCalls","some","length","functionCalls","filter","map","functionCall","has","add","executeFunctionCall","warn","size","requestResponseIfNeeded","r","Record","Array","isArray","output","eventType","emit","log","hasAudio","delta","eventMap","text","transcript","clearTimeout","result","executeToolCall","readyState","stringify","success","send","undefined","sendToolError","String","delete","errorResponse","reset","clear","jsonrepair","FunctionCall","OpenAITool","ToolExecutionResult","RegisteredTool","name","description","inputSchema","Record","ToolExecutor","args","Promise","ToolManager","tools","executor","lastSentToolSignature","setTools","setExecutor","resetSession","console","log","getToolSignature","map","t","sort","join","hasToolsChanged","currentSignature","markToolsSent","formatToolsForOpenAI","builtInTools","type","parameters","properties","required","registeredTools","tool","const","validateToolSchema","schema","result","validateNestedSchemas","Object","entries","filter","prop","p","optional","nullable","key","validated","value","propType","items","warn","executeToolCall","functionCall","arguments","argsString","executeListTools","error","success","repaired","JSON","parse","slice","data","String","toolList","count","length","message","getChangesSummary","added","removed","total","prevTools","split","Boolean","currTools","prevSet","Set","currSet","has","debugLog","REALTIME_DEFAULT_API_URL","REALTIME_DEFAULT_MODEL","REALTIME_DEFAULT_VOICE","RealtimeConfig","RealtimeSession","EphemeralTokenResponse","client_secret","value","hasClientSecret","response","secret","WebRTCManager","tokenEndpoint","constructor","createSession","config","Promise","model","voice","apiUrl","ephemeralKey","getEphemeralToken","pc","RTCPeerConnection","audioElement","createAudioElement","remoteStream","MediaStream","ontrack","e","streams","srcObject","streamId","id","tracks","getTracks","length","localStream","getUserMedia","map","t","kind","enabled","muted","readyState","forEach","track","addTrack","dataChannel","createDataChannel","offer","createOffer","setLocalDescription","sdp","Error","answer","connectToOpenAI","setRemoteDescription","cleanup","stop","remove","close","fetch","method","headers","body","JSON","stringify","ok","errorText","text","console","error","statusText","data","json","HTMLAudioElement","document","createElement","autoplay","style","display","appendChild","navigator","mediaDevices","audio","echoCancellation","noiseSuppression","autoGainControl","baseUrl","RTCSessionDescriptionInit","Authorization","answerSdp","type","const","AUDIO_FREQUENCY_BINS","AUDIO_VISUALIZATION_INTERVAL_MS","debugLog","AudioAnalyzer","EventEmitter","MessageHandler","ToolManager","WebRTCManager","RegisteredTool","ToolExecutor","EventCallback","RealtimeConfig","RealtimeSession","SessionConfig","EMPTY_FREQUENCY_TEMPLATE","Object","freeze","Array","fill","createZeroFrequencyArray","OpenAIRealtimeService","session","webrtcManager","toolManager","messageHandler","eventEmitter","muted","lastState","localAnalyzer","remoteAnalyzer","visualizationInterval","ReturnType","setInterval","sessionStartTime","onToolsChangedCallback","constructor","tokenEndpoint","setTools","tools","isSessionActive","updateSessionTools","setToolExecutor","executor","setExecutor","onToolsChanged","callback","startSession","config","Promise","stopSession","Date","now","emitSessionState","createSession","setupDataChannel","dataChannel","setupPeerConnectionMonitoring","pc","localStream","initializeLocalAnalyzer","remoteStream","initializeRemoteAnalyzer","originalOntrack","ontrack","e","call","streams","console","warn","error","handleSessionError","durationSeconds","Math","floor","clearInterval","destroy","cleanup","reset","resetSession","sendUserMessage","text","Error","message","type","item","role","content","send","JSON","stringify","readyState","getLocalStream","MediaStream","getRemoteStream","toggleMute","audioElement","isMuted","pauseAudio","pause","resumeAudio","play","catch","on","event","off","getSessionStatus","state","isActive","RTCDataChannel","addEventListener","configureSession","MessageEvent","handleMessage","data","emit","RTCPeerConnection","connectionState","iceConnectionState","formatToolsForOpenAI","markToolsSent","sessionConfig","modalities","instructions","getSessionInstructions","voice","tool_choice","turn_detection","threshold","prefix_padding_ms","silence_duration_ms","input_audio_transcription","model","sessionUpdate","changesSummary","getChangesSummary","log","total","added","length","slice","join","removed","String","stream","clonedStream","getAudioTracks","map","t","clone","initialize","startAudioVisualization","logCounter","micLevel","getAudioLevel","micFrequency","getFrequencyData","speakerLevel","speakerFrequency","mic","toFixed","speaker","extra","Record","payload","RealtimeConfig","model","voice","apiUrl","tokenEndpoint","RealtimeSession","pc","RTCPeerConnection","dataChannel","RTCDataChannel","audioElement","HTMLAudioElement","localStream","MediaStream","remoteStream","cleanup","OpenAITool","type","name","description","parameters","properties","Record","required","SessionConfig","modalities","instructions","tools","tool_choice","turn_detection","threshold","prefix_padding_ms","silence_duration_ms","input_audio_transcription","FunctionCall","arguments","call_id","status","ConversationItem","role","content","output","RealtimeMessage","key","ToolExecutionResult","success","data","error","EventCallback","IEventEmitter","on","event","callback","off","emit","AudioLevelData","micLevel","micFrequency","speakerLevel","speakerFrequency","TranscriptData","text","isDone","ToolCallData","toolName","VoiceModeState","isActive","isConnecting","isMuted","isError","connectionState","audioLevel","transcript","toolCall","SessionStateEventData","state","durationSeconds","UserTranscriptEventData","AssistantTranscriptEventData","delta","ToolCallStartedEventData","ToolCallCompletedEventData","NestedErrorObject","code","message","param","event_id","ErrorEventData","isSessionStateEventData","d","includes","isUserTranscriptEventData","isAssistantTranscriptEventData","undefined","isToolCallStartedEventData","isToolCallCompletedEventData","isErrorEventData","hasError","extractErrorMessage","nestedError","isAudioLevelData","Array","isArray","useCallback","useEffect","useMemo","useRef","useState","TOOL_CALL_DISPLAY_DURATION_MS","TOOL_CALL_ERROR_DISPLAY_DURATION_MS","extractErrorMessage","isAssistantTranscriptEventData","isAudioLevelData","isErrorEventData","isSessionStateEventData","isToolCallCompletedEventData","isToolCallStartedEventData","isUserTranscriptEventData","OpenAIRealtimeService","AudioLevelData","RealtimeConfig","RegisteredTool","ToolCallData","ToolExecutor","TranscriptData","VoiceModeState","UseVoiceModeOptions","tokenEndpoint","tools","toolExecutor","onConnect","onDisconnect","durationSeconds","onError","error","onUserTranscript","text","onAssistantTranscript","UseVoiceModeReturn","startSession","config","Promise","stopSession","toggleMute","muted","sendMessage","pauseAudio","resumeAudio","useVoiceMode","options","$","_c","isActive","setIsActive","isConnecting","setIsConnecting","isMuted","setIsMuted","isError","setIsError","connectionState","setConnectionState","audioLevel","setAudioLevel","transcript","setTranscript","toolCall","setToolCall","setError","serviceRef","onConnectRef","onDisconnectRef","onErrorRef","onUserTranscriptRef","onAssistantTranscriptRef","t0","t1","current","t2","getService","t3","t4","service","setTools","t5","t6","service_0","setToolExecutor","t7","t8","service_1","handleSessionState","data","console","warn","state","handleAudioLevel","data_0","handleUserTranscript","data_1","type","isDone","handleAssistantTranscript","data_2","delta","prev","handleAssistantTranscriptDone","data_3","text_0","handleToolCallStarted","data_4","status","toolName","name","handleToolCallCompleted","data_5","setTimeout","undefined","handleError","data_6","errorMsg","on","off","t9","service_2","t10","err","errorMsg_0","Error","message","service_3","t11","service_4","newMuted","t12","text_1","service_5","isSessionActive","sendUserMessage","t13","service_6","t14","service_7","t15","createContext","useContext","useMemo","useVoiceMode","ReactNode","UseVoiceModeReturn","RegisteredTool","ToolExecutor","VoiceModeContextValue","isSupported","VoiceModeContext","VoiceModeProviderProps","children","tokenEndpoint","tools","toolExecutor","onConnect","onDisconnect","durationSeconds","onError","error","onUserTranscript","text","onAssistantTranscript","checkVoiceModeSupport","window","RTCPeerConnection","navigator","mediaDevices","getUserMedia","VoiceModeProvider","t0","$","_c","t1","voiceMode","t2","Symbol","for","t3","value","t4","useVoiceModeContext","context","Error","useOptionalVoiceModeContext","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS","VOICE_APPROVAL_TIMEOUT_MS","FC","ReactNode","VoicePendingApproval","callId","toolName","args","Record","timestamp","VoiceToolApprovalContextValue","pendingApproval","approve","deny","timeoutRemaining","isWaitingForApproval","requestApproval","Promise","clearPendingApproval","VoiceToolApprovalContext","VoiceToolApprovalProviderProps","children","timeout","onTimeout","onApprove","onDeny","VoiceToolApprovalProvider","setPendingApproval","setTimeoutRemaining","resolveRef","approved","timeoutIdRef","ReturnType","setTimeout","countdownIdRef","setInterval","onTimeoutRef","onApproveRef","onDenyRef","current","clearTimers","clearTimeout","clearInterval","resolveApproval","reason","resolve","Date","now","timeoutSeconds","Math","ceil","prev","value","useVoiceToolApproval","context","Error","useOptionalVoiceToolApproval","useThreadRuntime","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","VOICE_TOOL_RESULT_MESSAGES","TOOL_DENIED_MESSAGE","resolveAllPendingToolCalls","resolveAllPendingToolCallsByName","useOptionalMCPTools","useOptionalToolApproval","useOptionalVoiceModeContext","VoiceModeProvider","useOptionalVoiceToolApproval","VoiceToolApprovalProvider","ToolCallMetadata","ToolWithSource","FC","MutableRefObject","ReactNode","RegisteredTool","ToolExecutor","VoiceToolCallData","toolCallId","toolName","args","Record","result","isError","artifact","AddToolCallToThread","data","VoiceMessageMetadata","source","voiceSessionId","timestamp","VoiceThreadContextValue","isActive","isConnecting","isMuted","isSupported","error","sessionId","start","Promise","stop","toggleMute","muted","sendMessage","text","pauseAudio","resumeAudio","audioLevel","micLevel","speakerLevel","transcript","type","isDone","toolCall","status","VoiceThreadContext","generateSessionId","Date","now","Math","random","toString","slice","convertToRegisteredTool","tool","name","description","inputSchema","properties","VoiceThreadBridgeProps","children","tokenEndpoint","onConnect","onDisconnect","durationSeconds","onError","VoiceThreadIntegrator","setSessionId","id","addToolCallRef","threadRuntime","voiceMode","lastUserTranscriptRef","lastAssistantTranscriptRef","wasActiveRef","onConnectRef","onDisconnectRef","onErrorRef","current","console","warn","append","role","content","argsText","JSON","stringify","metadata","custom","addUserMessage","trim","addAssistantMessage","newSessionId","sessionEnded","ApprovalAwareVoiceBridge","voiceTools","t0","$","_c","mcpTools","toolApproval","voiceToolApproval","t1","callTool","Error","tools","find","t","needsApproval","requiresApproval","callId","approved","requestApproval","resultMessage","handled","textContent","_temp","toolExecutor","t2","t3","t4","VoiceThreadBridge","map","VoiceThreadContextProvider","bb0","undefined","t5","startSession","stopSession","contextValue","useVoiceThread","context","useOptionalVoiceThread","useIsVoiceActive","c","useThread","useMemo","useLatestSummary","useActions","useCurrentAction","useLastCompletedAction","useRecentActions","useOptionalMCPTools","useOptionalVoiceThread","CallToolResult","Prompt","ToolWithSource","GetPromptResult","Action","AgentVoice","isActive","isConnecting","isError","isMuted","isSupported","error","sessionId","audioLevel","micLevel","speakerLevel","transcript","type","text","isDone","start","Promise","stop","toggleMute","muted","sendMessage","AgentTools","list","call","name","args","Record","prompts","getPrompt","AgentMessage","id","role","content","status","metadata","AgentState","messages","isRunning","hasMessages","actions","currentAction","recentActions","lastCompletedAction","summary","voice","tools","isVoiceActive","useAgent","$","_c","threadMessages","_temp","_temp2","voiceThread","mcpContext","length","t0","bb0","t1","bb1","t2","t3","callTool","t4","thread_0","thread","createContext","useCallback","useContext","useMemo","useRef","useState","FC","ReactNode","PillMode","Position","x","y","AgentUIState","isOpen","userMode","position","hasUnread","isVoiceActive","isFullScreen","AgentUIContextValue","setOpen","open","toggleOpen","setUserMode","mode","setPosition","resetPosition","markRead","markUnread","setVoiceActive","active","collapse","expand","enterFullScreen","exitFullScreen","toggleFullScreen","AgentUIContext","DEFAULT_POSITION","AgentUIProviderProps","children","defaultOpen","defaultMode","onOpenChange","onModeChange","AgentUIProvider","setIsOpenState","setUserModeState","setPositionState","setHasUnread","setIsVoiceActiveState","setIsFullScreen","onOpenChangeRef","onModeChangeRef","current","prev","next","pos","value","useAgentUI","context","Error","useOptionalAgentUI","usePillMode","useHasUnread","c","_c","useCallback","useEffect","useState","KEYBOARD_VISIBILITY_THRESHOLD_PX","KeyboardState","isKeyboardVisible","keyboardHeight","visibleHeight","useKeyboardAware","$","t0","Symbol","for","window","innerHeight","state","setState","t1","visualViewport","windowHeight","viewportHeight","height","heightDiff","updateKeyboardState","t2","t3","visualViewport_0","addEventListener","removeEventListener","getKeyboardOffset","additionalOffset","c","_c","useEffect","useState","useMobileDetect","$","isMobile","setIsMobile","isTouchDevice","setIsTouchDevice","isCoarsePointer","setIsCoarsePointer","t0","t1","Symbol","for","hasTouch","window","navigator","maxTouchPoints","hoverNone","matchMedia","pointerCoarse","updateState","matches","handleHoverChange","handlePointerChange","addEventListener","removeEventListener","t2","checkIsMobileSSR","useThread","useThreadRuntime","useMemo","ThreadAssistantMessage","PendingToolCallInfo","PendingToolCall","usePendingToolCalls","$","_c","messages","_temp","result","msg","role","assistantMsg","status","type","part","content","undefined","push","messageId","id","toolCallId","toolName","args","Record","t","useHasPendingToolCalls","_temp2","t0","bb0","c","_c","useCallback","useRef","PINCH_GESTURE_CONFIG","TouchEvent","ReactTouchEvent","PinchGestureOptions","onPinchOut","onPinchIn","enabled","threshold","PinchState","initialDistance","lastDistance","isActive","TouchPoint","clientX","clientY","getTouchDistance","touch1","touch2","dx","dy","Math","sqrt","usePinchGesture","t0","$","t1","t2","undefined","t3","Symbol","for","stateRef","t4","e","touches","length","distance","minInitialDistance","current","handleTouchStart","t5","e_0","currentDistance","handleTouchMove","t6","e_1","scaleDelta","handleTouchEnd","t7","handlers","onTouchStart","onTouchMove","onTouchEnd","c","_c","useThread","Camera","FileText","Loader2","MousePointer","Navigation","PenLine","Search","Trash2","Wrench","useMemo","humanizeToolName","cn","LucideIcon","FC","getToolIcon","toolName","name","toLowerCase","includes","ActivityState","type","label","icon","toolNames","streamingText","useActivityState","$","messages","_temp","isRunning","_temp2","t0","bb0","lastAssistantMessage","reverse","find","_temp3","t1","Symbol","for","runningToolNames","lastText","part","content","toolPart","status","push","textPart","text","length","t2","m","role","thread_0","thread","ActivityIndicatorProps","className","ActivityIndicator","activity","Icon","isSpinning","t3","t4","t5","t6","slice","map","_temp4","t7","i","ToolIcon","Shield","ShieldOff","cn","useOptionalToolApproval","FC","ApprovalModeToggleProps","className","ApprovalModeToggle","t0","$","_c","toolApproval","mode","toggleMode","isAskMode","t1","t2","t3","t4","t5","ApprovalModeIndicator","c","_c","AlertCircle","CheckCircle2","Circle","Loader2","cn","FC","Action","CurrentActivityProps","currentAction","recentActions","showRecent","className","CurrentActivity","t0","$","t1","t2","t3","undefined","t4","t5","status","label","t6","length","map","_temp","t7","ActionStatusIconProps","size","ActionStatusIcon","sizeClass","IdleIndicator","Symbol","for","action","id","useAssistantTool","ToolResponse","useMCPTools","useOptionalToolApproval","CallToolResult","ToolCallMetadata","ToolWithSource","ReadonlyJSONValue","FC","formatToolResult","result","textContent","content","map","c","type","text","JSON","stringify","join","ToolBridge","tool","callTool","name","args","Record","Promise","t0","$","_c","t1","description","t2","inputSchema","t3","t4","_sourceId","startedAt","Date","now","isError","wasAborted","some","_temp","metadata_0","duration","sourceId","artifact","metadata","t5","error","console","Error","message","String","toolName","parameters","execute","DestructiveToolBridge","MCPToolRegistry","tools","toolApproval","needsApproval","requiresApproval","includes","useThreadRuntime","AlertTriangle","Check","Loader2","X","useState","usePendingToolCalls","formatArgs","humanizeToolName","TOOL_DENIED_MESSAGE","resolveAllPendingToolCalls","cn","useMCPTools","formatToolResult","FC","ElicitationButtonBarProps","className","ElicitationButtonBar","isExecuting","setIsExecuting","pendingToolCalls","threadRuntime","callTool","tools","length","firstTool","humanizedName","toolName","toolDescription","find","t","name","description","hasArgs","Object","keys","args","formattedArgs","getPartRuntime","messageRuntime","getMessageById","messageId","getMessagePartByToolCallId","toolCallId","handleAccept","toolResult","partRuntime","addToolResult","error","errorMessage","Error","message","String","handleDeny","cancelRun","c","_c","ComposerPrimitive","ThreadPrimitive","useComposer","useComposerRuntime","Mic","Send","Square","useCallback","useRef","useMobileDetect","COMPOSER_MAX_CHARS","cn","FC","PillComposerProps","placeholder","showVoiceButton","isVoiceActive","onVoiceToggle","showCharCount","className","isEliciting","onElicitationSubmit","reason","CharacterCount","$","composer","_temp","charCount","length","isOver","remaining","t0","t1","t2","PillComposer","t3","t4","t5","undefined","isMobile","inputRef","composerRuntime","effectivePlaceholder","t6","current","blur","handleSubmit","t7","text","getState","trim","setText","handleElicitationSubmit","t8","e","key","shiftKey","preventDefault","handleKeyDown","t9","t10","t11","Symbol","for","touchAction","t12","t13","_temp2","t14","t15","t16","t17","t18","t19","e_0","stopPropagation","c","_c","useEffect","useRef","useAriaHidden","isActive","containerRef","$","t0","Symbol","for","Map","modifiedElementsRef","t1","t2","current","forEach","_temp","clear","container","dialogRoot","parentElement","document","body","bodyChildren","Array","from","children","child","tagName","originalValue_0","getAttribute","set","originalValue","setAttribute","_temp2","originalValue_1","element_0","element","removeAttribute","c","_c","useCallback","useEffect","useRef","FOCUSABLE_SELECTOR","join","UseFocusTrapOptions","isActive","onEscape","autoFocus","returnFocus","skipInputFocusReturn","UseFocusTrapReturn","containerRef","React","RefObject","HTMLDivElement","storeTrigger","useFocusTrap","t0","$","t1","t2","t3","undefined","triggerRef","previouslyFocusedRef","t4","Symbol","for","current","document","activeElement","HTMLElement","t5","Array","from","querySelectorAll","getFocusableElements","t6","t7","timeoutId","setTimeout","focusableElements","length","focus","clearTimeout","isConnected","isInputElement","tagName","blur","isInputElement_0","t8","t9","handleKeyDown","event","key","preventDefault","focusableElements_0","firstElement","lastElement","shiftKey","contains","addEventListener","removeEventListener","t10","AnimatePresence","motion","useReducedMotion","useCallback","useEffect","useRef","useState","useAriaHidden","useFocusTrap","useMobileDetect","ARIA_IDS","ARIA_LABELS","clampSize","FULL_SCREEN_CONFIG","PILL_BORDER_RADIUS","PILL_CONTAINER_SIZES","UI_TIMING","cn","Variants","FC","ReactNode","PillMode","PillContainerProps","mode","children","onModeChange","isFullScreen","className","sizeSpring","type","const","stiffness","damping","mass","fullScreenTween","duration","ease","reducedMotionTransition","sizes","containerVariants","Record","width","height","padding","borderRadius","collapsed","pill","hovered","composing","rounded","active","expanded","fullScreenVariant","widthPercent","maxWidth","heightPercent","contentVariants","hidden","opacity","visible","transition","delay","exit","hintVariants","barVariants","idle","scaleX","hover","PillContainer","isHovered","setIsHovered","hoverTimeoutRef","NodeJS","Timeout","prefersReducedMotion","wasFullScreenRef","isTransitioningFullScreen","current","isMobile","isDialogActive","containerRef","focusTrapRef","storeTrigger","isActive","onEscape","autoFocus","returnFocus","skipInputFocusReturn","prevModeRef","wasCollapsedOrHovered","isNowDialog","handleMouseEnter","clearTimeout","setTimeout","hoverDebounce","handleMouseLeave","collapseDelay","handleClick","handleFocus","handleBlur","handleKeyDown","e","KeyboardEvent","isShortcut","ctrlKey","metaKey","shiftKey","key","toLowerCase","isEscape","preventDefault","window","addEventListener","removeEventListener","showContent","currentVariant","isDialogMode","setContainerRef","node","HTMLDivElement","glassClassName","undefined","pillTitle","openAssistant","background","backgroundSize","Slot","cva","React","cn","VariantProps","ButtonProps","ComponentProps","buttonVariants","asChild","variants","variant","default","destructive","outline","secondary","ghost","link","size","sm","lg","icon","defaultVariants","Button","t0","$","_c","className","props","t1","undefined","Comp","t2","t3","c","_c","AlertCircle","AlertTriangle","Check","ChevronDownIcon","ChevronUpIcon","X","useCallback","useState","formatArgs","humanizeToolName","TOOL_DENIED_MESSAGE","cn","useMCPTools","Button","formatToolResult","getToolIcon","ToolCallMessagePartComponent","ApprovedResult","approved","result","isApprovedResult","isDeniedResult","hasStatusError","status","type","error","RunningToolDisplay","React","FC","toolName","t0","$","t1","ToolIcon","t2","t3","t4","t5","ApprovalDialog","toolDescription","inputArgs","Record","onApprove","onDeny","isExecuting","isHovered","setIsHovered","Symbol","for","t6","t7","t8","t9","t10","Object","keys","length","t11","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","t24","t25","CompletedToolDisplay","argsText","isExpanded","setIsExpanded","undefined","JSON","stringify","ErrorToolDisplay","DeniedToolDisplay","UnifiedToolFallback","toolCallId","_toolCallId","args","addResult","callTool","tools","setIsExecuting","parsedArgs","parse","e","console","warn","find","t","name","description","handleApprove","toolResult","errorMessage","Error","message","String","handleDeny","statusType","isPendingApproval","displayResult","c","_c","MessagePrimitive","ThreadPrimitive","UnifiedToolFallback","FC","PillMessageContent","$","t0","Symbol","for","UserMessage","_temp","AssistantMessage","PillAssistantMessage","Text","_temp2","tools","Fallback","c","_c","AlertTriangle","ChevronDown","useEffect","useState","useActions","cn","PillMessageContent","FC","PillToolsSectionProps","defaultCollapsed","className","isFullScreen","PillToolsSection","t0","$","t1","t2","undefined","isCollapsed","setIsCollapsed","actions","t3","filter","_temp","completedCount","length","t4","_temp2","runningCount","t5","_temp3","pendingCount","totalCount","t6","t7","t8","t9","t10","Symbol","for","t11","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","t24","t25","touchAction","t26","t27","_temp4","t28","t29","a","status","a_0","a_1","e","stopPropagation","useEffect","useRef","cn","HTMLAttributes","LiveWaveformProps","HTMLDivElement","active","processing","barWidth","barGap","barRadius","barColor","fadeEdges","fadeWidth","height","sensitivity","smoothingTimeConstant","mode","manualAudioLevel","LiveWaveform","t0","$","_c","className","props","t1","t10","t2","t3","t4","t5","t6","t7","t8","t9","undefined","canvasRef","containerRef","t11","Symbol","for","historyRef","lastUpdateRef","processingAnimationRef","t12","lastActiveDataRef","transitionProgressRef","t13","staticBarsRef","needsRedrawRef","gradientCacheRef","lastWidthRef","heightStyle","t14","t15","canvas","current","container","resizeObserver","ResizeObserver","rect","getBoundingClientRect","dpr","window","devicePixelRatio","width","style","ctx","getContext","scale","observe","disconnect","t16","t17","time","animateProcessing","Math","min","processingData","barCount","floor","halfCount","i","normalizedPosition","centerWeight","abs","wave1","sin","wave2","wave3","cos","combinedWave","processingValue","finalValue","length","lastDataIndex","lastValue","push","max","i_0","normalizedPosition_0","centerWeight_0","wave1_0","wave2_0","wave3_0","combinedWave_0","processingValue_0","finalValue_0","lastDataIndex_0","lastValue_0","requestAnimationFrame","cancelAnimationFrame","hasData","fadeProgress","fadeToIdle","map","value","value_0","t18","t19","canvas_0","ctx_0","rafId","animate","currentTime","rect_0","level","barCount_0","halfCount_0","newBars","i_1","distanceFromCenter","value_1","i_2","distanceFromCenter_0","value_2","shift","clearRect","computedBarColor","getComputedStyle","color","step","barCount_1","centerY","dataToRender","i_3","value_3","x","barHeight","y","fillStyle","globalAlpha","beginPath","roundRect","fill","fillRect","i_4","dataIndex","value_4","x_0","barHeight_0","y_0","gradient","createLinearGradient","fadePercent","addColorStop","globalCompositeOperation","t20","t21","t22","t23","t24","t25","c","_c","AlertTriangle","Check","Loader2","Pause","X","AnimatePresence","motion","useEffect","useState","humanizeToolName","cn","useOptionalVoiceThread","useOptionalVoiceToolApproval","FC","approvalBarVariants","hidden","opacity","height","y","visible","transition","type","const","stiffness","damping","exit","duration","countdownVariants","pulse","scale","repeat","Infinity","PillVoiceApprovalBarProps","className","PillVoiceApprovalBar","t0","$","voiceThread","voiceApproval","isExecuting","setIsExecuting","t1","pendingApproval","pauseAudio","resumeAudio","t2","t3","timeoutRemaining","approve","deny","t4","toolName","t5","handleApprove","t6","handleDeny","t7","t8","Symbol","for","t9","t10","t11","t12","t13","t14","undefined","t15","t16","t17","t18","t19","t20","t21","c","_c","Mic","MicOff","PhoneOff","AnimatePresence","motion","useCallback","cn","useOptionalVoiceThread","useOptionalVoiceToolApproval","LiveWaveform","PillVoiceApprovalBar","FC","ToolBorderStatus","PillVoiceProps","onEnd","compact","className","voiceVariants","hidden","opacity","scale","y","visible","transition","type","const","stiffness","damping","exit","duration","buttonVariants","idle","hover","tap","transcriptVariants","height","voiceToolCallToBorderStatus","toolCall","status","error","PillVoice","t0","$","t1","undefined","voiceThread","voiceToolApproval","t2","clearPendingApproval","stop","handleEnd","t3","toggleMute","handleToggleMute","isActive","isConnecting","isError","isMuted","audioLevel","transcript","isWaitingForApproval","micLevel","speakerLevel","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","t16","t17","Symbol","for","t18","t19","t20","t21","t22","t23","t24","t25","t26","t27","t28","t29","t30","t31","t32","t33","t34","t35","t36","t37","t38","t39","t40","t41","t42","repeat","Infinity","toolName","t43","t44","text","isDone","t45","t46","t47","t48","t49","t50","useVoiceBorderStatus","X","AnimatePresence","motion","useCallback","useState","useMobileDetect","MAX_PROMPT_BUBBLES","cn","Prompt","Variants","FC","MouseEvent","PromptBadgeProps","prompts","onSelect","prompt","className","STAGGER_DELAY","STAGGER_DELAY_INITIAL","STAGGER_DELAY_EXIT","containerVariants","hidden","opacity","visible","transition","staggerChildren","delayChildren","exit","staggerDirection","bubbleVariants","y","scale","type","stiffness","damping","duration","bubbleStyles","dismissBadgeBaseStyles","PromptBadge","t0","$","_c","isDismissed","setIsDismissed","isMobile","t1","handleSelect","t2","Symbol","for","e","stopPropagation","handleDismiss","length","T0","T1","t10","t11","t12","t13","t14","t3","t4","t5","t6","t7","t8","t9","visiblePrompts","slice","t15","t16","t17","dismissBadgeStyles","div","map","prompt_0","index","isMiddleBubble","name","description","AnimatePresence","motion","useCallback","useRef","cn","Prompt","FC","PromptSuggestionsProps","prompts","onSelect","prompt","className","PromptSuggestions","t0","$","_c","scrollRef","t1","handleClick","length","t2","t3","t4","Symbol","for","opacity","height","t5","t6","t7","touchAction","t8","t9","prompt_0","index","name","scale","type","stiffness","damping","delay","description","map","_temp","t10","e","stopPropagation","c","_c","useThread","useMemo","cn","PillMarkdown","FC","TextPart","type","text","useStreamingText","$","messages","_temp","isRunning","_temp2","t0","bb0","lastAssistantMessage","reverse","find","_temp3","textParts","content","filter","_temp4","lastText","at","trim","length","part","m","role","thread_0","thread","StreamingResponseProps","maxHeight","className","isFullScreen","StreamingResponse","t1","t2","undefined","streamingText","t3","t4","t5","t6","t7","Symbol","for","t8","t9","c","_c","AnimatePresence","motion","useEffect","useRef","useState","cn","FC","ReactNode","ToolBorderStatus","ToolStatusBorderProps","status","children","className","borderRadius","borderVariants","idle","opacity","scale","calling","transition","duration","error","shakeAnimation","x","ease","const","ToolStatusBorder","t0","$","t1","undefined","effectiveStatus","t2","t3","t4","t5","t6","t7","t8","useToolBorderStatus","hasRunningAction","lastActionStatus","setStatus","timeoutRef","current","clearTimeout","setTimeout","ThreadPrimitive","useComposerRuntime","useThreadRuntime","Expand","GripHorizontal","Minimize","X","AnimatePresence","motion","useDragControls","useCallback","useEffect","useMemo","useRef","useState","useAgent","useOptionalAgentUI","useKeyboardAware","useMobileDetect","useHasPendingToolCalls","usePendingToolCalls","usePinchGesture","ARIA_LABELS","AUTO_COLLAPSE_TIMEOUT_MS","debugLog","DRAG_OPACITY","GESTURE_CONFIG","KEYBOARD_GAP_PX","PILL_BORDER_RADIUS","formatToolDenialWithReason","resolvePendingToolCall","cn","ActivityIndicator","ApprovalModeIndicator","IdleIndicator","ElicitationButtonBar","PillComposer","PillContainer","PillToolsSection","PillVoice","useVoiceBorderStatus","PromptBadge","PromptSuggestions","StreamingResponse","SummaryBlock","WelcomeMessage","ToolStatusBorder","useToolBorderStatus","Prompt","FC","PillMode","PillPosition","AgentPillProps","position","showVoiceButton","isVoiceActive","onVoiceToggle","autoCollapse","className","AgentPill","agent","messages","isRunning","hasMessages","currentAction","lastCompletedAction","summary","voice","tools","agentVoiceActive","hasPendingApproval","pendingToolCalls","threadRuntime","agentUI","userMode","setUserMode","hasUnread","markRead","markUnread","dragPosition","x","y","setDragPosition","setPosition","resetPosition","isFullScreen","enterFullScreen","exitFullScreen","dragControls","constraintsRef","HTMLDivElement","autoCollapseTimeoutRef","NodeJS","Timeout","lastMessageCountRef","isKeyboardVisible","keyboardHeight","isMobile","prompts","getPrompt","composerRuntime","handleDragEnd","_","info","offset","velocity","dragDistance","Math","sqrt","isExpanded","swipeDistance","swipeVelocity","swipe","isAggressiveSwipe","minDistance","minVelocity","velocityOnlyThreshold","dragActivationDistance","currentCount","length","current","voiceBorderStatus","isVoiceModeActive","textBorderStatus","status","borderStatus","mode","handleModeChange","newMode","handleCollapse","clearTimeout","setTimeout","handleVoiceToggle","isActive","isConnecting","stop","start","handlePromptSelect","prompt","result","name","userMessage","find","m","role","content","textContent","type","text","setText","send","err","handleElicitationDeny","reason","firstTool","message","messageId","toolCallId","borderRadius","pill","rounded","handlers","pinchHandlers","onPinchOut","onPinchIn","enabled","isComposerReady","setComposerReady","timer","handleKeyDown","e","KeyboardEvent","key","preventDefault","window","addEventListener","removeEventListener","scale","opacity","dragging","stiffness","damping","touchAction","dragHandle","collapseFullScreen","expandFullScreen","endVoiceSession","closeAssistant","error","duration","isSupported","AssistantRuntimeProvider","AssistantChatTransport","useChatRuntime","lastAssistantMessageIsCompleteWithToolCalls","useMemo","MCPToolRegistry","WEBMCP_PRODUCTION_API_BASE","MCPToolsProvider","ToolApprovalProvider","VoiceThreadBridge","AgentUIProvider","ToolApprovalMode","ToolWithSource","FC","ReactNode","PillMode","AgentProviderProps","children","apiBase","tokenEndpoint","autoConnectLocal","defaultOpen","defaultMode","defaultApprovalMode","onToolsChange","tools","onVoiceError","error","onVoiceConnect","onVoiceDisconnect","duration","onOpenChange","open","onModeChange","mode","onApprovalModeChange","AgentRuntimeProps","AgentRuntime","t0","$","_c","resolvedApiBase","chatApi","t1","api","transport","t2","sendAutomaticallyWhen","_temp","runtime","resolvedTokenEndpoint","t3","Symbol","for","t4","t5","AgentProvider","undefined","t6","t7","messages","WEBMCP_STYLES","injectStyles","document","styleId","getElementById","style","createElement","id","textContent","head","appendChild","r2wc","AgentPill","AgentProvider","injectStyles","WEBMCP_PRODUCTION_API_BASE","FC","getDefaultApiBase","useLocalApi","window","location","origin","DevModeConfig","anthropicApiKey","openaiApiKey","EmbeddedAgentProps","appId","devMode","EmbeddedAgent","t0","$","_c","apiBase","console","debug","mode","voiceEnabled","t1","undefined","t2","t3","WebMCPAgentElement","Parameters","props","registerWebMCPAgent","tagName","customElements","get","define"],"sources":["../src/lib/constants.ts","../src/lib/utils.ts","../src/components/pill/PillMarkdown.tsx","../src/components/pill/SummaryBlock.tsx","../src/lib/format.ts","../src/hooks/useActions.ts","../src/lib/mcp-transport.ts","../src/providers/MCPToolsProvider.tsx","../src/lib/thread-utils.ts","../src/providers/ToolApprovalProvider.tsx","../src/services/realtime/audio-analyzer.ts","../src/services/realtime/event-emitter.ts","../src/services/realtime/message-handler.ts","../src/services/realtime/tool-manager.ts","../src/services/realtime/webrtc-manager.ts","../src/services/realtime/openai-realtime-service.ts","../src/services/realtime/types.ts","../src/hooks/useVoiceMode.ts","../src/providers/VoiceModeProvider.tsx","../src/providers/VoiceToolApprovalProvider.tsx","../src/providers/VoiceThreadBridge.tsx","../src/core/hooks/useAgent.ts","../src/core/providers/AgentUIProvider.tsx","../src/hooks/useKeyboardAware.ts","../src/hooks/useMobileDetect.ts","../src/hooks/usePendingToolCalls.ts","../src/hooks/usePinchGesture.ts","../src/components/pill/ActivityIndicator.tsx","../src/components/pill/ApprovalModeToggle.tsx","../src/components/pill/CurrentActivity.tsx","../src/components/MCPToolRegistry.tsx","../src/components/pill/ElicitationButtonBar.tsx","../src/components/pill/PillComposer.tsx","../src/hooks/useAriaHidden.ts","../src/hooks/useFocusTrap.ts","../src/components/pill/PillContainer.tsx","../src/components/button.tsx","../src/components/UnifiedToolFallback.tsx","../src/components/pill/PillMessageContent.tsx","../src/components/pill/PillToolsSection.tsx","../src/components/live-waveform.tsx","../src/components/pill/PillVoiceApprovalBar.tsx","../src/components/pill/PillVoice.tsx","../src/components/pill/PromptBadge.tsx","../src/components/pill/PromptSuggestions.tsx","../src/components/pill/StreamingResponse.tsx","../src/components/pill/ToolStatusBorder.tsx","../src/components/pill/AgentPill.tsx","../src/core/providers/AgentProvider.tsx","../src/generated/inline-styles.ts","../src/web-component.tsx"],"sourcesContent":["/**\n * Shared Constants\n *\n * Centralized location for all magic numbers, timeouts, and configuration values.\n * Having these in one place makes the codebase more maintainable and easier to tune.\n */\n\n// ============================================================================\n// Mobile UX Constants\n// ============================================================================\n\n/**\n * Gesture configuration for touch interactions.\n *\n * Mobile swipe-to-dismiss requires an AGGRESSIVE upward swipe to prevent\n * accidental dismisses while allowing intentional quick swipes.\n */\nexport const GESTURE_CONFIG = {\n\t/** Minimum drag distance (px) before it counts as a drag (prevents tap interference) */\n\tdragActivationDistance: 15,\n\n\t/** Swipe-to-dismiss thresholds (mobile only) */\n\tswipe: {\n\t\t/** Must swipe at least this far (px) AND this fast to dismiss */\n\t\tminDistance: 100,\n\t\t/** Minimum velocity (px/s) required with minDistance */\n\t\tminVelocity: 800,\n\t\t/** OR swipe this fast (px/s) regardless of distance for quick flicks */\n\t\tvelocityOnlyThreshold: 1200,\n\t},\n} as const\n\n/**\n * Container sizing for different pill modes.\n * Uses CSS clamp() for fluid responsive sizing.\n *\n * Format: { min, preferred (vw), max }\n *\n * WCAG 2.5.8 (Level AA): Touch targets must be at least 24x24 CSS pixels\n * WCAG 2.5.5 (Level AAA): Touch targets should be at least 44x44 CSS pixels\n * We use 24px minimum for collapsed state to meet AA compliance.\n */\nexport const PILL_CONTAINER_SIZES = {\n\tcollapsed: { width: { min: 44, vw: 12, max: 56 }, height: { min: 24, vw: 6, max: 28 } },\n\thovered: { width: { min: 160, vw: 45, max: 180 }, height: { min: 36, vw: 9, max: 40 } },\n\tcomposing: { width: { min: 260, vw: 80, max: 340 } },\n\tactive: { width: { min: 260, vw: 80, max: 340 } },\n\texpanded: { width: { min: 280, vw: 85, max: 400 } },\n} as const\n\n/** Helper to generate CSS clamp() string from sizing config */\nexport function clampSize(config: { min: number; vw: number; max: number }): string {\n\treturn `clamp(${config.min}px, ${config.vw}vw, ${config.max}px)`\n}\n\n/** Auto-collapse timeout in milliseconds (inactivity before pill collapses) */\nexport const AUTO_COLLAPSE_TIMEOUT_MS = 30000\n\n/** Maximum character limit for composer input */\nexport const COMPOSER_MAX_CHARS = 4000\n\n/** Border radius values for pill states */\nexport const PILL_BORDER_RADIUS = {\n\t/** Pill shape (collapsed/hovered) */\n\tpill: '9999px',\n\t/** Rounded rectangle (expanded states) */\n\trounded: '16px',\n\t/** Inner elements (cards, buttons, etc.) */\n\tinner: '10px',\n\t/** Small elements (chips, badges) */\n\tsmall: '6px',\n} as const\n\n/**\n * Spacing scale for consistent padding/margins.\n * Uses a compact scale optimized for mobile information density.\n * Values in pixels - use with template literals: `${PILL_SPACING.sm}px`\n */\nexport const PILL_SPACING = {\n\t/** Extra small: 4px - minimal gaps */\n\txs: 4,\n\t/** Small: 6px - tight spacing */\n\tsm: 6,\n\t/** Medium: 8px - default spacing */\n\tmd: 8,\n\t/** Large: 10px - section spacing */\n\tlg: 10,\n\t/** Extra large: 12px - container padding */\n\txl: 12,\n} as const\n\n/**\n * Max heights for scrollable sections.\n * Mobile-first values (larger on mobile for easier touch scrolling).\n */\nexport const PILL_MAX_HEIGHTS = {\n\t/** Tools section: 160px mobile, 128px desktop */\n\ttools: { mobile: 160, desktop: 128 },\n\t/** Summary block: 128px mobile, 96px desktop */\n\tsummary: { mobile: 128, desktop: 96 },\n\t/** Composer input: 120px mobile, 96px desktop */\n\tcomposer: { mobile: 120, desktop: 96 },\n} as const\n\n/** Maximum number of prompt bubbles to show above collapsed pill */\nexport const MAX_PROMPT_BUBBLES = 3\n\n/** Debounce/delay values in milliseconds */\nexport const UI_TIMING = {\n\t/** Hover debounce before expanding */\n\thoverDebounce: 100,\n\t/** Delay before collapsing after mouse leave */\n\tcollapseDelay: 50,\n\t/** Copy button feedback duration */\n\tcopyFeedback: 2000,\n} as const\n\n/** Minimum height difference (px) to consider keyboard visible (avoids browser chrome false positives) */\nexport const KEYBOARD_VISIBILITY_THRESHOLD_PX = 100\n\n/** Gap (px) between pill and keyboard when keyboard is visible */\nexport const KEYBOARD_GAP_PX = 16\n\n/**\n * Drag interaction opacity configuration.\n * Lower opacity allows seeing content underneath while dragging (useful for mobile).\n */\nexport const DRAG_OPACITY = {\n\t/** Opacity while actively dragging (0.3 = mostly transparent to see underlying content) */\n\tdragging: 0.3,\n\t/** Normal opacity when not dragging */\n\tnormal: 1,\n} as const\n\n// ============================================================================\n// Full-Screen Mode Constants\n// ============================================================================\n\n/**\n * Full-screen mode sizing configuration.\n * Uses viewport units for responsive full-screen layout.\n */\nexport const FULL_SCREEN_CONFIG = {\n\t/** Maximum width of full-screen container */\n\tmaxWidth: '640px',\n\t/** Width as percentage of viewport */\n\twidthPercent: 95,\n\t/** Height as percentage of viewport */\n\theightPercent: 85,\n\t/** Padding inside the container */\n\tpadding: 16,\n} as const\n\n/**\n * Pinch gesture configuration for two-finger expand/collapse.\n */\nexport const PINCH_GESTURE_CONFIG = {\n\t/** Minimum scale change to trigger expand/collapse (30% = 0.3) */\n\tthreshold: 0.3,\n\t/** Minimum distance between fingers to start tracking (px) */\n\tminInitialDistance: 50,\n} as const\n\n// ============================================================================\n// Accessibility Constants\n// ============================================================================\n\n/** ARIA label IDs for accessibility */\nexport const ARIA_IDS = {\n\t/** ID for the pill dialog title (used with aria-labelledby) */\n\tpillTitle: 'agent-pill-title',\n\t/** ID for the pill dialog description (used with aria-describedby) */\n\tpillDescription: 'agent-pill-description',\n\t/** ID for the live region announcements */\n\tliveRegion: 'agent-pill-live-region',\n} as const\n\n/** ARIA labels for various UI elements */\nexport const ARIA_LABELS = {\n\topenAssistant: 'Open assistant',\n\tcloseAssistant: 'Close assistant',\n\tendVoiceSession: 'End voice session',\n\tdragHandle: 'Drag to reposition',\n\tsendMessage: 'Send message',\n\tvoiceInput: 'Start voice input',\n\texpandFullScreen: 'Expand to full screen',\n\tcollapseFullScreen: 'Collapse from full screen',\n} as const\n\n// ============================================================================\n// API Configuration\n// ============================================================================\n\n/** Production API base URL for WebMCP chat and token server */\nexport const WEBMCP_PRODUCTION_API_BASE = 'https://webmcp-agent-playground.alexmnahas.workers.dev'\n\n// ============================================================================\n// MCP Connection Constants\n// ============================================================================\n\n/** Maximum number of reconnection attempts before giving up */\nexport const MCP_MAX_RECONNECT_ATTEMPTS = 5\n\n/** Base delay in milliseconds for exponential backoff reconnection */\nexport const MCP_BASE_RECONNECT_DELAY_MS = 1000\n\n/** Maximum reconnect delay in milliseconds (caps exponential backoff) */\nexport const MCP_MAX_RECONNECT_DELAY_MS = 30000\n\n/** Delay before auto-connecting to tab-based MCP sources (allows server initialization) */\nexport const MCP_TAB_CONNECT_DELAY_MS = 100\n\n// ============================================================================\n// Voice Mode / Realtime API Constants\n// ============================================================================\n\n/** Number of frequency bins for audio visualization */\nexport const AUDIO_FREQUENCY_BINS = 32\n\n/** Default OpenAI Realtime model */\nexport const REALTIME_DEFAULT_MODEL = 'gpt-realtime'\n\n/** Default voice for OpenAI Realtime */\nexport const REALTIME_DEFAULT_VOICE = 'echo'\n\n/** Default OpenAI Realtime API URL */\nexport const REALTIME_DEFAULT_API_URL = 'https://api.openai.com/v1/realtime'\n\n/** Interval in milliseconds for audio visualization updates (~60fps) */\nexport const AUDIO_VISUALIZATION_INTERVAL_MS = 16\n\n/** Delay in milliseconds before requesting response after tool execution */\nexport const RESPONSE_REQUEST_DELAY_MS = 150\n\n/** Duration to show completed tool calls before clearing (success) */\nexport const TOOL_CALL_DISPLAY_DURATION_MS = 1500\n\n/** Duration to show failed tool calls before clearing (error) */\nexport const TOOL_CALL_ERROR_DISPLAY_DURATION_MS = 3000\n\n/** Duration to retain voice actions after session ends (for display) */\nexport const VOICE_ACTIONS_RETENTION_MS = 3000\n\n/** Duration to retain voice summary after session ends */\nexport const VOICE_SUMMARY_RETENTION_MS = 30000\n\n// ============================================================================\n// Voice Tool Approval Constants\n// ============================================================================\n\n/** Timeout before auto-deny when waiting for voice approval (30 seconds) */\nexport const VOICE_APPROVAL_TIMEOUT_MS = 30000\n\n/** Interval for countdown timer updates */\nexport const VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS = 1000\n\n/**\n * Keywords that trigger approval or denial.\n * Uses word boundary matching for safety (prevents \"yesterday\" matching \"yes\").\n */\nexport const VOICE_APPROVAL_KEYWORDS = {\n\tapprove: ['approve', 'yes', 'confirm', 'allow', 'go ahead', 'do it', 'proceed'],\n\tdeny: ['deny', 'no', 'cancel', 'stop', 'reject', \"don't\", 'dont'],\n} as const\n\n/**\n * Tool result messages for voice mode approvals.\n * Used when syncing voice approval results to the thread.\n */\nexport const VOICE_TOOL_RESULT_MESSAGES = {\n\t/** Message when tool was approved and executed in voice mode */\n\thandled: '[Handled in voice mode]',\n\t/** Message when voice session ended with pending approvals */\n\tsessionEnded: '[Voice session ended]',\n} as const\n\n// ============================================================================\n// Waveform Visualization Constants\n// ============================================================================\n\n/** Default history size for scrolling waveform mode */\nexport const WAVEFORM_HISTORY_SIZE = 60\n\n/** Update rate in milliseconds for waveform visualization */\nexport const WAVEFORM_UPDATE_RATE_MS = 30\n\n// ============================================================================\n// WebSocket States (for type-safe comparisons)\n// ============================================================================\n\n/** WebSocket OPEN state value */\nexport const WEBSOCKET_OPEN = 1\n\n// ============================================================================\n// Logging Configuration\n// ============================================================================\n\n/**\n * Enable debug logging for development.\n * Can be enabled by setting window.__WEBMCP_DEBUG__ = true in the browser console.\n * In production builds, this defaults to false.\n */\nexport const DEBUG_LOGGING_ENABLED =\n\ttypeof window !== 'undefined' &&\n\t(window as { __WEBMCP_DEBUG__?: boolean }).__WEBMCP_DEBUG__ === true\n\n/**\n * Conditional debug logger that only logs when DEBUG_LOGGING_ENABLED is true.\n * Can be enabled at runtime by setting window.__WEBMCP_DEBUG__ = true\n *\n * @param component - The component or service name for the log prefix\n * @param message - The log message\n * @param data - Optional data to include in the log\n */\nexport function debugLog(component: string, message: string, data?: unknown): void {\n\t// Check the flag at runtime to allow enabling after page load\n\tconst isDebugEnabled =\n\t\ttypeof window !== 'undefined' &&\n\t\t(window as { __WEBMCP_DEBUG__?: boolean }).__WEBMCP_DEBUG__ === true\n\n\tif (isDebugEnabled) {\n\t\tif (data !== undefined) {\n\t\t\tconsole.log(`[${component}] ${message}`, data)\n\t\t} else {\n\t\t\tconsole.log(`[${component}] ${message}`)\n\t\t}\n\t}\n}\n","import { clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nimport type { ClassValue } from 'clsx'\n\n/**\n * Merges Tailwind CSS classes with proper precedence handling.\n * Combines clsx for conditional classes and tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]): string {\n\treturn twMerge(clsx(inputs))\n}\n","'use client'\n\n/**\n * Markdown renderer for pill components.\n * Uses the same styling as the main MarkdownText but accepts content as a prop.\n */\nimport { memo } from 'react'\nimport ReactMarkdown from 'react-markdown'\nimport remarkGfm from 'remark-gfm'\n\nimport { cn } from '../../lib/utils'\n\nimport type { FC, HTMLAttributes } from 'react'\nimport type { Components } from 'react-markdown'\n\ninterface PillMarkdownProps {\n\tcontent: string\n\tclassName?: string\n\t/** Compact mode uses smaller text and tighter spacing */\n\tcompact?: boolean\n}\n\ntype ElementProps = HTMLAttributes<HTMLElement>\n\n/**\n * Markdown component for rendering content within pill UI.\n * Supports GitHub-flavored markdown with compact styling option.\n */\nexport const PillMarkdown: FC<PillMarkdownProps> = memo(({ content, className, compact }) => {\n\tconst components: Components = {\n\t\th1: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<h1\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-h1 mb-3 scroll-m-20 font-extrabold tracking-tight last:mb-0',\n\t\t\t\t\tcompact ? 'text-base' : 'text-lg',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\th2: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<h2\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-h2 mt-3 mb-2 scroll-m-20 font-semibold tracking-tight first:mt-0 last:mb-0',\n\t\t\t\t\tcompact ? 'text-sm' : 'text-base',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\th3: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<h3\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-h3 mt-2 mb-1 scroll-m-20 font-semibold tracking-tight first:mt-0 last:mb-0',\n\t\t\t\t\tcompact ? 'text-sm' : 'text-[15px]',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tp: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<p\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-p leading-relaxed first:mt-0 last:mb-0',\n\t\t\t\t\tcompact ? 'text-xs my-1' : 'text-sm my-2',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\ta: ({ className: cn_, ...props }: HTMLAttributes<HTMLAnchorElement>) => (\n\t\t\t<a\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-a font-medium text-primary underline underline-offset-4 hover:text-primary/80',\n\t\t\t\t\tcompact ? 'text-xs' : 'text-sm',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tul: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<ul\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-ul ml-4 list-disc [&>li]:mt-0.5',\n\t\t\t\t\tcompact ? 'text-xs my-1' : 'text-sm my-2',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tol: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<ol\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-ol ml-4 list-decimal [&>li]:mt-0.5',\n\t\t\t\t\tcompact ? 'text-xs my-1' : 'text-sm my-2',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tli: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<li className={cn('aui-md-li', cn_)} {...props} />\n\t\t),\n\t\tblockquote: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<blockquote\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-blockquote border-l-2 border-white/20 pl-3 italic text-white/70',\n\t\t\t\t\tcompact ? 'text-xs' : 'text-sm',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\tcode: ({ className: cn_, ...props }: ElementProps) => {\n\t\t\t// Check if this is inline code (no language class)\n\t\t\tconst isInline = !cn_?.includes('language-')\n\t\t\tif (isInline) {\n\t\t\t\treturn (\n\t\t\t\t\t<code\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'aui-md-inline-code rounded bg-white/10 px-1 py-0.5 font-mono',\n\t\t\t\t\t\t\tcompact ? 'text-[10px]' : 'text-xs',\n\t\t\t\t\t\t\tcn_\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t/>\n\t\t\t\t)\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<code\n\t\t\t\t\tclassName={cn('aui-md-code block font-mono', compact ? 'text-[10px]' : 'text-xs', cn_)}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t)\n\t\t},\n\t\tpre: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<pre\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'aui-md-pre overflow-x-auto rounded-lg bg-black/30 p-2 my-2',\n\t\t\t\t\tcompact ? 'text-[10px]' : 'text-xs',\n\t\t\t\t\tcn_\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t),\n\t\thr: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<hr className={cn('aui-md-hr my-2 border-white/10', cn_)} {...props} />\n\t\t),\n\t\tstrong: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<strong className={cn('aui-md-strong font-semibold', cn_)} {...props} />\n\t\t),\n\t\tem: ({ className: cn_, ...props }: ElementProps) => (\n\t\t\t<em className={cn('aui-md-em italic', cn_)} {...props} />\n\t\t),\n\t}\n\n\treturn (\n\t\t<div className={cn('aui-md pill-markdown', compact && 'pill-markdown-compact', className)}>\n\t\t\t<ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>\n\t\t\t\t{content}\n\t\t\t</ReactMarkdown>\n\t\t</div>\n\t)\n})\n\nPillMarkdown.displayName = 'PillMarkdown'\n","'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport { AlertCircle, Check, CheckCircle2, Copy } from 'lucide-react'\nimport { useCallback, useMemo, useState } from 'react'\n\nimport { UI_TIMING } from '../../lib/constants'\nimport { cn } from '../../lib/utils'\nimport { PillMarkdown } from './PillMarkdown'\n\nimport type { FC, ReactNode } from 'react'\n\ninterface SummaryBlockProps {\n\tsummary: string\n\tisSuccess?: boolean\n\tisError?: boolean\n\tactions?: QuickAction[]\n\tclassName?: string\n\t/** Full-screen mode - larger text, no height constraints (parent handles scrolling) */\n\tisFullScreen?: boolean\n}\n\ninterface QuickAction {\n\tlabel: string\n\tonClick: () => void\n\tvariant?: 'primary' | 'secondary'\n}\n\n/**\n * Summary block showing the agent's synthesized output.\n * Displayed after task completion instead of token streaming.\n * Uses compact styling with max-height and scrolling for long responses.\n */\nexport const SummaryBlock: FC<SummaryBlockProps> = ({\n\tsummary,\n\tisSuccess,\n\tisError,\n\tactions,\n\tclassName,\n\tisFullScreen = false,\n}) => {\n\tconst [copied, setCopied] = useState(false)\n\n\tconst handleCopy = useCallback(async () => {\n\t\ttry {\n\t\t\tawait navigator.clipboard.writeText(summary)\n\t\t\tsetCopied(true)\n\t\t\tsetTimeout(() => setCopied(false), UI_TIMING.copyFeedback)\n\t\t} catch {\n\t\t\t// Ignore clipboard errors\n\t\t}\n\t}, [summary])\n\n\treturn (\n\t\t<div className={cn('rounded-lg p-2 relative group', 'bg-white/5', className)}>\n\t\t\t{/* Copy button - visible on touch, appears on hover for desktop */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={(e) => {\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t\tvoid handleCopy()\n\t\t\t\t}}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'absolute top-1.5 right-1.5 z-10',\n\t\t\t\t\t'p-1.5 sm:p-1 rounded',\n\t\t\t\t\t// On touch devices: always slightly visible. On hover devices: hidden until hover\n\t\t\t\t\t'opacity-50 sm:opacity-0 sm:group-hover:opacity-100',\n\t\t\t\t\t'hover:bg-white/10 active:bg-white/15',\n\t\t\t\t\t'text-white/40 hover:text-white/60',\n\t\t\t\t\t'transition-all duration-150'\n\t\t\t\t)}\n\t\t\t\taria-label={copied ? 'Copied!' : 'Copy response'}\n\t\t\t>\n\t\t\t\t{copied ? (\n\t\t\t\t\t<Check className=\"h-3.5 w-3.5 sm:h-3 sm:w-3 text-white/70\" />\n\t\t\t\t) : (\n\t\t\t\t\t<Copy className=\"h-3.5 w-3.5 sm:h-3 sm:w-3\" />\n\t\t\t\t)}\n\t\t\t</button>\n\n\t\t\t{/* Status header - compact */}\n\t\t\t{(isSuccess || isError) && (\n\t\t\t\t<div className=\"flex items-center gap-1.5 mb-1.5\">\n\t\t\t\t\t{isSuccess && <CheckCircle2 className=\"h-3.5 w-3.5 text-white/60\" />}\n\t\t\t\t\t{isError && <AlertCircle className=\"h-3.5 w-3.5 text-white/60\" />}\n\t\t\t\t\t<span className=\"text-[11px] font-medium text-white/70\">\n\t\t\t\t\t\t{isSuccess ? 'Done' : 'Error'}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Summary content - no height limit when full-screen (parent handles scrolling) */}\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'overflow-y-auto scrollbar-thin scroll-touch',\n\t\t\t\t\t!isFullScreen && 'max-h-32 sm:max-h-24'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<PillMarkdown content={summary} className=\"text-white/80\" compact={!isFullScreen} />\n\t\t\t</div>\n\n\t\t\t{/* Quick actions - compact */}\n\t\t\t{actions && actions.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-1.5 mt-2 pt-1.5 border-t border-white/5\">\n\t\t\t\t\t{actions.map((action, i) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\t\te.stopPropagation()\n\t\t\t\t\t\t\t\taction.onClick()\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'px-2 py-1 rounded text-[11px] font-medium',\n\t\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\t\taction.variant === 'primary'\n\t\t\t\t\t\t\t\t\t? 'bg-white/90 text-slate-900 hover:bg-white'\n\t\t\t\t\t\t\t\t\t: 'bg-white/10 text-white/70 hover:bg-white/15'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{action.label}\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\ninterface TextPart {\n\ttype: 'text'\n\ttext: string\n}\n\n/**\n * Hook to get the latest summary from the thread\n * Returns the last text content from the last assistant message\n */\nexport function useLatestSummary(): string | null {\n\t// Use selector pattern to get messages reactively\n\tconst messages = useThread((thread) => thread.messages)\n\n\treturn useMemo(() => {\n\t\tif (!messages || messages.length === 0) return null\n\n\t\tconst lastAssistantMessage = [...messages].reverse().find((m) => m.role === 'assistant')\n\n\t\tif (!lastAssistantMessage) return null\n\n\t\t// Get the last text content\n\t\tconst textParts = lastAssistantMessage.content.filter((c): c is TextPart => c.type === 'text')\n\t\tconst lastText = textParts.at(-1)\n\n\t\tif (!lastText) return null\n\n\t\treturn lastText.text\n\t}, [messages])\n}\n\n/**\n * Welcome message for empty state\n */\nexport const WelcomeMessage: FC<{ className?: string }> = ({ className }) => {\n\treturn (\n\t\t<div className={cn('text-center py-4', className)}>\n\t\t\t<h3 className=\"text-lg font-semibold text-white mb-1\">Hello!</h3>\n\t\t\t<p className=\"text-sm text-white/60\">How can I help you today?</p>\n\t\t</div>\n\t)\n}\n\n/**\n * Wrapper for conditional content based on thread state\n */\nexport const ThreadContent: FC<{\n\tempty: ReactNode\n\trunning: ReactNode\n\tcomplete: ReactNode\n}> = ({ empty, running, complete }) => {\n\t// Use selector pattern to get messages reactively\n\tconst messages = useThread((thread) => thread.messages)\n\n\tif (!messages || messages.length === 0) {\n\t\treturn <>{empty}</>\n\t}\n\n\t// Check if currently running (last message is assistant and incomplete)\n\tconst lastMessage = messages.at(-1)\n\t// Status is an object with a type property, not a string\n\tconst isRunning = lastMessage?.role === 'assistant' && lastMessage.status?.type !== 'complete'\n\n\tif (isRunning) {\n\t\treturn <>{running}</>\n\t}\n\n\treturn <>{complete}</>\n}\n","/**\n * Formatting utilities for tool display\n *\n * Shared helpers for formatting tool names and arguments across components.\n */\n\n/**\n * Humanize tool name for display\n * Converts snake_case and camelCase to readable text.\n *\n * @param name - The tool name to humanize\n * @param progressive - If true, converts verb to progressive tense (e.g., \"searching\")\n *\n * @example\n * humanizeToolName('get_current_time') // 'Get current time'\n * humanizeToolName('deleteNote') // 'Delete note'\n * humanizeToolName('search_files', true) // 'Searching files'\n */\nexport function humanizeToolName(name: string, progressive = false): string {\n\t// Convert camelCase or snake_case to words\n\tconst words = name\n\t\t.replace(/([a-z])([A-Z])/g, '$1 $2')\n\t\t.replace(/_/g, ' ')\n\t\t.toLowerCase()\n\t\t.split(' ')\n\n\tif (words.length === 0) return name\n\n\tif (progressive) {\n\t\t// Make first word progressive (e.g., \"search\" -> \"Searching\")\n\t\tconst verb = words[0]\n\t\tconst progressiveVerb = verb.endsWith('e') ? verb.slice(0, -1) + 'ing' : verb + 'ing'\n\t\twords[0] = progressiveVerb.charAt(0).toUpperCase() + progressiveVerb.slice(1)\n\t} else {\n\t\t// Just capitalize first word\n\t\twords[0] = words[0].charAt(0).toUpperCase() + words[0].slice(1)\n\t}\n\n\treturn words.join(' ')\n}\n\n/**\n * Format tool arguments for display\n * Truncates long strings and formats objects as JSON\n *\n * @example\n * formatArgs({ name: 'test', count: 5 }) // 'name: \"test\"\\ncount: 5'\n */\nexport function formatArgs(args: Record<string, unknown>): string {\n\tconst entries = Object.entries(args)\n\tif (entries.length === 0) return 'No arguments'\n\n\treturn entries\n\t\t.map(([key, value]) => {\n\t\t\tconst displayValue =\n\t\t\t\ttypeof value === 'string'\n\t\t\t\t\t? value.length > 50\n\t\t\t\t\t\t? `\"${value.slice(0, 50)}...\"`\n\t\t\t\t\t\t: `\"${value}\"`\n\t\t\t\t\t: JSON.stringify(value)\n\t\t\treturn `${key}: ${displayValue}`\n\t\t})\n\t\t.join('\\n')\n}\n\n/**\n * Denial message constant\n * Used when user denies a tool execution\n */\nexport const TOOL_DENIED_MESSAGE = 'Tool execution denied by user'\n\n/**\n * Format a denial message with a user-provided reason.\n * Used when user wants to tell the agent what to do differently.\n *\n * @param reason - The user's feedback explaining what to do differently\n * @returns Formatted denial message with reason\n */\nexport function formatToolDenialWithReason(reason: string): string {\n\treturn `Tool denied: ${reason}`\n}\n","import { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { humanizeToolName } from '../lib/format'\n\nimport type { ToolCallMetadata } from '@mcp-b/cloud-mirror-types'\n\n/**\n * Represents a single action derived from a tool call.\n * Metadata (timing, source) is extracted from thread artifacts.\n */\nexport interface Action {\n\tid: string\n\tlabel: string\n\ttoolName: string\n\tstatus: 'running' | 'pending' | 'success' | 'error'\n\targs?: unknown\n\tresult?: unknown\n\terror?: string\n\t/** Timestamp when the tool call started (ms since epoch) */\n\tstartedAt?: number\n\t/** Duration of the tool call in milliseconds */\n\tduration?: number\n\t/** Source ID of the MCP server that handled the call */\n\tsourceId?: string\n\t/** Whether the tool call was aborted (e.g., tool removed during execution) */\n\twasAborted?: boolean\n}\n\ninterface ToolCallPart {\n\ttype: 'tool-call'\n\ttoolCallId: string\n\ttoolName: string\n\targs: unknown\n\tresult?: unknown\n\t// Status from assistant-ui\n\tstatus?: {\n\t\ttype: 'running' | 'complete' | 'incomplete' | 'requires-action'\n\t\terror?: unknown\n\t}\n\t/** Artifact containing ToolCallMetadata (timing, source info) */\n\tartifact?: unknown\n\tisError?: boolean\n}\n\n/**\n * Type guard to check if an artifact is ToolCallMetadata\n */\nfunction isToolCallMetadata(artifact: unknown): artifact is ToolCallMetadata {\n\tif (!artifact || typeof artifact !== 'object') return false\n\tconst a = artifact as Record<string, unknown>\n\treturn (\n\t\ttypeof a.startedAt === 'number' &&\n\t\ttypeof a.duration === 'number' &&\n\t\ttypeof a.sourceId === 'string'\n\t)\n}\n\n/**\n * Hook to derive actions from the current thread's tool calls\n *\n * Actions are a view of tool calls - not separate state.\n * This maintains compatibility with assistant-ui's data model.\n *\n * Metadata (timing, source info) is extracted from the artifact field\n * which is populated by MCPToolRegistry during tool execution.\n */\nexport function useActions(): Action[] {\n\t// Use selector pattern to get messages reactively\n\tconst messages = useThread((thread) => thread.messages)\n\n\treturn useMemo(() => {\n\t\tif (!messages || messages.length === 0) {\n\t\t\treturn []\n\t\t}\n\n\t\tconst actions: Action[] = []\n\n\t\tfor (const message of messages) {\n\t\t\tif (message.role !== 'assistant') continue\n\n\t\t\tfor (const part of message.content) {\n\t\t\t\tif (part.type !== 'tool-call') continue\n\n\t\t\t\tconst toolPart = part as ToolCallPart\n\t\t\t\tconst isComplete = toolPart.result !== undefined\n\t\t\t\tconst hasError =\n\t\t\t\t\ttoolPart.isError === true ||\n\t\t\t\t\t(toolPart.result &&\n\t\t\t\t\t\ttypeof toolPart.result === 'object' &&\n\t\t\t\t\t\t'error' in (toolPart.result as Record<string, unknown>))\n\n\t\t\t\t// Check for requires-action status (HITL pattern)\n\t\t\t\tconst requiresAction = toolPart.status?.type === 'requires-action'\n\n\t\t\t\tlet status: Action['status']\n\t\t\t\tif (hasError) {\n\t\t\t\t\tstatus = 'error'\n\t\t\t\t} else if (isComplete) {\n\t\t\t\t\tstatus = 'success'\n\t\t\t\t} else if (requiresAction) {\n\t\t\t\t\tstatus = 'pending' // Waiting for user approval\n\t\t\t\t} else {\n\t\t\t\t\tstatus = 'running'\n\t\t\t\t}\n\n\t\t\t\t// Extract metadata from artifact if available\n\t\t\t\tconst metadata = isToolCallMetadata(toolPart.artifact) ? toolPart.artifact : undefined\n\n\t\t\t\tactions.push({\n\t\t\t\t\tid: toolPart.toolCallId,\n\t\t\t\t\ttoolName: toolPart.toolName,\n\t\t\t\t\tlabel: humanizeToolName(toolPart.toolName, status === 'running'),\n\t\t\t\t\tstatus,\n\t\t\t\t\targs: toolPart.args,\n\t\t\t\t\tresult: toolPart.result,\n\t\t\t\t\terror: hasError ? String((toolPart.result as Record<string, unknown>).error) : undefined,\n\t\t\t\t\t// Populate from artifact metadata\n\t\t\t\t\tstartedAt: metadata?.startedAt,\n\t\t\t\t\tduration: metadata?.duration,\n\t\t\t\t\tsourceId: metadata?.sourceId,\n\t\t\t\t\twasAborted: metadata?.wasAborted,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\treturn actions\n\t}, [messages])\n}\n\n/**\n * Hook to get the current running action (if any)\n */\nexport function useCurrentAction(): Action | null {\n\tconst actions = useActions()\n\treturn actions.find((a) => a.status === 'running') ?? null\n}\n\n/**\n * Hook to get recently completed actions\n */\nexport function useRecentActions(limit = 3): Action[] {\n\tconst actions = useActions()\n\treturn actions.filter((a) => a.status === 'success' || a.status === 'error').slice(-limit)\n}\n\n/**\n * Hook to get the last completed action (success or error)\n */\nexport function useLastCompletedAction(): Action | null {\n\tconst actions = useActions()\n\tconst completed = actions.filter((a) => a.status === 'success' || a.status === 'error')\n\treturn completed.at(-1) ?? null\n}\n","/**\n * MCP Transport Utilities\n *\n * Shared transport creation logic for MCP sources.\n * This eliminates duplication between MCPToolsProvider and useMCPSource.\n */\nimport { TabClientTransport } from '@mcp-b/transports'\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\n\nimport type { MCPSourceConfig } from '@mcp-b/cloud-mirror-types'\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'\n\n/**\n * Transport type options for HTTP-based connections\n */\nexport type TransportType = 'http' | 'sse'\n\n/**\n * Creates the appropriate MCP transport based on source configuration.\n *\n * @param config - The MCP source configuration\n * @param transportType - For HTTP sources, specifies whether to use HTTP or SSE transport\n * @returns A configured MCP Transport instance\n *\n * @example Tab-based transport (same-tab or iframe)\n * ```ts\n * const transport = createMCPTransport({ type: 'tab' })\n * ```\n *\n * @example HTTP transport with auth\n * ```ts\n * const transport = createMCPTransport({\n * type: 'http',\n * url: 'https://example.com/mcp',\n * authToken: 'secret'\n * }, 'http')\n * ```\n */\nexport function createMCPTransport(\n\tconfig: MCPSourceConfig,\n\ttransportType: TransportType = 'http'\n): Transport {\n\tif (config.type === 'tab') {\n\t\treturn new TabClientTransport({\n\t\t\ttargetOrigin: config.targetOrigin ?? window.location.origin,\n\t\t\tchannelId: config.channelId ?? 'mcp-default',\n\t\t})\n\t}\n\n\t// HTTP/SSE transport configuration\n\tconst serverUrl = new URL(config.url)\n\tconst headers: Record<string, string> = {\n\t\tAccept: 'application/json, text/event-stream',\n\t\t...(config.customHeaders ?? {}),\n\t}\n\n\tif (config.authToken) {\n\t\theaders.Authorization = `Bearer ${config.authToken}`\n\t}\n\n\tconst transportOptions = {\n\t\trequestInit: { headers },\n\t}\n\n\tif (transportType === 'sse') {\n\t\treturn new SSEClientTransport(serverUrl, transportOptions)\n\t}\n\n\treturn new StreamableHTTPClientTransport(serverUrl, transportOptions)\n}\n\n/**\n * Check if an error indicates we should try SSE fallback.\n *\n * This handles cases where HTTP streaming isn't supported (404/405) or\n * when the connection fails due to CORS/network issues.\n *\n * @param error - The error from the failed HTTP connection\n * @returns true if the error suggests trying SSE transport instead\n */\nexport function shouldFallbackToSSE(error: Error): boolean {\n\tconst message = error.message\n\treturn (\n\t\tmessage.includes('404') ||\n\t\tmessage.includes('Not Found') ||\n\t\tmessage.includes('405') ||\n\t\tmessage.includes('Method Not Allowed') ||\n\t\tmessage === 'Failed to fetch' || // Chrome CORS\n\t\tmessage === 'NetworkError when attempting to fetch resource.' || // Firefox\n\t\tmessage === 'Load failed' // Safari\n\t)\n}\n\n/**\n * Calculate exponential backoff delay for reconnection attempts.\n *\n * @param attempt - The current attempt number (0-based)\n * @param baseDelay - Base delay in milliseconds\n * @param maxDelay - Maximum delay cap in milliseconds\n * @returns The calculated delay in milliseconds\n */\nexport function calculateReconnectDelay(\n\tattempt: number,\n\tbaseDelay: number,\n\tmaxDelay: number\n): number {\n\treturn Math.min(baseDelay * Math.pow(2, attempt), maxDelay)\n}\n","/**\n * MCP Tools Provider\n *\n * Simplified provider for managing tools from multiple MCP sources.\n * Sources can be tab-based (same-tab, iframes) or HTTP-based (remote servers).\n *\n * @example Basic usage\n * ```tsx\n * <MCPToolsProvider>\n * <App />\n * </MCPToolsProvider>\n * ```\n *\n * @example Using the hook\n * ```tsx\n * const { tools, addSource, callTool } = useMCPTools()\n * await addSource('remote', { type: 'http', url: 'http://localhost:8888/mcp' })\n * ```\n */\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport {\n\tPromptListChangedNotificationSchema,\n\tToolListChangedNotificationSchema,\n} from '@modelcontextprotocol/sdk/types.js'\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { MCP_TAB_CONNECT_DELAY_MS } from '../lib/constants'\nimport { createMCPTransport } from '../lib/mcp-transport'\n\nimport type {\n\tCallToolResult,\n\tGetPromptResult,\n\tMCPSource,\n\tMCPSourceConfig,\n\tPrompt,\n\tResource,\n\tResourceTemplate,\n\tToolWithSource,\n} from '@mcp-b/cloud-mirror-types'\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'\nimport type { ReactNode } from 'react'\n\n/** Well-known source IDs */\nexport const SOURCE_LOCAL = 'local'\nexport const SOURCE_REMOTE = 'remote'\n\n/** Internal source state with client reference */\ninterface SourceState extends Omit<MCPSource, 'resources' | 'resourceTemplates' | 'prompts'> {\n\tclient: Client | null\n\ttransport: Transport | null\n\tresources: Resource[]\n\tresourceTemplates: ResourceTemplate[]\n\tprompts: Prompt[]\n}\n\n/**\n * Tracks an in-flight tool call with its abort controller.\n *\n * Note: Aborting a call only affects the caller side (the promise race).\n * The underlying tool execution in the MCP server/handler may continue\n * to completion - this is a limitation of the MCP protocol which doesn't\n * support cancellation. The abort ensures the caller gets a timely error\n * response rather than waiting for a tool that's no longer relevant.\n */\ninterface InflightToolCall {\n\t/** The tool name being called */\n\ttoolName: string\n\t/** The source ID the tool belongs to */\n\tsourceId: string\n\t/** Abort controller to cancel the call */\n\tabortController: AbortController\n}\n\n/**\n * MCP Tools Context Value\n */\nexport interface MCPToolsContextValue {\n\t/** All tools from all sources, tagged with _sourceId */\n\ttools: ToolWithSource[]\n\n\t/** All prompts from all sources */\n\tprompts: Prompt[]\n\n\t/** All sources and their states */\n\tsources: Map<string, MCPSource>\n\n\t/** Add a new source */\n\taddSource: (id: string, config: MCPSourceConfig) => Promise<void>\n\n\t/** Remove a source */\n\tremoveSource: (id: string) => Promise<void>\n\n\t/** Get a specific source */\n\tgetSource: (id: string) => MCPSource | undefined\n\n\t/** Check if a source is connected */\n\tisConnected: (id: string) => boolean\n\n\t/** Call a tool (auto-routes based on tool name lookup) */\n\tcallTool: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>\n\n\t/** Call a tool on a specific source */\n\tcallToolOnSource: (\n\t\tsourceId: string,\n\t\tname: string,\n\t\targs: Record<string, unknown>\n\t) => Promise<CallToolResult>\n\n\t/** Get a prompt's expanded content (auto-routes based on prompt name lookup) */\n\tgetPrompt: (name: string, args?: Record<string, string>) => Promise<GetPromptResult>\n}\n\nconst MCPToolsContext = createContext<MCPToolsContextValue | null>(null)\n\nexport interface MCPToolsProviderProps {\n\tchildren: ReactNode\n\t/** Auto-connect to same-tab source on mount (default: true) */\n\tautoConnectLocal?: boolean\n\t/** Callback when tools change */\n\tonToolsChange?: (tools: ToolWithSource[]) => void\n\t/** Callback when prompts change */\n\tonPromptsChange?: (prompts: Prompt[]) => void\n}\n\nexport function MCPToolsProvider({\n\tchildren,\n\tautoConnectLocal = true,\n\tonToolsChange,\n\tonPromptsChange,\n}: MCPToolsProviderProps) {\n\t// Sources map (internal state with client references)\n\tconst sourcesRef = useRef<Map<string, SourceState>>(new Map())\n\n\t// Track in-flight tool calls for abort handling\n\tconst inflightCallsRef = useRef<Map<string, InflightToolCall>>(new Map())\n\n\t// Counter for generating unique call IDs\n\tconst callIdCounterRef = useRef(0)\n\n\t// Trigger re-renders when sources change\n\tconst [, forceUpdate] = useState({})\n\n\t// Derived tools list\n\tconst [toolsList, setToolsList] = useState<ToolWithSource[]>([])\n\n\t// Derived prompts list\n\tconst [promptsList, setPromptsList] = useState<Prompt[]>([])\n\n\t/**\n\t * Abort in-flight tool calls for tools that are no longer available.\n\t * Called after the tool list changes to clean up orphaned calls.\n\t */\n\tconst abortOrphanedCalls = useCallback((currentTools: ToolWithSource[]) => {\n\t\tconst currentToolNames = new Set(currentTools.map((t) => t.name))\n\n\t\tinflightCallsRef.current.forEach((call, callId) => {\n\t\t\tif (!currentToolNames.has(call.toolName)) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[MCPToolsProvider] Aborting orphaned tool call: ${call.toolName} (call ID: ${callId})`\n\t\t\t\t)\n\t\t\t\tcall.abortController.abort(new Error(`Tool '${call.toolName}' is no longer available`))\n\t\t\t\tinflightCallsRef.current.delete(callId)\n\t\t\t}\n\t\t})\n\t}, [])\n\n\t/**\n\t * Rebuild tools list from all sources\n\t */\n\tconst rebuildTools = useCallback(() => {\n\t\tconst allTools: ToolWithSource[] = []\n\n\t\tsourcesRef.current.forEach((source) => {\n\t\t\tsource.tools.forEach((tool) => {\n\t\t\t\tallTools.push({\n\t\t\t\t\t...tool,\n\t\t\t\t\t_sourceId: source.id,\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\n\t\t// Abort any in-flight calls for tools that are no longer in the list\n\t\tabortOrphanedCalls(allTools)\n\n\t\tsetToolsList(allTools)\n\t}, [abortOrphanedCalls])\n\n\t/**\n\t * Rebuild prompts list from all sources\n\t */\n\tconst rebuildPrompts = useCallback(() => {\n\t\tconst allPrompts: Prompt[] = []\n\n\t\tsourcesRef.current.forEach((source) => {\n\t\t\tsource.prompts.forEach((prompt) => {\n\t\t\t\tallPrompts.push(prompt)\n\t\t\t})\n\t\t})\n\n\t\tsetPromptsList(allPrompts)\n\t}, [])\n\n\t/**\n\t * Get public source state (without client reference)\n\t */\n\tconst getPublicSource = useCallback((source: SourceState): MCPSource => {\n\t\treturn {\n\t\t\tid: source.id,\n\t\t\tconfig: source.config,\n\t\t\tstate: source.state,\n\t\t\terror: source.error,\n\t\t\ttools: source.tools,\n\t\t\tresources: source.resources,\n\t\t\tresourceTemplates: source.resourceTemplates,\n\t\t\tprompts: source.prompts,\n\t\t}\n\t}, [])\n\n\t/**\n\t * Add a new source\n\t */\n\tconst addSource = useCallback(\n\t\tasync (id: string, config: MCPSourceConfig): Promise<void> => {\n\t\t\t// Remove existing source if any\n\t\t\tif (sourcesRef.current.has(id)) {\n\t\t\t\tawait removeSource(id)\n\t\t\t}\n\n\t\t\t// Create initial state\n\t\t\tconst sourceState: SourceState = {\n\t\t\t\tid,\n\t\t\t\tconfig,\n\t\t\t\tstate: 'connecting',\n\t\t\t\terror: null,\n\t\t\t\ttools: [],\n\t\t\t\tresources: [],\n\t\t\t\tresourceTemplates: [],\n\t\t\t\tprompts: [],\n\t\t\t\tclient: null,\n\t\t\t\ttransport: null,\n\t\t\t}\n\n\t\t\tsourcesRef.current.set(id, sourceState)\n\t\t\tforceUpdate({})\n\n\t\t\ttry {\n\t\t\t\t// Create client and transport\n\t\t\t\tconst client = new Client({\n\t\t\t\t\tname: `MCP-Source-${id}`,\n\t\t\t\t\tversion: '1.0.0',\n\t\t\t\t})\n\n\t\t\t\tconst transport = createMCPTransport(config)\n\n\t\t\t\t// Connect\n\t\t\t\tawait client.connect(transport)\n\n\t\t\t\t// Update state with client\n\t\t\t\tsourceState.client = client\n\t\t\t\tsourceState.transport = transport\n\n\t\t\t\t// Get initial tools and prompts\n\t\t\t\tconst { tools } = await client.listTools()\n\t\t\t\tsourceState.tools = tools\n\n\t\t\t\t// Get initial prompts (wrapped in try-catch as some servers may not support prompts)\n\t\t\t\ttry {\n\t\t\t\t\tconst { prompts } = await client.listPrompts()\n\t\t\t\t\tsourceState.prompts = prompts\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.warn(`[MCPToolsProvider:${id}] Server does not support prompts:`, err)\n\t\t\t\t\tsourceState.prompts = []\n\t\t\t\t}\n\n\t\t\t\tsourceState.state = 'connected'\n\n\t\t\t\t// Listen for tool updates\n\t\t\t\tclient.setNotificationHandler(ToolListChangedNotificationSchema, async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst updated = await client.listTools()\n\t\t\t\t\t\tsourceState.tools = updated.tools\n\t\t\t\t\t\trebuildTools()\n\t\t\t\t\t\tforceUpdate({})\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Failed to update tools:`, err)\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\t// Listen for prompt updates\n\t\t\t\tclient.setNotificationHandler(PromptListChangedNotificationSchema, async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst updated = await client.listPrompts()\n\t\t\t\t\t\tsourceState.prompts = updated.prompts\n\t\t\t\t\t\trebuildPrompts()\n\t\t\t\t\t\tforceUpdate({})\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Failed to update prompts:`, err)\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\trebuildTools()\n\t\t\t\trebuildPrompts()\n\t\t\t\tforceUpdate({})\n\t\t\t} catch (err) {\n\t\t\t\tconst error = err instanceof Error ? err : new Error(String(err))\n\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Connection failed:`, error)\n\n\t\t\t\tsourceState.state = 'error'\n\t\t\t\tsourceState.error = error\n\t\t\t\tforceUpdate({})\n\t\t\t}\n\t\t},\n\t\t[rebuildTools, rebuildPrompts]\n\t)\n\n\t/**\n\t * Remove a source\n\t */\n\tconst removeSource = useCallback(\n\t\tasync (id: string): Promise<void> => {\n\t\t\tconst source = sourcesRef.current.get(id)\n\t\t\tif (!source) return\n\n\t\t\t// Close client and transport\n\t\t\tif (source.client) {\n\t\t\t\ttry {\n\t\t\t\t\tawait source.client.close()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Error closing client:`, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (source.transport) {\n\t\t\t\ttry {\n\t\t\t\t\tawait source.transport.close()\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[MCPToolsProvider:${id}] Error closing transport:`, err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsourcesRef.current.delete(id)\n\t\t\trebuildTools()\n\t\t\trebuildPrompts()\n\t\t\tforceUpdate({})\n\t\t},\n\t\t[rebuildTools, rebuildPrompts]\n\t)\n\n\t/**\n\t * Get a source by ID\n\t */\n\tconst getSource = useCallback(\n\t\t(id: string): MCPSource | undefined => {\n\t\t\tconst source = sourcesRef.current.get(id)\n\t\t\treturn source ? getPublicSource(source) : undefined\n\t\t},\n\t\t[getPublicSource]\n\t)\n\n\t/**\n\t * Check if a source is connected\n\t */\n\tconst isConnected = useCallback((id: string): boolean => {\n\t\tconst source = sourcesRef.current.get(id)\n\t\treturn source?.state === 'connected'\n\t}, [])\n\n\t/**\n\t * Call a tool on a specific source with in-flight tracking and abort support.\n\t * If the tool is removed while the call is in progress, the call will be aborted.\n\t */\n\tconst callToolOnSource = useCallback(\n\t\tasync (\n\t\t\tsourceId: string,\n\t\t\tname: string,\n\t\t\targs: Record<string, unknown>\n\t\t): Promise<CallToolResult> => {\n\t\t\tconst source = sourcesRef.current.get(sourceId)\n\t\t\tif (!source?.client) {\n\t\t\t\tthrow new Error(`Source '${sourceId}' not connected`)\n\t\t\t}\n\n\t\t\t// Generate unique call ID and create abort controller\n\t\t\tconst callId = `${sourceId}-${name}-${++callIdCounterRef.current}`\n\t\t\tconst abortController = new AbortController()\n\n\t\t\t// Register in-flight call\n\t\t\tinflightCallsRef.current.set(callId, {\n\t\t\t\ttoolName: name,\n\t\t\t\tsourceId,\n\t\t\t\tabortController,\n\t\t\t})\n\n\t\t\ttry {\n\t\t\t\t// Create a promise that rejects when aborted\n\t\t\t\tconst abortPromise = new Promise<never>((_, reject) => {\n\t\t\t\t\tconst signal = abortController.signal\n\n\t\t\t\t\t// Handle already-aborted signal (race condition prevention)\n\t\t\t\t\tif (signal.aborted) {\n\t\t\t\t\t\treject(signal.reason || new Error(`Tool '${name}' call was aborted`))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Use { once: true } to auto-cleanup the listener\n\t\t\t\t\tsignal.addEventListener(\n\t\t\t\t\t\t'abort',\n\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\treject(signal.reason || new Error(`Tool '${name}' call was aborted`))\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ once: true }\n\t\t\t\t\t)\n\t\t\t\t})\n\n\t\t\t\t// Race between the actual tool call and the abort signal\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tsource.client.callTool({ name, arguments: args }),\n\t\t\t\t\tabortPromise,\n\t\t\t\t])\n\n\t\t\t\treturn result as CallToolResult\n\t\t\t} catch (error) {\n\t\t\t\t// Check if this was an abort\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\t// Return an error result for aborted calls\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text' as const,\n\t\t\t\t\t\t\t\ttext: `Tool call aborted: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\t// Clean up the in-flight tracking\n\t\t\t\tinflightCallsRef.current.delete(callId)\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\t/**\n\t * Call a tool (auto-routes based on tool name)\n\t */\n\tconst callTool = useCallback(\n\t\tasync (name: string, args: Record<string, unknown>): Promise<CallToolResult> => {\n\t\t\t// Find which source has this tool\n\t\t\tconst tool = toolsList.find((t) => t.name === name)\n\t\t\tif (!tool) {\n\t\t\t\tthrow new Error(`Tool '${name}' not found`)\n\t\t\t}\n\n\t\t\treturn callToolOnSource(tool._sourceId, name, args)\n\t\t},\n\t\t[toolsList, callToolOnSource]\n\t)\n\n\t/**\n\t * Get a prompt's expanded content (auto-routes based on prompt name)\n\t */\n\tconst getPrompt = useCallback(\n\t\tasync (name: string, args?: Record<string, string>): Promise<GetPromptResult> => {\n\t\t\t// Find which source has this prompt\n\t\t\tfor (const source of sourcesRef.current.values()) {\n\t\t\t\tconst hasPrompt = source.prompts.some((p) => p.name === name)\n\t\t\t\tif (hasPrompt && source.client) {\n\t\t\t\t\treturn (await source.client.getPrompt({ name, arguments: args })) as GetPromptResult\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(`Prompt '${name}' not found`)\n\t\t},\n\t\t[]\n\t)\n\n\t/**\n\t * Get sources map for context (public view).\n\t *\n\t * Note: This useMemo reads from sourcesRef but depends on toolsList/promptsList.\n\t * This is intentional - toolsList and promptsList are derived from sourcesRef,\n\t * so when they change, it means sourcesRef has changed and we need to rebuild\n\t * the public view. This avoids exposing sourcesRef as a dependency while still\n\t * triggering recomputation when source data changes.\n\t */\n\tconst sources = useMemo(() => {\n\t\tconst publicSources = new Map<string, MCPSource>()\n\t\tsourcesRef.current.forEach((source) => {\n\t\t\tpublicSources.set(source.id, getPublicSource(source))\n\t\t})\n\t\treturn publicSources\n\t}, [toolsList, promptsList, getPublicSource])\n\n\t// Auto-connect to local source on mount\n\tuseEffect(() => {\n\t\tif (autoConnectLocal) {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tvoid addSource(SOURCE_LOCAL, { type: 'tab' })\n\t\t\t}, MCP_TAB_CONNECT_DELAY_MS)\n\t\t\treturn () => clearTimeout(timer)\n\t\t}\n\t}, [autoConnectLocal, addSource])\n\n\t// Notify on tools change\n\tuseEffect(() => {\n\t\tonToolsChange?.(toolsList)\n\t}, [toolsList, onToolsChange])\n\n\t// Notify on prompts change\n\tuseEffect(() => {\n\t\tonPromptsChange?.(promptsList)\n\t}, [promptsList, onPromptsChange])\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\tconst sources = sourcesRef\n\t\tconst inflightCalls = inflightCallsRef\n\t\treturn () => {\n\t\t\t// Abort all in-flight tool calls\n\t\t\t// Note: We iterate first, then clear - don't mutate during iteration\n\t\t\tinflightCalls.current.forEach((call) => {\n\t\t\t\tcall.abortController.abort(new Error('Provider unmounted'))\n\t\t\t})\n\t\t\tinflightCalls.current.clear()\n\n\t\t\t// Close all source connections\n\t\t\tsources.current.forEach((source) => {\n\t\t\t\tif (source.client) {\n\t\t\t\t\tvoid source.client.close().catch(console.error)\n\t\t\t\t}\n\t\t\t\tif (source.transport) {\n\t\t\t\t\tvoid source.transport.close().catch(console.error)\n\t\t\t\t}\n\t\t\t})\n\t\t\tsources.current.clear()\n\t\t}\n\t}, [])\n\n\tconst value = useMemo<MCPToolsContextValue>(\n\t\t() => ({\n\t\t\ttools: toolsList,\n\t\t\tprompts: promptsList,\n\t\t\tsources,\n\t\t\taddSource,\n\t\t\tremoveSource,\n\t\t\tgetSource,\n\t\t\tisConnected,\n\t\t\tcallTool,\n\t\t\tcallToolOnSource,\n\t\t\tgetPrompt,\n\t\t}),\n\t\t[\n\t\t\ttoolsList,\n\t\t\tpromptsList,\n\t\t\tsources,\n\t\t\taddSource,\n\t\t\tremoveSource,\n\t\t\tgetSource,\n\t\t\tisConnected,\n\t\t\tcallTool,\n\t\t\tcallToolOnSource,\n\t\t\tgetPrompt,\n\t\t]\n\t)\n\n\treturn <MCPToolsContext.Provider value={value}>{children}</MCPToolsContext.Provider>\n}\n\n/**\n * Hook to access MCP Tools context\n */\nexport function useMCPTools(): MCPToolsContextValue {\n\tconst context = useContext(MCPToolsContext)\n\tif (!context) {\n\t\tthrow new Error('useMCPTools must be used within an MCPToolsProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access MCP Tools context\n */\nexport function useOptionalMCPTools(): MCPToolsContextValue | null {\n\treturn useContext(MCPToolsContext)\n}\n","/**\n * Thread Utilities\n *\n * Shared utilities for working with assistant-ui thread state.\n * These functions provide a non-reactive way to query and modify thread state,\n * suitable for use in callbacks and effects.\n *\n * For reactive hooks, see usePendingToolCalls.ts which wraps these utilities.\n */\n\nimport type { ThreadAssistantMessage, ThreadRuntime } from '@assistant-ui/react'\n\n/**\n * Information about a pending tool call that requires user approval\n */\nexport interface PendingToolCallInfo {\n\tmessageId: string\n\ttoolCallId: string\n\ttoolName: string\n\targs: Record<string, unknown>\n}\n\n/**\n * Find all pending tool calls in a thread.\n *\n * This is a non-reactive utility for use in callbacks.\n * For reactive state, use usePendingToolCalls() hook instead.\n *\n * @param threadRuntime - The thread runtime to query\n * @returns Array of pending tool calls with their metadata\n */\nexport function getPendingToolCalls(threadRuntime: ThreadRuntime): PendingToolCallInfo[] {\n\tconst messages = threadRuntime.getState().messages\n\tconst result: PendingToolCallInfo[] = []\n\n\tfor (const msg of messages) {\n\t\t// Only assistant messages can have tool calls\n\t\tif (msg.role !== 'assistant') continue\n\n\t\t// Cast to assistant message to access status\n\t\tconst assistantMsg = msg as ThreadAssistantMessage\n\n\t\t// Only process messages waiting for tool results\n\t\tif (assistantMsg.status?.type !== 'requires-action') continue\n\n\t\t// Find tool-call parts without results\n\t\tfor (const part of assistantMsg.content) {\n\t\t\tif (part.type !== 'tool-call') continue\n\t\t\tif (part.result !== undefined) continue\n\n\t\t\tresult.push({\n\t\t\t\tmessageId: msg.id,\n\t\t\t\ttoolCallId: part.toolCallId,\n\t\t\t\ttoolName: part.toolName,\n\t\t\t\targs: (part.args as Record<string, unknown>) ?? {},\n\t\t\t})\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Find pending tool calls matching a specific tool name.\n *\n * @param threadRuntime - The thread runtime to query\n * @param toolName - The tool name to filter by\n * @returns Array of matching pending tool calls\n */\nexport function getPendingToolCallsByName(\n\tthreadRuntime: ThreadRuntime,\n\ttoolName: string\n): PendingToolCallInfo[] {\n\treturn getPendingToolCalls(threadRuntime).filter((tc) => tc.toolName === toolName)\n}\n\n/**\n * Resolve a pending tool call by adding a result.\n *\n * @param threadRuntime - The thread runtime\n * @param messageId - The message ID containing the tool call\n * @param toolCallId - The specific tool call ID to resolve\n * @param result - The result string to add\n * @returns true if resolved successfully, false if tool call not found\n */\nexport function resolvePendingToolCall(\n\tthreadRuntime: ThreadRuntime,\n\tmessageId: string,\n\ttoolCallId: string,\n\tresult: string\n): boolean {\n\tconst messageRuntime = threadRuntime.getMessageById(messageId)\n\tconst partRuntime = messageRuntime?.getMessagePartByToolCallId(toolCallId)\n\n\tif (partRuntime) {\n\t\tpartRuntime.addToolResult(result)\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * Resolve all pending tool calls matching a tool name.\n *\n * @param threadRuntime - The thread runtime\n * @param toolName - The tool name to match\n * @param result - The result string to add to all matches\n * @returns Number of tool calls resolved\n */\nexport function resolveAllPendingToolCallsByName(\n\tthreadRuntime: ThreadRuntime,\n\ttoolName: string,\n\tresult: string\n): number {\n\tconst pendingCalls = getPendingToolCallsByName(threadRuntime, toolName)\n\tlet resolved = 0\n\n\tfor (const call of pendingCalls) {\n\t\tif (resolvePendingToolCall(threadRuntime, call.messageId, call.toolCallId, result)) {\n\t\t\tresolved++\n\t\t}\n\t}\n\n\treturn resolved\n}\n\n/**\n * Resolve all pending tool calls in the thread.\n *\n * @param threadRuntime - The thread runtime\n * @param result - The result string to add to all pending calls\n * @returns Number of tool calls resolved\n */\nexport function resolveAllPendingToolCalls(threadRuntime: ThreadRuntime, result: string): number {\n\tconst pendingCalls = getPendingToolCalls(threadRuntime)\n\tlet resolved = 0\n\n\tfor (const call of pendingCalls) {\n\t\tif (resolvePendingToolCall(threadRuntime, call.messageId, call.toolCallId, result)) {\n\t\t\tresolved++\n\t\t}\n\t}\n\n\treturn resolved\n}\n","/**\n * Tool Approval Provider\n *\n * Manages user preferences for destructive tool approval.\n * When mode is 'ask', tools with destructiveHint: true require user confirmation.\n * When mode is 'auto', all tools execute immediately.\n *\n * @example\n * ```tsx\n * <ToolApprovalProvider>\n * <App />\n * </ToolApprovalProvider>\n *\n * // In a component:\n * const { mode, setMode, requiresApproval } = useToolApproval()\n * ```\n */\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'\n\nimport type { Tool, ToolApprovalMode, ToolApprovalSettings } from '@mcp-b/cloud-mirror-types'\nimport type { ReactNode } from 'react'\n\nconst STORAGE_KEY = 'webmcp-tool-approval-mode'\nconst DEFAULT_MODE: ToolApprovalMode = 'ask'\n\n/**\n * Tool Approval Context Value\n */\nexport interface ToolApprovalContextValue extends ToolApprovalSettings {\n\t/** Set the approval mode */\n\tsetMode: (mode: ToolApprovalMode) => void\n\t/** Toggle between 'auto' and 'ask' modes */\n\ttoggleMode: () => void\n\t/** Check if a specific tool requires approval based on its annotations */\n\trequiresApproval: (tool: Tool) => boolean\n\t/** Check if a tool is considered destructive based on its annotations */\n\tisDestructive: (tool: Tool) => boolean\n}\n\nconst ToolApprovalContext = createContext<ToolApprovalContextValue | null>(null)\n\nexport interface ToolApprovalProviderProps {\n\tchildren: ReactNode\n\t/** Initial mode (overrides stored preference) */\n\tdefaultMode?: ToolApprovalMode\n\t/** Disable localStorage persistence */\n\tdisablePersistence?: boolean\n\t/** Callback when mode changes */\n\tonModeChange?: (mode: ToolApprovalMode) => void\n}\n\n/**\n * Check if a tool is destructive based on MCP annotations.\n *\n * A tool is considered destructive if:\n * - It has destructiveHint: true explicitly set, OR\n * - It is NOT read-only (readOnlyHint is false or undefined) AND destructiveHint is not false\n *\n * This follows the MCP spec where destructiveHint defaults to true for non-read-only tools.\n */\nfunction checkIsDestructive(tool: Tool): boolean {\n\tconst annotations = tool.annotations\n\n\t// If no annotations, default to destructive (MCP spec default)\n\tif (!annotations) {\n\t\treturn true\n\t}\n\n\t// If explicitly marked as read-only, it's not destructive\n\tif (annotations.readOnlyHint === true) {\n\t\treturn false\n\t}\n\n\t// If destructiveHint is explicitly set, use that value\n\tif (typeof annotations.destructiveHint === 'boolean') {\n\t\treturn annotations.destructiveHint\n\t}\n\n\t// Default: non-read-only tools are considered potentially destructive\n\treturn true\n}\n\nexport function ToolApprovalProvider({\n\tchildren,\n\tdefaultMode,\n\tdisablePersistence = false,\n\tonModeChange,\n}: ToolApprovalProviderProps) {\n\t// Initialize mode from storage or default\n\tconst [mode, setModeState] = useState<ToolApprovalMode>(() => {\n\t\tif (defaultMode) return defaultMode\n\t\tif (disablePersistence) return DEFAULT_MODE\n\n\t\ttry {\n\t\t\tconst stored = localStorage.getItem(STORAGE_KEY)\n\t\t\tif (stored === 'auto' || stored === 'ask') {\n\t\t\t\treturn stored\n\t\t\t}\n\t\t} catch {\n\t\t\t// localStorage not available\n\t\t}\n\t\treturn DEFAULT_MODE\n\t})\n\n\t// Persist mode changes\n\tuseEffect(() => {\n\t\tif (disablePersistence) return\n\n\t\ttry {\n\t\t\tlocalStorage.setItem(STORAGE_KEY, mode)\n\t\t} catch {\n\t\t\t// localStorage not available\n\t\t}\n\t}, [mode, disablePersistence])\n\n\t// Set mode with callback\n\tconst setMode = useCallback(\n\t\t(newMode: ToolApprovalMode) => {\n\t\t\tsetModeState(newMode)\n\t\t\tonModeChange?.(newMode)\n\t\t},\n\t\t[onModeChange]\n\t)\n\n\t// Toggle between modes\n\tconst toggleMode = useCallback(() => {\n\t\tsetMode(mode === 'auto' ? 'ask' : 'auto')\n\t}, [mode, setMode])\n\n\t// Check if a tool is destructive\n\tconst isDestructive = useCallback((tool: Tool): boolean => {\n\t\treturn checkIsDestructive(tool)\n\t}, [])\n\n\t// Check if a tool requires approval (destructive + ask mode)\n\tconst requiresApproval = useCallback(\n\t\t(tool: Tool): boolean => {\n\t\t\tif (mode === 'auto') return false\n\t\t\treturn isDestructive(tool)\n\t\t},\n\t\t[mode, isDestructive]\n\t)\n\n\tconst value = useMemo<ToolApprovalContextValue>(\n\t\t() => ({\n\t\t\tmode,\n\t\t\tsetMode,\n\t\t\ttoggleMode,\n\t\t\trequiresApproval,\n\t\t\tisDestructive,\n\t\t}),\n\t\t[mode, setMode, toggleMode, requiresApproval, isDestructive]\n\t)\n\n\treturn <ToolApprovalContext.Provider value={value}>{children}</ToolApprovalContext.Provider>\n}\n\n/**\n * Hook to access tool approval settings\n */\nexport function useToolApproval(): ToolApprovalContextValue {\n\tconst context = useContext(ToolApprovalContext)\n\tif (!context) {\n\t\tthrow new Error('useToolApproval must be used within a ToolApprovalProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access tool approval settings\n */\nexport function useOptionalToolApproval(): ToolApprovalContextValue | null {\n\treturn useContext(ToolApprovalContext)\n}\n","import { debugLog } from '../../lib/constants'\n\n/**\n * Audio analyzer for processing microphone and speaker audio streams.\n * Uses Web Audio API to analyze audio levels and frequency data.\n */\nexport class AudioAnalyzer {\n\tprivate audioContext: AudioContext | null = null\n\tprivate analyser: AnalyserNode | null = null\n\tprivate source: MediaStreamAudioSourceNode | null = null\n\tprivate dataArray: Uint8Array<ArrayBuffer> | null = null\n\tprivate animationId: number | null = null\n\n\t/**\n\t * Initialize the audio analyzer with a media stream\n\t * @param stream - MediaStream to analyze (typically from microphone or speaker)\n\t */\n\tasync initialize(stream: MediaStream): Promise<void> {\n\t\t// Log stream info for debugging\n\t\tconst audioTracks = stream.getAudioTracks()\n\t\tdebugLog('AudioAnalyzer', 'Initializing with stream', {\n\t\t\tstreamId: stream.id,\n\t\t\taudioTracks: audioTracks.length,\n\t\t\ttrackInfo: audioTracks.map((t) => ({\n\t\t\t\tid: t.id,\n\t\t\t\tlabel: t.label,\n\t\t\t\tenabled: t.enabled,\n\t\t\t\tmuted: t.muted,\n\t\t\t\treadyState: t.readyState,\n\t\t\t})),\n\t\t})\n\n\t\tthis.audioContext = new AudioContext()\n\t\tdebugLog('AudioAnalyzer', `AudioContext created, initial state: ${this.audioContext.state}`)\n\n\t\t// Always try to resume - some browsers need this regardless of reported state\n\t\ttry {\n\t\t\tawait this.audioContext.resume()\n\t\t\tdebugLog('AudioAnalyzer', `AudioContext after resume: ${this.audioContext.state}`)\n\t\t} catch (err) {\n\t\t\tconsole.warn('[AudioAnalyzer] Failed to resume AudioContext:', err)\n\t\t}\n\n\t\tthis.analyser = this.audioContext.createAnalyser()\n\t\tthis.analyser.fftSize = 256\n\t\tthis.analyser.smoothingTimeConstant = 0.8\n\n\t\tthis.source = this.audioContext.createMediaStreamSource(stream)\n\t\tthis.source.connect(this.analyser)\n\n\t\tconst bufferLength = this.analyser.frequencyBinCount\n\t\tthis.dataArray = new Uint8Array(new ArrayBuffer(bufferLength))\n\n\t\tdebugLog('AudioAnalyzer', 'Setup complete', {\n\t\t\tsampleRate: this.audioContext.sampleRate,\n\t\t\tfrequencyBinCount: bufferLength,\n\t\t\tcontextState: this.audioContext.state,\n\t\t})\n\t}\n\n\tgetAudioLevel(): number {\n\t\tif (!this.analyser || !this.dataArray) return 0\n\n\t\tthis.analyser.getByteFrequencyData(this.dataArray)\n\n\t\t// Calculate average volume\n\t\tlet sum = 0\n\t\tfor (let i = 0; i < this.dataArray.length; i++) {\n\t\t\tsum += this.dataArray[i]\n\t\t}\n\t\tconst average = sum / this.dataArray.length\n\n\t\t// Normalize to 0-1 range\n\t\treturn Math.min(1, average / 128)\n\t}\n\n\tgetFrequencyData(bins = 16): number[] {\n\t\tif (!this.analyser || !this.dataArray) return new Array(bins).fill(0)\n\n\t\tthis.analyser.getByteFrequencyData(this.dataArray)\n\n\t\tconst result: number[] = []\n\t\tconst samplesPerBin = Math.floor(this.dataArray.length / bins)\n\n\t\tfor (let i = 0; i < bins; i++) {\n\t\t\tlet sum = 0\n\t\t\tfor (let j = 0; j < samplesPerBin; j++) {\n\t\t\t\tsum += this.dataArray[i * samplesPerBin + j]\n\t\t\t}\n\t\t\t// Normalize to 0-1 range\n\t\t\tresult.push(Math.min(1, sum / samplesPerBin / 255))\n\t\t}\n\n\t\treturn result\n\t}\n\n\tstartAnalysis(callback: (level: number, frequencies: number[]) => void): void {\n\t\tconst analyze = () => {\n\t\t\tconst level = this.getAudioLevel()\n\t\t\tconst frequencies = this.getFrequencyData()\n\t\t\tcallback(level, frequencies)\n\t\t\tthis.animationId = requestAnimationFrame(analyze)\n\t\t}\n\t\tanalyze()\n\t}\n\n\tstopAnalysis(): void {\n\t\tif (this.animationId !== null) {\n\t\t\tcancelAnimationFrame(this.animationId)\n\t\t\tthis.animationId = null\n\t\t}\n\t}\n\n\tdestroy(): void {\n\t\tthis.stopAnalysis()\n\n\t\tif (this.source) {\n\t\t\tthis.source.disconnect()\n\t\t\tthis.source = null\n\t\t}\n\n\t\tif (this.analyser) {\n\t\t\tthis.analyser.disconnect()\n\t\t\tthis.analyser = null\n\t\t}\n\n\t\tif (this.audioContext) {\n\t\t\tvoid this.audioContext.close()\n\t\t\tthis.audioContext = null\n\t\t}\n\n\t\tthis.dataArray = null\n\t}\n}\n","import type { EventCallback, IEventEmitter } from './types'\n\nexport class EventEmitter implements IEventEmitter {\n\tprivate listeners = new Map<string, Set<EventCallback>>()\n\n\ton(event: string, callback: EventCallback): void {\n\t\tif (!this.listeners.has(event)) {\n\t\t\tthis.listeners.set(event, new Set())\n\t\t}\n\t\tconst listeners = this.listeners.get(event)\n\t\tif (listeners) {\n\t\t\tlisteners.add(callback)\n\t\t}\n\t}\n\n\toff(event: string, callback: EventCallback): void {\n\t\tthis.listeners.get(event)?.delete(callback)\n\t}\n\n\temit(event: string, data: unknown): void {\n\t\tthis.listeners.get(event)?.forEach((callback) => {\n\t\t\ttry {\n\t\t\t\tcallback(data)\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`Error in event listener for ${event}:`, error)\n\t\t\t}\n\t\t})\n\t}\n\n\tremoveAllListeners(event?: string): void {\n\t\tif (event) {\n\t\t\tthis.listeners.delete(event)\n\t\t} else {\n\t\t\tthis.listeners.clear()\n\t\t}\n\t}\n\n\tlistenerCount(event: string): number {\n\t\treturn this.listeners.get(event)?.size || 0\n\t}\n}\n","import { RESPONSE_REQUEST_DELAY_MS } from '../../lib/constants'\n\nimport type { EventEmitter } from './event-emitter'\nimport type { ToolManager } from './tool-manager'\nimport type { FunctionCall, RealtimeMessage } from './types'\n\n/**\n * Type for response output items from OpenAI Realtime API\n */\ninterface ResponseOutputItem {\n\ttype: string\n\tstatus?: string\n\tname?: string\n\tcall_id?: string\n\targuments?: string\n}\n\n/**\n * Type guard to check if an output item is a completed function call\n */\nfunction isCompletedFunctionCall(item: ResponseOutputItem): item is ResponseOutputItem & {\n\tname: string\n\tcall_id: string\n\targuments: string\n} {\n\treturn (\n\t\titem.type === 'function_call' &&\n\t\titem.status === 'completed' &&\n\t\ttypeof item.name === 'string' &&\n\t\ttypeof item.call_id === 'string'\n\t)\n}\n\nexport class MessageHandler {\n\tprivate isProcessingResponse = false\n\tprivate pendingFunctionCalls = new Set<string>()\n\tprivate responseRequestTimer: ReturnType<typeof setTimeout> | null = null\n\tprivate hasRequestedResponse = false\n\n\tconstructor(\n\t\tprivate toolManager: ToolManager,\n\t\tprivate eventEmitter: EventEmitter\n\t) {}\n\n\tasync handleMessage(data: string, dataChannel: RTCDataChannel): Promise<void> {\n\t\tlet msg: RealtimeMessage\n\n\t\ttry {\n\t\t\tmsg = JSON.parse(data) as RealtimeMessage\n\t\t} catch (error) {\n\t\t\tconsole.error('Failed to parse realtime message:', error)\n\t\t\treturn\n\t\t}\n\n\t\t// Log all incoming events for debugging\n\t\t// Route message to appropriate handler\n\t\tswitch (msg.type) {\n\t\t\tcase 'response.created':\n\t\t\t\tthis.handleResponseCreated(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'response.done':\n\t\t\t\tawait this.handleResponseDone(msg, dataChannel)\n\t\t\t\tbreak\n\n\t\t\tcase 'response.function_call_arguments.done':\n\t\t\t\tthis.handleFunctionCallArguments()\n\t\t\t\tbreak\n\n\t\t\tcase 'input_audio_buffer.speech_started':\n\t\t\tcase 'input_audio_buffer.speech_stopped':\n\t\t\t\tthis.handleSpeechEvents(msg)\n\t\t\t\tbreak\n\n\t\t\t// GA API: response.output_audio events\n\t\t\tcase 'response.output_audio.delta':\n\t\t\tcase 'response.output_audio.done':\n\t\t\t\tthis.handleAudioEvents(msg)\n\t\t\t\tbreak\n\n\t\t\t// GA API: response.output_audio_transcript and response.output_text events\n\t\t\tcase 'response.output_audio_transcript.delta':\n\t\t\tcase 'response.output_audio_transcript.done':\n\t\t\tcase 'response.output_text.delta':\n\t\t\tcase 'response.output_text.done':\n\t\t\t\tthis.handleTranscriptEvents(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'conversation.item.input_audio_transcription.completed':\n\t\t\t\tthis.handleUserTranscript(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'error':\n\t\t\t\tthis.handleError(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'session.created':\n\t\t\tcase 'session.updated':\n\t\t\t\tthis.handleSessionEvents(msg)\n\t\t\t\tbreak\n\n\t\t\tcase 'conversation.item.created':\n\t\t\tcase 'input_audio_buffer.committed':\n\t\t\t\t// Log only, no action needed\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate handleResponseCreated(_msg: RealtimeMessage): void {\n\t\tthis.isProcessingResponse = true\n\t\tthis.hasRequestedResponse = false\n\t}\n\n\tprivate async handleResponseDone(\n\t\tmsg: RealtimeMessage,\n\t\tdataChannel: RTCDataChannel\n\t): Promise<void> {\n\t\t// Safely extract response output with proper type checking\n\t\tconst outputItems = this.extractResponseOutput(msg.response)\n\n\t\t// Check if there are function calls to process\n\t\tconst hasFunctionCalls = outputItems.some(isCompletedFunctionCall)\n\n\t\t// Only set isProcessingResponse to false if there are no function calls\n\t\tif (!hasFunctionCalls) {\n\t\t\tthis.isProcessingResponse = false\n\t\t\tthis.hasRequestedResponse = false\n\t\t}\n\n\t\t// Process any function calls in the response\n\t\tif (outputItems.length > 0) {\n\t\t\t// Extract function calls with proper type narrowing\n\t\t\tconst functionCalls: FunctionCall[] = outputItems\n\t\t\t\t.filter(isCompletedFunctionCall)\n\t\t\t\t.map((item) => ({\n\t\t\t\t\tname: item.name,\n\t\t\t\t\tcall_id: item.call_id,\n\t\t\t\t\targuments: item.arguments ?? '',\n\t\t\t\t}))\n\n\t\t\tfor (const functionCall of functionCalls) {\n\t\t\t\tif (!this.pendingFunctionCalls.has(functionCall.call_id)) {\n\t\t\t\t\tthis.pendingFunctionCalls.add(functionCall.call_id)\n\t\t\t\t\tawait this.executeFunctionCall(functionCall, dataChannel)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[MessageHandler] Skipping duplicate function call: ${functionCall.name} (${functionCall.call_id})`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// After all function calls are processed, check if we need to request a response\n\t\t\tif (functionCalls.length > 0 && this.pendingFunctionCalls.size === 0) {\n\t\t\t\tthis.requestResponseIfNeeded(dataChannel)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Safely extract response output array from response object\n\t */\n\tprivate extractResponseOutput(response: unknown): ResponseOutputItem[] {\n\t\tif (!response || typeof response !== 'object') {\n\t\t\treturn []\n\t\t}\n\n\t\tconst r = response as Record<string, unknown>\n\t\tif (!Array.isArray(r.output)) {\n\t\t\treturn []\n\t\t}\n\n\t\t// Filter to only valid output items\n\t\treturn r.output.filter(\n\t\t\t(item): item is ResponseOutputItem =>\n\t\t\t\titem !== null &&\n\t\t\t\ttypeof item === 'object' &&\n\t\t\t\ttypeof (item as ResponseOutputItem).type === 'string'\n\t\t)\n\t}\n\n\tprivate handleFunctionCallArguments(): void {\n\t\t// Function call arguments are being accumulated\n\t\t// Actual execution happens in handleResponseDone\n\t}\n\n\tprivate handleSpeechEvents(msg: RealtimeMessage): void {\n\t\tconst eventType =\n\t\t\tmsg.type === 'input_audio_buffer.speech_started' ? 'speech_started' : 'speech_stopped'\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate handleAudioEvents(msg: RealtimeMessage): void {\n\t\tconst eventType = msg.type === 'response.output_audio.delta' ? 'audio_started' : 'audio_stopped'\n\t\tconsole.log(`[MessageHandler] Assistant ${eventType}`, {\n\t\t\ttype: msg.type,\n\t\t\thasAudio: !!(msg as { delta?: unknown }).delta,\n\t\t})\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate handleTranscriptEvents(msg: RealtimeMessage): void {\n\t\t// GA API event name mappings\n\t\tconst eventMap: Record<string, string> = {\n\t\t\t'response.output_audio_transcript.delta': 'assistant_transcript',\n\t\t\t'response.output_audio_transcript.done': 'assistant_transcript_done',\n\t\t\t'response.output_text.delta': 'text',\n\t\t\t'response.output_text.done': 'text_done',\n\t\t}\n\n\t\tconst eventType = eventMap[msg.type]\n\t\tif (eventType) {\n\t\t\tthis.eventEmitter.emit(eventType, msg)\n\t\t}\n\t}\n\n\tprivate handleUserTranscript(msg: RealtimeMessage): void {\n\t\tthis.eventEmitter.emit('user_transcript_done', { text: msg.transcript })\n\t}\n\n\tprivate handleSessionEvents(_msg: RealtimeMessage): void {\n\t\t// Session events are handled but no action is needed at this time\n\t}\n\n\tprivate handleError(msg: RealtimeMessage): void {\n\t\tconsole.error('Realtime API error:', msg)\n\t\tthis.eventEmitter.emit('error', msg)\n\t\tthis.isProcessingResponse = false\n\t\tthis.hasRequestedResponse = false\n\n\t\t// Clear any pending response timer\n\t\tif (this.responseRequestTimer) {\n\t\t\tclearTimeout(this.responseRequestTimer)\n\t\t\tthis.responseRequestTimer = null\n\t\t}\n\t}\n\n\tprivate async executeFunctionCall(\n\t\tfunctionCall: FunctionCall,\n\t\tdataChannel: RTCDataChannel\n\t): Promise<void> {\n\t\tconst { name, call_id } = functionCall\n\n\t\ttry {\n\t\t\t// Emit start event\n\t\t\tthis.eventEmitter.emit('tool_call_started', { name })\n\n\t\t\t// Execute tool\n\t\t\tconst result = await this.toolManager.executeToolCall(functionCall)\n\n\t\t\t// Check if data channel is still open before sending\n\t\t\tif (dataChannel.readyState !== 'open') {\n\t\t\t\tconsole.error(\n\t\t\t\t\t`[MessageHandler] Cannot send tool result for ${name}: DataChannel is ${dataChannel.readyState}`\n\t\t\t\t)\n\t\t\t\tthis.eventEmitter.emit('tool_call_completed', {\n\t\t\t\t\tname,\n\t\t\t\t\terror: 'DataChannel closed during tool execution',\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Send result back\n\t\t\tconst response = {\n\t\t\t\ttype: 'conversation.item.create',\n\t\t\t\titem: {\n\t\t\t\t\ttype: 'function_call_output',\n\t\t\t\t\tcall_id: call_id,\n\t\t\t\t\toutput: JSON.stringify(\n\t\t\t\t\t\tresult.success\n\t\t\t\t\t\t\t? result.data\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tdataChannel.send(JSON.stringify(response))\n\n\t\t\t// Emit completion event\n\t\t\tthis.eventEmitter.emit('tool_call_completed', {\n\t\t\t\tname,\n\t\t\t\terror: result.success ? undefined : result.error,\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tconsole.error(`[MessageHandler] Tool execution failed for ${name}:`, error)\n\t\t\tthis.sendToolError(call_id, String(error), dataChannel)\n\t\t} finally {\n\t\t\tthis.pendingFunctionCalls.delete(call_id)\n\n\t\t\t// After removing this function call, check if all are complete\n\t\t\tif (this.pendingFunctionCalls.size === 0) {\n\t\t\t\t// All function calls are done, now we can request a response\n\t\t\t\tthis.isProcessingResponse = false\n\t\t\t\tthis.hasRequestedResponse = false\n\t\t\t\tthis.requestResponseIfNeeded(dataChannel)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate sendToolError(call_id: string, error: string, dataChannel: RTCDataChannel): void {\n\t\t// Check if data channel is still open before sending error\n\t\tif (dataChannel.readyState !== 'open') {\n\t\t\tconsole.error(\n\t\t\t\t`[MessageHandler] Cannot send tool error: DataChannel is ${dataChannel.readyState}`\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\tconst errorResponse = {\n\t\t\ttype: 'conversation.item.create',\n\t\t\titem: {\n\t\t\t\ttype: 'function_call_output',\n\t\t\t\tcall_id: call_id,\n\t\t\t\toutput: JSON.stringify({ error, success: false }),\n\t\t\t},\n\t\t}\n\n\t\tdataChannel.send(JSON.stringify(errorResponse))\n\t}\n\n\tprivate requestResponseIfNeeded(dataChannel: RTCDataChannel): void {\n\t\t// Clear any existing timer\n\t\tif (this.responseRequestTimer) {\n\t\t\tclearTimeout(this.responseRequestTimer)\n\t\t\tthis.responseRequestTimer = null\n\t\t}\n\n\t\t// Set a new timer to request response (delay prevents race conditions)\n\t\tthis.responseRequestTimer = setTimeout(() => {\n\t\t\tif (\n\t\t\t\t!this.isProcessingResponse &&\n\t\t\t\t!this.hasRequestedResponse &&\n\t\t\t\tdataChannel.readyState === 'open' &&\n\t\t\t\tthis.pendingFunctionCalls.size === 0\n\t\t\t) {\n\t\t\t\tthis.hasRequestedResponse = true\n\t\t\t\tthis.isProcessingResponse = true\n\t\t\t\tdataChannel.send(JSON.stringify({ type: 'response.create' }))\n\t\t\t}\n\t\t\tthis.responseRequestTimer = null\n\t\t}, RESPONSE_REQUEST_DELAY_MS)\n\t}\n\n\treset(): void {\n\t\tthis.isProcessingResponse = false\n\t\tthis.hasRequestedResponse = false\n\t\tthis.pendingFunctionCalls.clear()\n\n\t\t// Clear any pending response timer\n\t\tif (this.responseRequestTimer) {\n\t\t\tclearTimeout(this.responseRequestTimer)\n\t\t\tthis.responseRequestTimer = null\n\t\t}\n\t}\n}\n","import { jsonrepair } from 'jsonrepair'\n\nimport type { FunctionCall, OpenAITool, ToolExecutionResult } from './types'\n\nexport interface RegisteredTool {\n\tname: string\n\tdescription: string\n\tinputSchema?: Record<string, unknown>\n}\n\nexport type ToolExecutor = (name: string, args: Record<string, unknown>) => Promise<unknown>\n\nexport class ToolManager {\n\tprivate tools: RegisteredTool[] = []\n\tprivate executor: ToolExecutor | null = null\n\tprivate lastSentToolSignature = ''\n\n\tsetTools(tools: RegisteredTool[]): void {\n\t\tthis.tools = tools\n\t}\n\n\tsetExecutor(executor: ToolExecutor): void {\n\t\tthis.executor = executor\n\t}\n\n\tresetSession(): void {\n\t\tconsole.log('[ToolManager] resetSession called (lastSentToolSignature preserved)')\n\t}\n\n\tprivate getToolSignature(tools: RegisteredTool[]): string {\n\t\treturn tools\n\t\t\t.map((t) => t.name)\n\t\t\t.sort()\n\t\t\t.join('|')\n\t}\n\n\thasToolsChanged(): boolean {\n\t\tconst currentSignature = this.getToolSignature(this.tools)\n\t\treturn currentSignature !== this.lastSentToolSignature\n\t}\n\n\tmarkToolsSent(): void {\n\t\tthis.lastSentToolSignature = this.getToolSignature(this.tools)\n\t}\n\n\tformatToolsForOpenAI(): OpenAITool[] {\n\t\t// Built-in tools\n\t\tconst builtInTools: OpenAITool[] = [\n\t\t\t{\n\t\t\t\ttype: 'function',\n\t\t\t\tname: 'list_available_tools',\n\t\t\t\tdescription:\n\t\t\t\t\t'List all currently available tools that can be called. Use this when you need to know what tools are available or when the user asks about available capabilities.',\n\t\t\t\tparameters: {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tproperties: {},\n\t\t\t\t\trequired: [],\n\t\t\t\t},\n\t\t\t},\n\t\t]\n\n\t\t// Registered tools\n\t\tconst registeredTools = this.tools.map((tool) => ({\n\t\t\ttype: 'function' as const,\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description || `Execute ${tool.name} action`,\n\t\t\tparameters: this.validateToolSchema(tool.inputSchema),\n\t\t}))\n\n\t\treturn [...builtInTools, ...registeredTools]\n\t}\n\n\tprivate validateToolSchema(schema: Record<string, unknown> | undefined): {\n\t\ttype: string\n\t\tproperties?: Record<string, unknown>\n\t\trequired?: string[]\n\t} {\n\t\tif (!schema) {\n\t\t\treturn { type: 'object', properties: {}, required: [] }\n\t\t}\n\n\t\tconst result: {\n\t\t\ttype: string\n\t\t\tproperties?: Record<string, unknown>\n\t\t\trequired?: string[]\n\t\t} = { type: 'object', ...schema }\n\n\t\tif (result.type === 'object') {\n\t\t\tresult.properties = (result.properties as Record<string, unknown>) || {}\n\n\t\t\t// Validate and fix nested schemas (especially arrays missing 'items')\n\t\t\tresult.properties = this.validateNestedSchemas(result.properties)\n\n\t\t\t// Generate required array if not present\n\t\t\tif (!result.required && result.properties) {\n\t\t\t\tresult.required = Object.entries(result.properties)\n\t\t\t\t\t.filter(([, prop]) => {\n\t\t\t\t\t\tif (prop && typeof prop === 'object') {\n\t\t\t\t\t\t\tconst p = prop as { optional?: boolean; nullable?: boolean; type?: string }\n\t\t\t\t\t\t\treturn !p.optional && !p.nullable && p.type !== 'null'\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false\n\t\t\t\t\t})\n\t\t\t\t\t.map(([key]) => key)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Recursively validate nested schemas, ensuring array types have 'items'.\n\t * The OpenAI Realtime API requires array schemas to have an 'items' field.\n\t */\n\tprivate validateNestedSchemas(properties: Record<string, unknown>): Record<string, unknown> {\n\t\tconst validated: Record<string, unknown> = {}\n\n\t\tfor (const [key, value] of Object.entries(properties)) {\n\t\t\tif (!value || typeof value !== 'object') {\n\t\t\t\tvalidated[key] = value\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst prop = value as Record<string, unknown>\n\t\t\tconst propType = prop.type as string | undefined\n\n\t\t\tif (propType === 'array') {\n\t\t\t\t// Ensure array schemas have 'items' - required by OpenAI Realtime API\n\t\t\t\tif (!prop.items) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`[ToolManager] Array property '${key}' missing 'items' - adding default string items`\n\t\t\t\t\t)\n\t\t\t\t\tvalidated[key] = {\n\t\t\t\t\t\t...prop,\n\t\t\t\t\t\titems: { type: 'string' },\n\t\t\t\t\t}\n\t\t\t\t} else if (typeof prop.items === 'object') {\n\t\t\t\t\t// Recursively validate items schema\n\t\t\t\t\tconst items = prop.items as Record<string, unknown>\n\t\t\t\t\tif (items.type === 'object' && items.properties) {\n\t\t\t\t\t\tvalidated[key] = {\n\t\t\t\t\t\t\t...prop,\n\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t...items,\n\t\t\t\t\t\t\t\tproperties: this.validateNestedSchemas(items.properties as Record<string, unknown>),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalidated[key] = prop\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tvalidated[key] = prop\n\t\t\t\t}\n\t\t\t} else if (propType === 'object' && prop.properties) {\n\t\t\t\t// Recursively validate nested object properties\n\t\t\t\tvalidated[key] = {\n\t\t\t\t\t...prop,\n\t\t\t\t\tproperties: this.validateNestedSchemas(prop.properties as Record<string, unknown>),\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tvalidated[key] = prop\n\t\t\t}\n\t\t}\n\n\t\treturn validated\n\t}\n\n\tasync executeToolCall(functionCall: FunctionCall): Promise<ToolExecutionResult> {\n\t\tconst { name, arguments: argsString } = functionCall\n\n\t\t// Handle built-in tools\n\t\tif (name === 'list_available_tools') {\n\t\t\treturn this.executeListTools()\n\t\t}\n\n\t\t// Check if executor is set\n\t\tif (!this.executor) {\n\t\t\tconsole.error('[ToolManager] Tool executor not configured')\n\t\t\treturn { success: false, error: 'Tool executor not configured' }\n\t\t}\n\n\t\t// Parse arguments - use jsonrepair to handle malformed JSON from OpenAI\n\t\tlet args: Record<string, unknown>\n\t\ttry {\n\t\t\tconst repaired = argsString ? jsonrepair(argsString) : '{}'\n\t\t\targs = JSON.parse(repaired) as Record<string, unknown>\n\t\t} catch (error) {\n\t\t\tconsole.error('[ToolManager] Failed to parse arguments:', error)\n\t\t\tconsole.error('[ToolManager] Raw argsString:', argsString?.slice(0, 200))\n\t\t\treturn { success: false, error: 'Invalid arguments format' }\n\t\t}\n\n\t\t// Execute via the executor - it handles tool lookup from the current MCP context\n\t\t// Note: We intentionally don't verify the tool exists in this.tools first because\n\t\t// the executor has access to the latest tool list via React context/closure, which\n\t\t// may be more up-to-date than our cached copy (avoiding stale closure issues).\n\t\t// The executor will throw if the tool is not found.\n\t\ttry {\n\t\t\tconst result = await this.executor(name, args)\n\t\t\treturn { success: true, data: result }\n\t\t} catch (error) {\n\t\t\tconsole.error(`[ToolManager] Tool execution error for ${name}:`, error)\n\t\t\treturn { success: false, error: String(error) }\n\t\t}\n\t}\n\n\tprivate executeListTools(): ToolExecutionResult {\n\t\tconst toolList = this.tools.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description || 'No description available',\n\t\t\tparameters: tool.inputSchema || {},\n\t\t}))\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\ttools: toolList,\n\t\t\t\tcount: toolList.length,\n\t\t\t\tmessage:\n\t\t\t\t\ttoolList.length > 0\n\t\t\t\t\t\t? `Found ${toolList.length} available tools`\n\t\t\t\t\t\t: 'No tools currently available',\n\t\t\t},\n\t\t}\n\t}\n\n\tgetChangesSummary(): { added: string[]; removed: string[]; total: number } | null {\n\t\tif (!this.hasToolsChanged()) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst prevTools = this.lastSentToolSignature.split('|').filter(Boolean)\n\t\tconst currTools = this.tools.map((t) => t.name)\n\n\t\tconst prevSet = new Set(prevTools)\n\t\tconst currSet = new Set(currTools)\n\n\t\tconst added = currTools.filter((name) => !prevSet.has(name))\n\t\tconst removed = prevTools.filter((name) => !currSet.has(name))\n\n\t\treturn {\n\t\t\tadded,\n\t\t\tremoved,\n\t\t\ttotal: this.tools.length,\n\t\t}\n\t}\n}\n","import {\n\tdebugLog,\n\tREALTIME_DEFAULT_API_URL,\n\tREALTIME_DEFAULT_MODEL,\n\tREALTIME_DEFAULT_VOICE,\n} from '../../lib/constants'\n\nimport type { RealtimeConfig, RealtimeSession } from './types'\n\ninterface EphemeralTokenResponse {\n\tclient_secret?: {\n\t\tvalue?: string\n\t}\n}\n\nfunction hasClientSecret(response: unknown): response is {\n\tclient_secret: { value: string }\n} {\n\tif (!response || typeof response !== 'object') {\n\t\treturn false\n\t}\n\tconst secret = (response as EphemeralTokenResponse).client_secret\n\treturn typeof secret?.value === 'string'\n}\n\nexport class WebRTCManager {\n\tprivate tokenEndpoint: string\n\n\tconstructor(tokenEndpoint: string) {\n\t\tthis.tokenEndpoint = tokenEndpoint\n\t}\n\n\tasync createSession(config: RealtimeConfig = {}): Promise<RealtimeSession> {\n\t\tconst model = config.model || REALTIME_DEFAULT_MODEL\n\t\tconst voice = config.voice || REALTIME_DEFAULT_VOICE\n\t\tconst apiUrl = config.apiUrl || REALTIME_DEFAULT_API_URL\n\n\t\t// Get ephemeral token from our backend\n\t\tconst ephemeralKey = await this.getEphemeralToken(model, voice)\n\n\t\t// Create peer connection\n\t\tconst pc = new RTCPeerConnection()\n\n\t\t// Set up audio playback\n\t\tconst audioElement = this.createAudioElement()\n\t\t// Track streams\n\t\tlet remoteStream: MediaStream | null = null\n\t\tpc.ontrack = (e) => {\n\t\t\tremoteStream = e.streams[0]\n\t\t\taudioElement.srcObject = remoteStream\n\t\t\tdebugLog('WebRTC', 'Remote audio stream received and connected to audio element', {\n\t\t\t\tstreamId: remoteStream.id,\n\t\t\t\ttracks: remoteStream.getTracks().length,\n\t\t\t})\n\t\t}\n\n\t\t// Add microphone\n\t\tconst localStream = await this.getUserMedia()\n\t\tdebugLog('WebRTC', 'Local microphone stream acquired', {\n\t\t\tstreamId: localStream.id,\n\t\t\ttracks: localStream.getTracks().map((t) => ({\n\t\t\t\tkind: t.kind,\n\t\t\t\tenabled: t.enabled,\n\t\t\t\tmuted: t.muted,\n\t\t\t\treadyState: t.readyState,\n\t\t\t})),\n\t\t})\n\n\t\tlocalStream.getTracks().forEach((track) => {\n\t\t\tpc.addTrack(track, localStream)\n\t\t})\n\n\t\t// Create data channel for events\n\t\tconst dataChannel = pc.createDataChannel('oai-events')\n\n\t\t// Create offer and establish connection\n\t\tconst offer = await pc.createOffer()\n\t\tawait pc.setLocalDescription(offer)\n\n\t\t// Connect to OpenAI\n\t\tif (!offer.sdp) {\n\t\t\tthrow new Error('Failed to create offer SDP')\n\t\t}\n\t\tconst answer = await this.connectToOpenAI(apiUrl, model, offer.sdp, ephemeralKey)\n\t\tawait pc.setRemoteDescription(answer)\n\n\t\t// Create cleanup function\n\t\tconst cleanup = () => {\n\t\t\tlocalStream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t\taudioElement.remove()\n\t\t\tdataChannel.close()\n\t\t\tpc.close()\n\t\t}\n\n\t\treturn {\n\t\t\tpc,\n\t\t\tdataChannel,\n\t\t\taudioElement,\n\t\t\tlocalStream,\n\t\t\tremoteStream,\n\t\t\tcleanup,\n\t\t}\n\t}\n\n\tprivate async getEphemeralToken(model: string, voice: string): Promise<string> {\n\t\tconst response = await fetch(this.tokenEndpoint, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify({ model, voice }),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tconst errorText = await response.text()\n\t\t\tconsole.error('Failed to get ephemeral token:', errorText)\n\t\t\tthrow new Error(`Failed to get ephemeral token: ${response.statusText}`)\n\t\t}\n\n\t\tconst data: unknown = await response.json()\n\n\t\tif (!hasClientSecret(data)) {\n\t\t\tthrow new Error('Invalid token response format')\n\t\t}\n\n\t\treturn data.client_secret.value\n\t}\n\n\tprivate createAudioElement(): HTMLAudioElement {\n\t\tconst audioElement = document.createElement('audio')\n\t\taudioElement.autoplay = true\n\t\taudioElement.style.display = 'none'\n\t\tdocument.body.appendChild(audioElement)\n\t\treturn audioElement\n\t}\n\n\tprivate async getUserMedia(): Promise<MediaStream> {\n\t\ttry {\n\t\t\treturn await navigator.mediaDevices.getUserMedia({\n\t\t\t\taudio: {\n\t\t\t\t\techoCancellation: true,\n\t\t\t\t\tnoiseSuppression: true,\n\t\t\t\t\tautoGainControl: true,\n\t\t\t\t},\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to access microphone: ${error}`)\n\t\t}\n\t}\n\n\tprivate async connectToOpenAI(\n\t\tbaseUrl: string,\n\t\tmodel: string,\n\t\tsdp: string,\n\t\tephemeralKey: string\n\t): Promise<RTCSessionDescriptionInit> {\n\t\tconst response = await fetch(`${baseUrl}?model=${model}`, {\n\t\t\tmethod: 'POST',\n\t\t\tbody: sdp,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${ephemeralKey}`,\n\t\t\t\t'Content-Type': 'application/sdp',\n\t\t\t},\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Failed to establish WebRTC connection: ${response.statusText}`)\n\t\t}\n\n\t\tconst answerSdp = await response.text()\n\t\treturn {\n\t\t\ttype: 'answer' as const,\n\t\t\tsdp: answerSdp,\n\t\t}\n\t}\n}\n","import {\n\tAUDIO_FREQUENCY_BINS,\n\tAUDIO_VISUALIZATION_INTERVAL_MS,\n\tdebugLog,\n} from '../../lib/constants'\nimport { AudioAnalyzer } from './audio-analyzer'\nimport { EventEmitter } from './event-emitter'\nimport { MessageHandler } from './message-handler'\nimport { ToolManager } from './tool-manager'\nimport { WebRTCManager } from './webrtc-manager'\n\nimport type { RegisteredTool, ToolExecutor } from './tool-manager'\nimport type { EventCallback, RealtimeConfig, RealtimeSession, SessionConfig } from './types'\n\n/** Pre-allocated zero frequency array for performance */\nconst EMPTY_FREQUENCY_TEMPLATE = Object.freeze(new Array(AUDIO_FREQUENCY_BINS).fill(0))\nconst createZeroFrequencyArray = (): number[] => [...EMPTY_FREQUENCY_TEMPLATE]\n\n/**\n * OpenAI Realtime API Service\n *\n * Manages voice conversations with OpenAI's Realtime API,\n * including WebRTC connections, tool integration, and message handling.\n */\nexport class OpenAIRealtimeService {\n\tprivate session: RealtimeSession | null = null\n\tprivate webrtcManager: WebRTCManager\n\tprivate toolManager: ToolManager\n\tprivate messageHandler: MessageHandler\n\tprivate eventEmitter: EventEmitter\n\tprivate muted = false\n\tprivate lastState: 'disconnected' | 'connecting' | 'connected' | 'error' = 'disconnected'\n\tprivate localAnalyzer: AudioAnalyzer | null = null\n\tprivate remoteAnalyzer: AudioAnalyzer | null = null\n\tprivate visualizationInterval: ReturnType<typeof setInterval> | null = null\n\tprivate sessionStartTime: number | null = null\n\tprivate onToolsChangedCallback: (() => void) | null = null\n\n\tconstructor(tokenEndpoint: string) {\n\t\tthis.webrtcManager = new WebRTCManager(tokenEndpoint)\n\t\tthis.toolManager = new ToolManager()\n\t\tthis.eventEmitter = new EventEmitter()\n\t\tthis.messageHandler = new MessageHandler(this.toolManager, this.eventEmitter)\n\t}\n\n\t/**\n\t * Set the tools available for the voice session\n\t */\n\tsetTools(tools: RegisteredTool[]): void {\n\t\tthis.toolManager.setTools(tools)\n\t\tif (this.isSessionActive()) {\n\t\t\tthis.updateSessionTools()\n\t\t}\n\t}\n\n\t/**\n\t * Set the tool executor function\n\t */\n\tsetToolExecutor(executor: ToolExecutor): void {\n\t\tthis.toolManager.setExecutor(executor)\n\t}\n\n\t/**\n\t * Register callback for when tools change\n\t */\n\tonToolsChanged(callback: () => void): void {\n\t\tthis.onToolsChangedCallback = callback\n\t}\n\n\t/**\n\t * Start a new realtime session\n\t */\n\tasync startSession(config: RealtimeConfig = {}): Promise<RealtimeSession> {\n\t\ttry {\n\t\t\t// Clean up existing session\n\t\t\tif (this.session) {\n\t\t\t\tthis.stopSession()\n\t\t\t}\n\n\t\t\tthis.muted = false\n\t\t\tthis.sessionStartTime = Date.now()\n\t\t\tthis.emitSessionState('connecting')\n\n\t\t\t// Create new WebRTC session\n\t\t\tthis.session = await this.webrtcManager.createSession(config)\n\n\t\t\t// Setup data channel handlers\n\t\t\tthis.setupDataChannel(this.session.dataChannel)\n\n\t\t\t// Monitor peer connection state\n\t\t\tthis.setupPeerConnectionMonitoring(this.session.pc)\n\n\t\t\tif (this.session.localStream) {\n\t\t\t\tawait this.initializeLocalAnalyzer(this.session.localStream)\n\t\t\t}\n\n\t\t\tif (this.session.remoteStream) {\n\t\t\t\tvoid this.initializeRemoteAnalyzer(this.session.remoteStream)\n\t\t\t}\n\n\t\t\t// Update session reference for remote stream\n\t\t\tconst originalOntrack = this.session.pc.ontrack\n\t\t\tconst session = this.session\n\t\t\tthis.session.pc.ontrack = (e) => {\n\t\t\t\tif (originalOntrack) originalOntrack.call(session.pc, e)\n\t\t\t\tif (this.session) {\n\t\t\t\t\tthis.session.remoteStream = e.streams[0]\n\t\t\t\t}\n\n\t\t\t\tconst remoteStream = e.streams[0]\n\t\t\t\tif (!remoteStream) {\n\t\t\t\t\tconsole.warn('[OpenAIRealtimeService] Received ontrack event without stream')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tvoid this.initializeRemoteAnalyzer(remoteStream)\n\t\t\t}\n\n\t\t\treturn this.session\n\t\t} catch (error) {\n\t\t\tthis.handleSessionError(error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Stop the current session\n\t */\n\tstopSession(): void {\n\t\t// Calculate session duration for usage tracking\n\t\tlet durationSeconds = 0\n\t\tif (this.sessionStartTime) {\n\t\t\tdurationSeconds = Math.floor((Date.now() - this.sessionStartTime) / 1000)\n\t\t}\n\n\t\tif (this.visualizationInterval) {\n\t\t\tclearInterval(this.visualizationInterval)\n\t\t\tthis.visualizationInterval = null\n\t\t}\n\n\t\tif (this.localAnalyzer) {\n\t\t\tthis.localAnalyzer.destroy()\n\t\t\tthis.localAnalyzer = null\n\t\t}\n\n\t\tif (this.remoteAnalyzer) {\n\t\t\tthis.remoteAnalyzer.destroy()\n\t\t\tthis.remoteAnalyzer = null\n\t\t}\n\t\tif (this.session) {\n\t\t\tthis.session.cleanup()\n\t\t\tthis.session = null\n\t\t}\n\t\tthis.messageHandler.reset()\n\t\tthis.toolManager.resetSession()\n\n\t\t// Emit disconnected state with session duration\n\t\tthis.muted = false\n\t\tthis.emitSessionState('disconnected', { durationSeconds })\n\n\t\t// Reset session start time\n\t\tthis.sessionStartTime = null\n\t}\n\n\t/**\n\t * Send a text message to the assistant\n\t */\n\tsendUserMessage(text: string): void {\n\t\tif (!this.isSessionActive()) {\n\t\t\tthrow new Error('No active session')\n\t\t}\n\n\t\tconst message = {\n\t\t\ttype: 'conversation.item.create',\n\t\t\titem: {\n\t\t\t\ttype: 'message',\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: [{ type: 'input_text', text }],\n\t\t\t},\n\t\t}\n\n\t\tif (!this.session) {\n\t\t\tthrow new Error('Session is not active')\n\t\t}\n\t\tthis.session.dataChannel.send(JSON.stringify(message))\n\t\tthis.session.dataChannel.send(JSON.stringify({ type: 'response.create' }))\n\t}\n\n\t/**\n\t * Check if session is active\n\t */\n\tisSessionActive(): boolean {\n\t\treturn this.session !== null && this.session.dataChannel.readyState === 'open'\n\t}\n\n\t/**\n\t * Get the local audio stream\n\t */\n\tgetLocalStream(): MediaStream | null {\n\t\treturn this.session?.localStream || null\n\t}\n\n\t/**\n\t * Get the remote audio stream\n\t */\n\tgetRemoteStream(): MediaStream | null {\n\t\treturn this.session?.remoteStream || null\n\t}\n\n\t/**\n\t * Toggle audio mute\n\t */\n\ttoggleMute(muted: boolean): void {\n\t\tif (this.session?.audioElement) {\n\t\t\tthis.session.audioElement.muted = muted\n\t\t}\n\t\tthis.muted = muted\n\t\tthis.emitSessionState(this.lastState, { isMuted: this.muted })\n\t}\n\n\t/**\n\t * Pause audio playback (for approval flow)\n\t * This pauses the audio element without stopping the WebRTC stream.\n\t */\n\tpauseAudio(): void {\n\t\tif (this.session?.audioElement) {\n\t\t\tthis.session.audioElement.pause()\n\t\t}\n\t}\n\n\t/**\n\t * Resume audio playback (after approval flow)\n\t */\n\tresumeAudio(): void {\n\t\tif (this.session?.audioElement) {\n\t\t\tthis.session.audioElement.play().catch((error) => {\n\t\t\t\t// Handle autoplay restrictions gracefully\n\t\t\t\tconsole.warn('[OpenAIRealtimeService] Failed to resume audio:', error)\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Event handling\n\t */\n\ton(event: string, callback: EventCallback): void {\n\t\tthis.eventEmitter.on(event, callback)\n\t}\n\n\toff(event: string, callback: EventCallback): void {\n\t\tthis.eventEmitter.off(event, callback)\n\t}\n\n\tgetSessionStatus(): {\n\t\tstate: 'connecting' | 'connected' | 'disconnected' | 'error'\n\t\tisActive: boolean\n\t\tisMuted: boolean\n\t} {\n\t\treturn {\n\t\t\tstate: this.lastState,\n\t\t\tisActive: this.lastState === 'connected',\n\t\t\tisMuted: this.muted,\n\t\t}\n\t}\n\n\t/**\n\t * Private methods\n\t */\n\tprivate setupDataChannel(dataChannel: RTCDataChannel): void {\n\t\t// Configure session when channel opens\n\t\tdataChannel.addEventListener('open', () => {\n\t\t\tthis.configureSession(dataChannel)\n\t\t\tthis.muted = false\n\t\t\tthis.emitSessionState('connected')\n\t\t})\n\n\t\t// Handle incoming messages\n\t\tdataChannel.addEventListener('message', (event: MessageEvent<string>) => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.messageHandler.handleMessage(event.data, dataChannel)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error('Error handling message:', error)\n\t\t\t\t}\n\t\t\t})()\n\t\t})\n\n\t\t// Handle errors\n\t\tdataChannel.addEventListener('error', (error) => {\n\t\t\tconsole.error('DataChannel error:', error)\n\t\t\tthis.eventEmitter.emit('error', { type: 'datachannel_error', error })\n\t\t})\n\n\t\t// Handle close\n\t\tdataChannel.addEventListener('close', () => {\n\t\t\tthis.messageHandler.reset()\n\t\t\tthis.eventEmitter.emit('session_closed', {})\n\t\t})\n\t}\n\n\tprivate setupPeerConnectionMonitoring(pc: RTCPeerConnection): void {\n\t\t// Monitor connection state changes\n\t\tpc.addEventListener('connectionstatechange', () => {\n\t\t\tif (pc.connectionState === 'failed' || pc.connectionState === 'disconnected') {\n\t\t\t\tconsole.error('Peer connection failed or disconnected')\n\t\t\t\tthis.messageHandler.reset()\n\t\t\t\tthis.eventEmitter.emit('error', {\n\t\t\t\t\ttype: 'connection_error',\n\t\t\t\t\tmessage: `Connection ${pc.connectionState}`,\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\n\t\t// Monitor ICE connection state\n\t\tpc.addEventListener('iceconnectionstatechange', () => {\n\t\t\tif (pc.iceConnectionState === 'failed' || pc.iceConnectionState === 'disconnected') {\n\t\t\t\tconsole.error('ICE connection failed or disconnected')\n\t\t\t}\n\t\t})\n\n\t\t// Monitor signaling state\n\t\tpc.addEventListener('signalingstatechange', () => {})\n\t}\n\n\tprivate configureSession(dataChannel: RTCDataChannel): void {\n\t\t// Reset per-session state\n\t\tthis.toolManager.resetSession()\n\n\t\t// Get initial tools\n\t\tconst tools = this.toolManager.formatToolsForOpenAI()\n\t\t// Mark tools as sent\n\t\tthis.toolManager.markToolsSent()\n\n\t\tconst sessionConfig: SessionConfig = {\n\t\t\tmodalities: ['text', 'audio'],\n\t\t\tinstructions: this.getSessionInstructions(),\n\t\t\tvoice: 'echo',\n\t\t\ttools: tools,\n\t\t\ttool_choice: 'auto',\n\t\t\tturn_detection: {\n\t\t\t\ttype: 'server_vad',\n\t\t\t\tthreshold: 0.5,\n\t\t\t\tprefix_padding_ms: 300,\n\t\t\t\tsilence_duration_ms: 500,\n\t\t\t},\n\t\t\tinput_audio_transcription: {\n\t\t\t\tmodel: 'whisper-1',\n\t\t\t},\n\t\t}\n\n\t\tconst sessionUpdate = {\n\t\t\ttype: 'session.update',\n\t\t\tsession: sessionConfig,\n\t\t}\n\n\t\tdataChannel.send(JSON.stringify(sessionUpdate))\n\t}\n\n\tprivate updateSessionTools(): void {\n\t\tif (!this.session) {\n\t\t\tconsole.warn('[OpenAIRealtimeService] Cannot update tools: no active session')\n\t\t\treturn\n\t\t}\n\n\t\tif (this.session.dataChannel.readyState !== 'open') {\n\t\t\tconsole.warn(\n\t\t\t\t`[OpenAIRealtimeService] Cannot update tools: DataChannel is ${this.session.dataChannel.readyState}`\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\t// Check if tools have actually changed\n\t\tconst changesSummary = this.toolManager.getChangesSummary()\n\t\tif (!changesSummary) {\n\t\t\treturn\n\t\t}\n\n\t\t// Get the full tool list\n\t\tconst tools = this.toolManager.formatToolsForOpenAI()\n\n\t\tconsole.log(\n\t\t\t'[OpenAIRealtimeService] Sending tool update to OpenAI:',\n\t\t\t`${changesSummary.total} total tools,`,\n\t\t\tchangesSummary.added.length > 0\n\t\t\t\t? `+${changesSummary.added.length} added (${changesSummary.added.slice(0, 3).join(', ')}${changesSummary.added.length > 3 ? '...' : ''})`\n\t\t\t\t: '',\n\t\t\tchangesSummary.removed.length > 0 ? `-${changesSummary.removed.length} removed` : ''\n\t\t)\n\n\t\t// Mark tools as sent\n\t\tthis.toolManager.markToolsSent()\n\n\t\tconst sessionUpdate = {\n\t\t\ttype: 'session.update',\n\t\t\tsession: {\n\t\t\t\ttools: tools,\n\t\t\t\ttool_choice: 'auto',\n\t\t\t},\n\t\t}\n\n\t\tthis.session.dataChannel.send(JSON.stringify(sessionUpdate))\n\t}\n\n\tprivate getSessionInstructions(): string {\n\t\treturn `You are a helpful assistant with access to tools.\n Use the available tools to help users with their tasks.\n You can use the list_available_tools function to see what tools are currently available.\n Be concise and helpful in your responses.`\n\t}\n\n\tprivate handleSessionError(error: unknown): void {\n\t\tconsole.error('Session error:', error)\n\t\tthis.emitSessionState('error', {\n\t\t\ttype: 'session_error',\n\t\t\terror: String(error),\n\t\t})\n\t\tthis.stopSession()\n\t}\n\n\tprivate async initializeLocalAnalyzer(stream: MediaStream): Promise<void> {\n\t\tif (this.localAnalyzer) {\n\t\t\tthis.localAnalyzer.destroy()\n\t\t}\n\n\t\tthis.localAnalyzer = new AudioAnalyzer()\n\t\ttry {\n\t\t\t// Clone the stream to avoid conflicts with WebRTC which consumes the original\n\t\t\tconst clonedStream = new MediaStream(stream.getAudioTracks().map((t) => t.clone()))\n\t\t\tawait this.localAnalyzer.initialize(clonedStream)\n\t\t\tthis.startAudioVisualization()\n\t\t} catch (error) {\n\t\t\tconsole.error('[OpenAIRealtimeService] Failed to initialize local audio analyzer', error)\n\t\t\tif (this.localAnalyzer) {\n\t\t\t\tthis.localAnalyzer.destroy()\n\t\t\t\tthis.localAnalyzer = null\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async initializeRemoteAnalyzer(stream: MediaStream): Promise<void> {\n\t\tif (this.remoteAnalyzer) {\n\t\t\tthis.remoteAnalyzer.destroy()\n\t\t}\n\n\t\tthis.remoteAnalyzer = new AudioAnalyzer()\n\t\ttry {\n\t\t\t// Clone the stream to avoid conflicts with WebRTC\n\t\t\tconst clonedStream = new MediaStream(stream.getAudioTracks().map((t) => t.clone()))\n\t\t\tawait this.remoteAnalyzer.initialize(clonedStream)\n\t\t\tthis.startAudioVisualization()\n\t\t} catch (error) {\n\t\t\tconsole.error('[OpenAIRealtimeService] Failed to initialize remote audio analyzer', error)\n\t\t\tif (this.remoteAnalyzer) {\n\t\t\t\tthis.remoteAnalyzer.destroy()\n\t\t\t\tthis.remoteAnalyzer = null\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate startAudioVisualization(): void {\n\t\tif (!this.localAnalyzer && !this.remoteAnalyzer) {\n\t\t\tdebugLog('OpenAIRealtimeService', 'Audio visualization not started: no analyzers ready')\n\t\t\treturn\n\t\t}\n\n\t\tif (this.visualizationInterval) {\n\t\t\tclearInterval(this.visualizationInterval)\n\t\t}\n\n\t\tlet logCounter = 0\n\t\tthis.visualizationInterval = setInterval(() => {\n\t\t\tconst micLevel = this.localAnalyzer?.getAudioLevel() ?? 0\n\t\t\tconst micFrequency =\n\t\t\t\tthis.localAnalyzer?.getFrequencyData(AUDIO_FREQUENCY_BINS) ?? createZeroFrequencyArray()\n\t\t\tconst speakerLevel = this.remoteAnalyzer?.getAudioLevel() ?? 0\n\t\t\tconst speakerFrequency =\n\t\t\t\tthis.remoteAnalyzer?.getFrequencyData(AUDIO_FREQUENCY_BINS) ?? createZeroFrequencyArray()\n\n\t\t\t// Log audio levels periodically for debugging (every ~1 second)\n\t\t\tlogCounter++\n\t\t\tif (logCounter % 60 === 0) {\n\t\t\t\tdebugLog('OpenAIRealtimeService', 'Audio levels', {\n\t\t\t\t\tmic: micLevel.toFixed(3),\n\t\t\t\t\tspeaker: speakerLevel.toFixed(3),\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tthis.eventEmitter.emit('audio_level', {\n\t\t\t\tmicLevel,\n\t\t\t\tmicFrequency,\n\t\t\t\tspeakerLevel,\n\t\t\t\tspeakerFrequency,\n\t\t\t})\n\t\t}, AUDIO_VISUALIZATION_INTERVAL_MS)\n\t}\n\n\tprivate emitSessionState(\n\t\tstate: 'connecting' | 'connected' | 'disconnected' | 'error',\n\t\textra: Record<string, unknown> = {}\n\t): void {\n\t\tthis.lastState = state\n\t\tconst payload = {\n\t\t\tstate,\n\t\t\tisActive: state === 'connected',\n\t\t\tisMuted: this.muted,\n\t\t\t...extra,\n\t\t}\n\n\t\tthis.eventEmitter.emit('session_state', payload)\n\n\t\tswitch (state) {\n\t\t\tcase 'connecting':\n\t\t\t\tthis.eventEmitter.emit('session_connecting', payload)\n\t\t\t\tbreak\n\t\t\tcase 'connected':\n\t\t\t\tthis.eventEmitter.emit('session_connected', payload)\n\t\t\t\tbreak\n\t\t\tcase 'disconnected':\n\t\t\t\tthis.eventEmitter.emit('session_closed', payload)\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tthis.eventEmitter.emit('error', payload)\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tbreak\n\t\t}\n\t}\n}\n\n// Re-export types for convenience\nexport type { RealtimeConfig, RealtimeSession } from './types'\n","/**\n * Types for OpenAI Realtime API integration\n */\n\nexport interface RealtimeConfig {\n\tmodel?: string\n\tvoice?: string\n\tapiUrl?: string\n\ttokenEndpoint?: string\n}\n\nexport interface RealtimeSession {\n\tpc: RTCPeerConnection\n\tdataChannel: RTCDataChannel\n\taudioElement: HTMLAudioElement\n\tlocalStream: MediaStream | null\n\tremoteStream: MediaStream | null\n\tcleanup: () => void\n}\n\nexport interface OpenAITool {\n\ttype: 'function'\n\tname: string\n\tdescription: string\n\tparameters: {\n\t\ttype: string\n\t\tproperties?: Record<string, unknown>\n\t\trequired?: string[]\n\t}\n}\n\nexport interface SessionConfig {\n\tmodalities: string[]\n\tinstructions: string\n\tvoice?: string\n\ttools: OpenAITool[]\n\ttool_choice: string\n\tturn_detection: {\n\t\ttype: string\n\t\tthreshold: number\n\t\tprefix_padding_ms: number\n\t\tsilence_duration_ms: number\n\t}\n\tinput_audio_transcription?: {\n\t\tmodel: string\n\t}\n}\n\nexport interface FunctionCall {\n\tname: string\n\targuments: string\n\tcall_id: string\n\ttype?: string\n\tstatus?: string\n}\n\nexport interface ConversationItem {\n\ttype: string\n\trole?: string\n\tcontent?: unknown[]\n\tcall_id?: string\n\toutput?: string\n}\n\nexport interface RealtimeMessage {\n\ttype: string\n\t[key: string]: unknown\n}\n\nexport interface ToolExecutionResult {\n\tsuccess: boolean\n\tdata?: unknown\n\terror?: string\n}\n\nexport type EventCallback = (data: unknown) => void\n\nexport interface IEventEmitter {\n\ton(event: string, callback: EventCallback): void\n\toff(event: string, callback: EventCallback): void\n\temit(event: string, data: unknown): void\n}\n\nexport interface AudioLevelData {\n\tmicLevel: number\n\tmicFrequency: number[]\n\tspeakerLevel: number\n\tspeakerFrequency: number[]\n}\n\nexport interface TranscriptData {\n\ttype: 'user' | 'assistant'\n\ttext: string\n\tisDone: boolean\n}\n\nexport interface ToolCallData {\n\tstatus: 'started' | 'completed'\n\ttoolName: string\n\terror?: string\n}\n\nexport interface VoiceModeState {\n\tisActive: boolean\n\tisConnecting: boolean\n\tisMuted: boolean\n\tisError: boolean\n\tconnectionState: string\n\taudioLevel?: AudioLevelData\n\ttranscript?: TranscriptData\n\ttoolCall?: ToolCallData\n\terror?: string\n}\n\n// ============================================================================\n// Event Data Types - For type-safe event handling\n// ============================================================================\n\n/**\n * Session state event data from the realtime service\n */\nexport interface SessionStateEventData {\n\tstate: 'connecting' | 'connected' | 'disconnected' | 'error'\n\tisActive: boolean\n\tisMuted: boolean\n\tdurationSeconds?: number\n}\n\n/**\n * User transcript event data\n */\nexport interface UserTranscriptEventData {\n\ttext: string\n}\n\n/**\n * Assistant transcript streaming event data\n */\nexport interface AssistantTranscriptEventData {\n\tdelta?: string\n\ttranscript?: string\n}\n\n/**\n * Tool call started event data\n */\nexport interface ToolCallStartedEventData {\n\tname: string\n}\n\n/**\n * Tool call completed event data\n */\nexport interface ToolCallCompletedEventData {\n\tname: string\n\terror?: string\n}\n\n/**\n * Nested error object from OpenAI Realtime API\n */\nexport interface NestedErrorObject {\n\tcode?: string\n\tmessage?: string\n\tparam?: string\n\tevent_id?: string | null\n\ttype?: string\n}\n\n/**\n * Error event data\n * The 'error' field can be either a string or a nested error object from OpenAI\n */\nexport interface ErrorEventData {\n\terror?: string | NestedErrorObject\n\tmessage?: string\n\ttype?: string\n}\n\n// ============================================================================\n// Type Guards - Runtime type checking for event data\n// ============================================================================\n\n/**\n * Type guard for SessionStateEventData\n */\nexport function isSessionStateEventData(data: unknown): data is SessionStateEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn (\n\t\ttypeof d.state === 'string' &&\n\t\t['connecting', 'connected', 'disconnected', 'error'].includes(d.state) &&\n\t\ttypeof d.isActive === 'boolean' &&\n\t\ttypeof d.isMuted === 'boolean'\n\t)\n}\n\n/**\n * Type guard for UserTranscriptEventData\n */\nexport function isUserTranscriptEventData(data: unknown): data is UserTranscriptEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn typeof d.text === 'string'\n}\n\n/**\n * Type guard for AssistantTranscriptEventData\n */\nexport function isAssistantTranscriptEventData(\n\tdata: unknown\n): data is AssistantTranscriptEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn d.delta === undefined || typeof d.delta === 'string'\n}\n\n/**\n * Type guard for ToolCallStartedEventData\n */\nexport function isToolCallStartedEventData(data: unknown): data is ToolCallStartedEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn typeof d.name === 'string'\n}\n\n/**\n * Type guard for ToolCallCompletedEventData\n */\nexport function isToolCallCompletedEventData(data: unknown): data is ToolCallCompletedEventData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn typeof d.name === 'string'\n}\n\n/**\n * Type guard for ErrorEventData\n */\nexport function isErrorEventData(data: unknown): data is ErrorEventData {\n\tif (!data || typeof data !== 'object') return false\n\t// Error events must have at least one of these fields\n\tconst d = data as Record<string, unknown>\n\t// error can be a string OR an object with a message\n\tconst hasError = typeof d.error === 'string' || (typeof d.error === 'object' && d.error !== null)\n\treturn hasError || typeof d.message === 'string' || typeof d.type === 'string'\n}\n\n/**\n * Extract a string error message from ErrorEventData.\n * Handles both string errors and nested error objects from OpenAI Realtime API.\n */\nexport function extractErrorMessage(data: ErrorEventData): string {\n\t// Handle nested error object (OpenAI Realtime API format)\n\tif (data.error && typeof data.error === 'object') {\n\t\tconst nestedError = data.error as NestedErrorObject\n\t\treturn nestedError.message || nestedError.code || 'Unknown error'\n\t}\n\n\t// Handle string error\n\tif (typeof data.error === 'string') {\n\t\treturn data.error\n\t}\n\n\t// Fallback to message field\n\tif (typeof data.message === 'string') {\n\t\treturn data.message\n\t}\n\n\treturn 'Unknown error'\n}\n\n/**\n * Type guard for AudioLevelData\n */\nexport function isAudioLevelData(data: unknown): data is AudioLevelData {\n\tif (!data || typeof data !== 'object') return false\n\tconst d = data as Record<string, unknown>\n\treturn (\n\t\ttypeof d.micLevel === 'number' &&\n\t\tArray.isArray(d.micFrequency) &&\n\t\ttypeof d.speakerLevel === 'number' &&\n\t\tArray.isArray(d.speakerFrequency)\n\t)\n}\n","/**\n * Voice Mode Hook\n *\n * Manages OpenAI Realtime API voice sessions with WebRTC.\n * Provides audio level streaming, transcript events, and tool call tracking.\n *\n * @example Basic usage\n * ```tsx\n * const {\n * isActive,\n * startSession,\n * stopSession,\n * toggleMute\n * } = useVoiceMode({\n * tokenEndpoint: '/api/realtime/session'\n * })\n * ```\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport {\n\tTOOL_CALL_DISPLAY_DURATION_MS,\n\tTOOL_CALL_ERROR_DISPLAY_DURATION_MS,\n} from '../lib/constants'\nimport {\n\textractErrorMessage,\n\tisAssistantTranscriptEventData,\n\tisAudioLevelData,\n\tisErrorEventData,\n\tisSessionStateEventData,\n\tisToolCallCompletedEventData,\n\tisToolCallStartedEventData,\n\tisUserTranscriptEventData,\n\tOpenAIRealtimeService,\n} from '../services/realtime'\n\nimport type {\n\tAudioLevelData,\n\tRealtimeConfig,\n\tRegisteredTool,\n\tToolCallData,\n\tToolExecutor,\n\tTranscriptData,\n\tVoiceModeState,\n} from '../services/realtime'\n\nexport interface UseVoiceModeOptions {\n\t/** Endpoint to get ephemeral tokens from */\n\ttokenEndpoint: string\n\t/** Tools available for the voice session */\n\ttools?: RegisteredTool[]\n\t/** Tool executor function */\n\ttoolExecutor?: ToolExecutor\n\t/** Callback when session connects */\n\tonConnect?: () => void\n\t/** Callback when session disconnects */\n\tonDisconnect?: (durationSeconds: number) => void\n\t/** Callback when error occurs */\n\tonError?: (error: string) => void\n\t/** Callback when user transcript is complete */\n\tonUserTranscript?: (text: string) => void\n\t/** Callback when assistant transcript is complete */\n\tonAssistantTranscript?: (text: string) => void\n}\n\nexport interface UseVoiceModeReturn extends VoiceModeState {\n\t/** Start voice session */\n\tstartSession: (config?: RealtimeConfig) => Promise<void>\n\t/** Stop voice session */\n\tstopSession: () => void\n\t/** Toggle microphone mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send text message while in voice mode */\n\tsendMessage: (text: string) => void\n\t/** Pause audio playback (for approval flow) */\n\tpauseAudio: () => void\n\t/** Resume audio playback (after approval flow) */\n\tresumeAudio: () => void\n}\n\nexport function useVoiceMode(options: UseVoiceModeOptions): UseVoiceModeReturn {\n\tconst {\n\t\ttokenEndpoint,\n\t\ttools,\n\t\ttoolExecutor,\n\t\tonConnect,\n\t\tonDisconnect,\n\t\tonError,\n\t\tonUserTranscript,\n\t\tonAssistantTranscript,\n\t} = options\n\n\t// State\n\tconst [isActive, setIsActive] = useState(false)\n\tconst [isConnecting, setIsConnecting] = useState(false)\n\tconst [isMuted, setIsMuted] = useState(false)\n\tconst [isError, setIsError] = useState(false)\n\tconst [connectionState, setConnectionState] = useState('disconnected')\n\tconst [audioLevel, setAudioLevel] = useState<AudioLevelData | undefined>()\n\tconst [transcript, setTranscript] = useState<TranscriptData | undefined>()\n\tconst [toolCall, setToolCall] = useState<ToolCallData | undefined>()\n\tconst [error, setError] = useState<string | undefined>()\n\n\t// Service ref\n\tconst serviceRef = useRef<OpenAIRealtimeService | null>(null)\n\n\t// Callbacks refs to avoid stale closures\n\tconst onConnectRef = useRef(onConnect)\n\tconst onDisconnectRef = useRef(onDisconnect)\n\tconst onErrorRef = useRef(onError)\n\tconst onUserTranscriptRef = useRef(onUserTranscript)\n\tconst onAssistantTranscriptRef = useRef(onAssistantTranscript)\n\n\tuseEffect(() => {\n\t\tonConnectRef.current = onConnect\n\t\tonDisconnectRef.current = onDisconnect\n\t\tonErrorRef.current = onError\n\t\tonUserTranscriptRef.current = onUserTranscript\n\t\tonAssistantTranscriptRef.current = onAssistantTranscript\n\t}, [onConnect, onDisconnect, onError, onUserTranscript, onAssistantTranscript])\n\n\t// Get or create service instance\n\tconst getService = useCallback(() => {\n\t\tif (!serviceRef.current) {\n\t\t\tserviceRef.current = new OpenAIRealtimeService(tokenEndpoint)\n\t\t}\n\t\treturn serviceRef.current\n\t}, [tokenEndpoint])\n\n\t// Update tools when they change\n\tuseEffect(() => {\n\t\tif (tools) {\n\t\t\tconst service = getService()\n\t\t\tservice.setTools(tools)\n\t\t}\n\t}, [tools, getService])\n\n\t// Update tool executor when it changes\n\tuseEffect(() => {\n\t\tif (toolExecutor) {\n\t\t\tconst service = getService()\n\t\t\tservice.setToolExecutor(toolExecutor)\n\t\t}\n\t}, [toolExecutor, getService])\n\n\t// Set up event listeners\n\tuseEffect(() => {\n\t\tconst service = getService()\n\n\t\t// Session state handler - uses type guard for safe access\n\t\tconst handleSessionState = (data: unknown) => {\n\t\t\tif (!isSessionStateEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid session state event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tsetConnectionState(data.state)\n\t\t\tsetIsActive(data.isActive)\n\t\t\tsetIsMuted(data.isMuted)\n\t\t\tsetIsConnecting(data.state === 'connecting')\n\t\t\tsetIsError(data.state === 'error')\n\n\t\t\tif (data.state === 'connected') {\n\t\t\t\tonConnectRef.current?.()\n\t\t\t} else if (data.state === 'disconnected') {\n\t\t\t\tonDisconnectRef.current?.(data.durationSeconds ?? 0)\n\t\t\t}\n\t\t}\n\n\t\t// Audio level handler - uses type guard for safe access\n\t\tconst handleAudioLevel = (data: unknown) => {\n\t\t\tif (isAudioLevelData(data)) {\n\t\t\t\tsetAudioLevel(data)\n\t\t\t}\n\t\t}\n\n\t\t// User transcript handler - uses type guard for safe access\n\t\tconst handleUserTranscript = (data: unknown) => {\n\t\t\tif (!isUserTranscriptEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid user transcript event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetTranscript({ type: 'user', text: data.text, isDone: true })\n\t\t\tonUserTranscriptRef.current?.(data.text)\n\t\t}\n\n\t\t// Assistant transcript handler (streaming) - uses type guard for safe access\n\t\tconst handleAssistantTranscript = (data: unknown) => {\n\t\t\tif (!isAssistantTranscriptEventData(data)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst text = data.delta || data.transcript || ''\n\t\t\tsetTranscript((prev) => ({\n\t\t\t\ttype: 'assistant',\n\t\t\t\ttext: prev?.type === 'assistant' ? prev.text + text : text,\n\t\t\t\tisDone: false,\n\t\t\t}))\n\t\t}\n\n\t\t// Assistant transcript done handler - uses type guard for safe access\n\t\tconst handleAssistantTranscriptDone = (data: unknown) => {\n\t\t\tif (!isAssistantTranscriptEventData(data)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst text = data.transcript || ''\n\t\t\tsetTranscript({ type: 'assistant', text, isDone: true })\n\t\t\tonAssistantTranscriptRef.current?.(text)\n\t\t}\n\n\t\t// Tool call started handler - uses type guard for safe access\n\t\tconst handleToolCallStarted = (data: unknown) => {\n\t\t\tif (!isToolCallStartedEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid tool call started event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetToolCall({ status: 'started', toolName: data.name })\n\t\t}\n\n\t\t// Tool call completed handler - uses type guard for safe access\n\t\tconst handleToolCallCompleted = (data: unknown) => {\n\t\t\tif (!isToolCallCompletedEventData(data)) {\n\t\t\t\tconsole.warn('[useVoiceMode] Invalid tool call completed event data:', data)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tsetToolCall({ status: 'completed', toolName: data.name, error: data.error })\n\n\t\t\t// Clear tool call after a delay (longer for errors)\n\t\t\tsetTimeout(\n\t\t\t\t() => {\n\t\t\t\t\tsetToolCall(undefined)\n\t\t\t\t},\n\t\t\t\tdata.error ? TOOL_CALL_ERROR_DISPLAY_DURATION_MS : TOOL_CALL_DISPLAY_DURATION_MS\n\t\t\t)\n\t\t}\n\n\t\t// Error handler - uses type guard for safe access\n\t\tconst handleError = (data: unknown) => {\n\t\t\tif (!isErrorEventData(data)) {\n\t\t\t\tsetError('Unknown error')\n\t\t\t\tsetIsError(true)\n\t\t\t\tonErrorRef.current?.('Unknown error')\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Use extractErrorMessage to handle both string and nested object errors\n\t\t\tconst errorMsg = extractErrorMessage(data)\n\t\t\tsetError(errorMsg)\n\t\t\tsetIsError(true)\n\t\t\tonErrorRef.current?.(errorMsg)\n\t\t}\n\n\t\t// Register listeners\n\t\tservice.on('session_state', handleSessionState)\n\t\tservice.on('audio_level', handleAudioLevel)\n\t\tservice.on('user_transcript_done', handleUserTranscript)\n\t\tservice.on('assistant_transcript', handleAssistantTranscript)\n\t\tservice.on('assistant_transcript_done', handleAssistantTranscriptDone)\n\t\tservice.on('tool_call_started', handleToolCallStarted)\n\t\tservice.on('tool_call_completed', handleToolCallCompleted)\n\t\tservice.on('error', handleError)\n\n\t\t// Cleanup\n\t\treturn () => {\n\t\t\tservice.off('session_state', handleSessionState)\n\t\t\tservice.off('audio_level', handleAudioLevel)\n\t\t\tservice.off('user_transcript_done', handleUserTranscript)\n\t\t\tservice.off('assistant_transcript', handleAssistantTranscript)\n\t\t\tservice.off('assistant_transcript_done', handleAssistantTranscriptDone)\n\t\t\tservice.off('tool_call_started', handleToolCallStarted)\n\t\t\tservice.off('tool_call_completed', handleToolCallCompleted)\n\t\t\tservice.off('error', handleError)\n\t\t}\n\t}, [getService])\n\n\t// Start session\n\tconst startSession = useCallback(\n\t\tasync (config?: RealtimeConfig) => {\n\t\t\ttry {\n\t\t\t\tsetIsConnecting(true)\n\t\t\t\tsetIsError(false)\n\t\t\t\tsetError(undefined)\n\n\t\t\t\tconst service = getService()\n\t\t\t\tawait service.startSession(config)\n\t\t\t} catch (err) {\n\t\t\t\tsetIsConnecting(false)\n\t\t\t\tsetIsError(true)\n\t\t\t\tconst errorMsg = err instanceof Error ? err.message : 'Failed to start session'\n\t\t\t\tsetError(errorMsg)\n\t\t\t\tonErrorRef.current?.(errorMsg)\n\t\t\t}\n\t\t},\n\t\t[getService]\n\t)\n\n\t// Stop session\n\tconst stopSession = useCallback(() => {\n\t\tconst service = getService()\n\t\tservice.stopSession()\n\t\tsetAudioLevel(undefined)\n\t\tsetTranscript(undefined)\n\t\tsetToolCall(undefined)\n\t}, [getService])\n\n\t// Toggle mute\n\tconst toggleMute = useCallback(\n\t\t(muted?: boolean) => {\n\t\t\tconst service = getService()\n\t\t\tconst newMuted = muted !== undefined ? muted : !isMuted\n\t\t\tservice.toggleMute(newMuted)\n\t\t\tsetIsMuted(newMuted)\n\t\t},\n\t\t[getService, isMuted]\n\t)\n\n\t// Send message\n\tconst sendMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tconst service = getService()\n\t\t\tif (service.isSessionActive()) {\n\t\t\t\tservice.sendUserMessage(text)\n\t\t\t}\n\t\t},\n\t\t[getService]\n\t)\n\n\t// Pause audio (for approval flow)\n\tconst pauseAudio = useCallback(() => {\n\t\tconst service = getService()\n\t\tservice.pauseAudio()\n\t}, [getService])\n\n\t// Resume audio (after approval flow)\n\tconst resumeAudio = useCallback(() => {\n\t\tconst service = getService()\n\t\tservice.resumeAudio()\n\t}, [getService])\n\n\t// Memoize return value\n\treturn useMemo(\n\t\t() => ({\n\t\t\tisActive,\n\t\t\tisConnecting,\n\t\t\tisMuted,\n\t\t\tisError,\n\t\t\tconnectionState,\n\t\t\taudioLevel,\n\t\t\ttranscript,\n\t\t\ttoolCall,\n\t\t\terror,\n\t\t\tstartSession,\n\t\t\tstopSession,\n\t\t\ttoggleMute,\n\t\t\tsendMessage,\n\t\t\tpauseAudio,\n\t\t\tresumeAudio,\n\t\t}),\n\t\t[\n\t\t\tisActive,\n\t\t\tisConnecting,\n\t\t\tisMuted,\n\t\t\tisError,\n\t\t\tconnectionState,\n\t\t\taudioLevel,\n\t\t\ttranscript,\n\t\t\ttoolCall,\n\t\t\terror,\n\t\t\tstartSession,\n\t\t\tstopSession,\n\t\t\ttoggleMute,\n\t\t\tsendMessage,\n\t\t\tpauseAudio,\n\t\t\tresumeAudio,\n\t\t]\n\t)\n}\n","import { createContext, useContext, useMemo } from 'react'\n\nimport { useVoiceMode } from '../hooks/useVoiceMode'\n\nimport type { ReactNode } from 'react'\nimport type { UseVoiceModeReturn } from '../hooks/useVoiceMode'\nimport type { RegisteredTool, ToolExecutor } from '../services/realtime'\n\n/**\n * Voice Mode Provider\n *\n * Provides voice mode state and controls to the component tree.\n */\n\nexport interface VoiceModeContextValue extends UseVoiceModeReturn {\n\tisSupported: boolean\n}\n\nconst VoiceModeContext = createContext<VoiceModeContextValue | null>(null)\n\nexport interface VoiceModeProviderProps {\n\tchildren: ReactNode\n\t/** Backend endpoint for ephemeral tokens */\n\ttokenEndpoint: string\n\t/** Tools available for voice mode */\n\ttools?: RegisteredTool[]\n\t/** Tool executor function */\n\ttoolExecutor?: ToolExecutor\n\t/** Callback when session connects */\n\tonConnect?: () => void\n\t/** Callback when session disconnects */\n\tonDisconnect?: (durationSeconds: number) => void\n\t/** Callback when error occurs */\n\tonError?: (error: string) => void\n\t/** Callback when user transcript is complete */\n\tonUserTranscript?: (text: string) => void\n\t/** Callback when assistant transcript is complete */\n\tonAssistantTranscript?: (text: string) => void\n}\n\n/**\n * Check if the browser supports WebRTC and getUserMedia\n */\nfunction checkVoiceModeSupport(): boolean {\n\treturn !!(\n\t\ttypeof window !== 'undefined' &&\n\t\twindow.RTCPeerConnection &&\n\t\tnavigator.mediaDevices?.getUserMedia\n\t)\n}\n\nexport function VoiceModeProvider({\n\tchildren,\n\ttokenEndpoint,\n\ttools,\n\ttoolExecutor,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n\tonUserTranscript,\n\tonAssistantTranscript,\n}: VoiceModeProviderProps) {\n\tconst voiceMode = useVoiceMode({\n\t\ttokenEndpoint,\n\t\ttools,\n\t\ttoolExecutor,\n\t\tonConnect,\n\t\tonDisconnect,\n\t\tonError,\n\t\tonUserTranscript,\n\t\tonAssistantTranscript,\n\t})\n\n\tconst isSupported = useMemo(() => checkVoiceModeSupport(), [])\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\t...voiceMode,\n\t\t\tisSupported,\n\t\t}),\n\t\t[voiceMode, isSupported]\n\t)\n\n\treturn <VoiceModeContext.Provider value={value}>{children}</VoiceModeContext.Provider>\n}\n\n/**\n * Hook to access voice mode context\n */\nexport function useVoiceModeContext(): VoiceModeContextValue {\n\tconst context = useContext(VoiceModeContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceModeContext must be used within a VoiceModeProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access voice mode context (returns null if not in provider)\n */\nexport function useOptionalVoiceModeContext(): VoiceModeContextValue | null {\n\treturn useContext(VoiceModeContext)\n}\n","/**\n * Voice Tool Approval Provider\n *\n * Manages tool approval state for voice mode. When a destructive tool is called\n * during a voice session, this provider pauses execution and waits for the user\n * to approve or deny (via voice keywords or button tap).\n *\n * Key features:\n * - 30-second timeout with auto-deny (safe default)\n * - Support for both voice keyword detection and button tap\n * - Single pending approval at a time (voice mode is sequential)\n *\n * @example\n * ```tsx\n * <VoiceToolApprovalProvider>\n * <VoiceMode />\n * </VoiceToolApprovalProvider>\n *\n * // In a component:\n * const { pendingApproval, approve, deny, requestApproval } = useVoiceToolApproval()\n * ```\n */\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS, VOICE_APPROVAL_TIMEOUT_MS } from '../lib/constants'\n\nimport type { FC, ReactNode } from 'react'\n\n/**\n * Pending approval request\n */\nexport interface VoicePendingApproval {\n\t/** Unique call ID from OpenAI Realtime */\n\tcallId: string\n\t/** Name of the tool being requested */\n\ttoolName: string\n\t/** Arguments passed to the tool */\n\targs: Record<string, unknown>\n\t/** Timestamp when approval was requested */\n\ttimestamp: number\n}\n\n/**\n * Voice Tool Approval Context Value\n */\nexport interface VoiceToolApprovalContextValue {\n\t/** Current pending approval (null if none) */\n\tpendingApproval: VoicePendingApproval | null\n\t/** Approve the current pending tool call */\n\tapprove: () => void\n\t/** Deny the current pending tool call */\n\tdeny: () => void\n\t/** Seconds remaining before auto-deny */\n\ttimeoutRemaining: number\n\t/** Whether we're currently waiting for approval */\n\tisWaitingForApproval: boolean\n\t/**\n\t * Request approval for a tool call.\n\t * Returns a Promise that resolves to true (approved) or false (denied/timeout).\n\t */\n\trequestApproval: (\n\t\tcallId: string,\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>\n\t) => Promise<boolean>\n\t/** Clear any pending approval without resolving (e.g., when voice session ends) */\n\tclearPendingApproval: () => void\n}\n\nconst VoiceToolApprovalContext = createContext<VoiceToolApprovalContextValue | null>(null)\n\nexport interface VoiceToolApprovalProviderProps {\n\tchildren: ReactNode\n\t/** Custom timeout in milliseconds (defaults to VOICE_APPROVAL_TIMEOUT_MS) */\n\ttimeout?: number\n\t/** Callback when approval times out */\n\tonTimeout?: (toolName: string) => void\n\t/** Callback when user approves */\n\tonApprove?: (toolName: string) => void\n\t/** Callback when user denies */\n\tonDeny?: (toolName: string) => void\n}\n\n/**\n * Provider for voice mode tool approval.\n *\n * Wraps voice mode components to enable approval workflow for destructive tools.\n */\nexport const VoiceToolApprovalProvider: FC<VoiceToolApprovalProviderProps> = ({\n\tchildren,\n\ttimeout = VOICE_APPROVAL_TIMEOUT_MS,\n\tonTimeout,\n\tonApprove,\n\tonDeny,\n}) => {\n\t// Current pending approval\n\tconst [pendingApproval, setPendingApproval] = useState<VoicePendingApproval | null>(null)\n\n\t// Time remaining for countdown\n\tconst [timeoutRemaining, setTimeoutRemaining] = useState(0)\n\n\t// Refs for the resolve function and timeout\n\tconst resolveRef = useRef<((approved: boolean) => void) | null>(null)\n\tconst timeoutIdRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\tconst countdownIdRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n\t// Callback refs to avoid stale closures\n\tconst onTimeoutRef = useRef(onTimeout)\n\tconst onApproveRef = useRef(onApprove)\n\tconst onDenyRef = useRef(onDeny)\n\tonTimeoutRef.current = onTimeout\n\tonApproveRef.current = onApprove\n\tonDenyRef.current = onDeny\n\n\t/**\n\t * Clear all timers\n\t */\n\tconst clearTimers = useCallback(() => {\n\t\tif (timeoutIdRef.current) {\n\t\t\tclearTimeout(timeoutIdRef.current)\n\t\t\ttimeoutIdRef.current = null\n\t\t}\n\t\tif (countdownIdRef.current) {\n\t\t\tclearInterval(countdownIdRef.current)\n\t\t\tcountdownIdRef.current = null\n\t\t}\n\t}, [])\n\n\t/**\n\t * Resolve the pending approval and clean up\n\t */\n\tconst resolveApproval = useCallback(\n\t\t(approved: boolean, reason: 'approve' | 'deny' | 'timeout' = approved ? 'approve' : 'deny') => {\n\t\t\tconst toolName = pendingApproval?.toolName\n\n\t\t\t// Resolve the promise\n\t\t\tif (resolveRef.current) {\n\t\t\t\tresolveRef.current(approved)\n\t\t\t\tresolveRef.current = null\n\t\t\t}\n\n\t\t\t// Clear state\n\t\t\tclearTimers()\n\t\t\tsetPendingApproval(null)\n\t\t\tsetTimeoutRemaining(0)\n\n\t\t\t// Fire callbacks\n\t\t\tif (toolName) {\n\t\t\t\tif (reason === 'timeout') {\n\t\t\t\t\tonTimeoutRef.current?.(toolName)\n\t\t\t\t} else if (reason === 'approve') {\n\t\t\t\t\tonApproveRef.current?.(toolName)\n\t\t\t\t} else {\n\t\t\t\t\tonDenyRef.current?.(toolName)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[pendingApproval?.toolName, clearTimers]\n\t)\n\n\t/**\n\t * Approve the current pending tool call\n\t */\n\tconst approve = useCallback(() => {\n\t\tif (pendingApproval) {\n\t\t\tresolveApproval(true, 'approve')\n\t\t}\n\t}, [pendingApproval, resolveApproval])\n\n\t/**\n\t * Deny the current pending tool call\n\t */\n\tconst deny = useCallback(() => {\n\t\tif (pendingApproval) {\n\t\t\tresolveApproval(false, 'deny')\n\t\t}\n\t}, [pendingApproval, resolveApproval])\n\n\t/**\n\t * Clear pending approval without resolving (for cleanup)\n\t */\n\tconst clearPendingApproval = useCallback(() => {\n\t\tif (resolveRef.current) {\n\t\t\tresolveRef.current(false)\n\t\t\tresolveRef.current = null\n\t\t}\n\t\tclearTimers()\n\t\tsetPendingApproval(null)\n\t\tsetTimeoutRemaining(0)\n\t}, [clearTimers])\n\n\t/**\n\t * Request approval for a tool call.\n\t * Returns a Promise that resolves when the user approves/denies or timeout occurs.\n\t */\n\tconst requestApproval = useCallback(\n\t\t(callId: string, toolName: string, args: Record<string, unknown>): Promise<boolean> => {\n\t\t\treturn new Promise((resolve) => {\n\t\t\t\t// If there's already a pending approval, deny it first\n\t\t\t\tif (resolveRef.current) {\n\t\t\t\t\tresolveRef.current(false)\n\t\t\t\t}\n\t\t\t\tclearTimers()\n\n\t\t\t\t// Store the resolve function\n\t\t\t\tresolveRef.current = resolve\n\n\t\t\t\t// Set pending approval state\n\t\t\t\tsetPendingApproval({\n\t\t\t\t\tcallId,\n\t\t\t\t\ttoolName,\n\t\t\t\t\targs,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t})\n\n\t\t\t\t// Set initial timeout remaining\n\t\t\t\tconst timeoutSeconds = Math.ceil(timeout / 1000)\n\t\t\t\tsetTimeoutRemaining(timeoutSeconds)\n\n\t\t\t\t// Start countdown interval\n\t\t\t\tcountdownIdRef.current = setInterval(() => {\n\t\t\t\t\tsetTimeoutRemaining((prev) => {\n\t\t\t\t\t\tif (prev <= 1) {\n\t\t\t\t\t\t\treturn 0\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn prev - 1\n\t\t\t\t\t})\n\t\t\t\t}, VOICE_APPROVAL_COUNTDOWN_INTERVAL_MS)\n\n\t\t\t\t// Set auto-deny timeout\n\t\t\t\ttimeoutIdRef.current = setTimeout(() => {\n\t\t\t\t\t// Auto-deny on timeout\n\t\t\t\t\tif (resolveRef.current) {\n\t\t\t\t\t\tresolveRef.current(false)\n\t\t\t\t\t\tresolveRef.current = null\n\t\t\t\t\t}\n\t\t\t\t\tclearTimers()\n\t\t\t\t\tsetPendingApproval(null)\n\t\t\t\t\tsetTimeoutRemaining(0)\n\t\t\t\t\tonTimeoutRef.current?.(toolName)\n\t\t\t\t}, timeout)\n\t\t\t})\n\t\t},\n\t\t[timeout, clearTimers]\n\t)\n\n\t// Cleanup on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tclearTimers()\n\t\t\tif (resolveRef.current) {\n\t\t\t\tresolveRef.current(false)\n\t\t\t\tresolveRef.current = null\n\t\t\t}\n\t\t}\n\t}, [clearTimers])\n\n\tconst value = useMemo<VoiceToolApprovalContextValue>(\n\t\t() => ({\n\t\t\tpendingApproval,\n\t\t\tapprove,\n\t\t\tdeny,\n\t\t\ttimeoutRemaining,\n\t\t\tisWaitingForApproval: pendingApproval !== null,\n\t\t\trequestApproval,\n\t\t\tclearPendingApproval,\n\t\t}),\n\t\t[pendingApproval, approve, deny, timeoutRemaining, requestApproval, clearPendingApproval]\n\t)\n\n\treturn (\n\t\t<VoiceToolApprovalContext.Provider value={value}>{children}</VoiceToolApprovalContext.Provider>\n\t)\n}\n\n/**\n * Hook to access voice tool approval context.\n * @throws Error if used outside VoiceToolApprovalProvider\n */\nexport function useVoiceToolApproval(): VoiceToolApprovalContextValue {\n\tconst context = useContext(VoiceToolApprovalContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceToolApproval must be used within a VoiceToolApprovalProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access voice tool approval context.\n * Returns null if not within provider.\n */\nexport function useOptionalVoiceToolApproval(): VoiceToolApprovalContextValue | null {\n\treturn useContext(VoiceToolApprovalContext)\n}\n","/**\n * VoiceThreadBridge\n *\n * Bridges voice mode events to the assistant-ui thread.\n * When voice transcripts and tool calls occur, they are pushed into the thread\n * as real messages, making assistant-ui the single source of truth.\n *\n * This replaces the separate voice state tracking (useVoiceActions, useVoiceSummary)\n * with unified thread state.\n *\n * Voice messages are tagged with metadata to distinguish them from text messages:\n * - metadata.source: 'voice'\n * - metadata.voiceSessionId: unique session identifier\n *\n * Tool calls from voice mode are also added to the thread with full metadata\n * (timing, source attribution) matching the text mode behavior.\n */\n\nimport { useThreadRuntime } from '@assistant-ui/react'\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { VOICE_TOOL_RESULT_MESSAGES } from '../lib/constants'\nimport { TOOL_DENIED_MESSAGE } from '../lib/format'\nimport { resolveAllPendingToolCalls, resolveAllPendingToolCallsByName } from '../lib/thread-utils'\nimport { useOptionalMCPTools } from './MCPToolsProvider'\nimport { useOptionalToolApproval } from './ToolApprovalProvider'\nimport { useOptionalVoiceModeContext, VoiceModeProvider } from './VoiceModeProvider'\nimport {\n\tuseOptionalVoiceToolApproval,\n\tVoiceToolApprovalProvider,\n} from './VoiceToolApprovalProvider'\n\nimport type { ToolCallMetadata, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { FC, MutableRefObject, ReactNode } from 'react'\nimport type { RegisteredTool, ToolExecutor } from '../services/realtime'\n\n/**\n * Data needed to add a voice tool call to the thread\n */\ninterface VoiceToolCallData {\n\ttoolCallId: string\n\ttoolName: string\n\targs: Record<string, unknown>\n\tresult: string\n\tisError: boolean\n\tartifact: ToolCallMetadata\n}\n\n/**\n * Callback type for adding tool calls to thread\n */\ntype AddToolCallToThread = (data: VoiceToolCallData) => void\n\n/**\n * Voice session metadata attached to messages\n */\nexport interface VoiceMessageMetadata {\n\tsource: 'voice'\n\tvoiceSessionId: string\n\ttimestamp: number\n}\n\n/**\n * Voice thread context - provides voice controls and current session info\n */\nexport interface VoiceThreadContextValue {\n\t/** Whether a voice session is active */\n\tisActive: boolean\n\t/** Whether voice is connecting */\n\tisConnecting: boolean\n\t/** Whether there's a voice error */\n\tisError: boolean\n\t/** Whether microphone is muted */\n\tisMuted: boolean\n\t/** Whether voice mode is supported in this browser */\n\tisSupported: boolean\n\t/** Current error message */\n\terror?: string\n\t/** Current voice session ID (null if no active session) */\n\tsessionId: string | null\n\t/** Start a voice session */\n\tstart: () => Promise<void>\n\t/** Stop the voice session */\n\tstop: () => void\n\t/** Toggle microphone mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send a text message in voice mode */\n\tsendMessage: (text: string) => void\n\t/** Pause audio playback (for approval flow) */\n\tpauseAudio: () => void\n\t/** Resume audio playback (after approval flow) */\n\tresumeAudio: () => void\n\t/** Audio level data for visualization */\n\taudioLevel?: {\n\t\tmicLevel: number\n\t\tspeakerLevel: number\n\t}\n\t/** Current transcript being spoken */\n\ttranscript?: {\n\t\ttype: 'user' | 'assistant'\n\t\ttext: string\n\t\tisDone: boolean\n\t}\n\t/** Current tool call being executed */\n\ttoolCall?: {\n\t\tstatus: 'started' | 'completed'\n\t\ttoolName: string\n\t\terror?: string\n\t}\n}\n\nconst VoiceThreadContext = createContext<VoiceThreadContextValue | null>(null)\n\n/**\n * Generate a unique session ID\n */\nfunction generateSessionId(): string {\n\treturn `voice-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n/**\n * Convert MCP tools to the format expected by the voice service\n */\nfunction convertToRegisteredTool(tool: ToolWithSource): RegisteredTool {\n\treturn {\n\t\tname: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tinputSchema: (tool.inputSchema ?? { type: 'object', properties: {} }) as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>,\n\t}\n}\n\nexport interface VoiceThreadBridgeProps {\n\tchildren: ReactNode\n\t/** Token endpoint for voice sessions */\n\ttokenEndpoint: string\n\t/** Callback when voice session connects */\n\tonConnect?: () => void\n\t/** Callback when voice session disconnects */\n\tonDisconnect?: (durationSeconds: number) => void\n\t/** Callback when voice error occurs */\n\tonError?: (error: string) => void\n}\n\n/**\n * Internal component that bridges voice events to the thread.\n * Must be used inside both VoiceModeProvider and AssistantRuntimeProvider.\n */\nconst VoiceThreadIntegrator: FC<{\n\tchildren: ReactNode\n\tsessionId: string | null\n\tsetSessionId: (id: string | null) => void\n\taddToolCallRef: MutableRefObject<AddToolCallToThread | null>\n\tonConnect?: () => void\n\tonDisconnect?: (durationSeconds: number) => void\n\tonError?: (error: string) => void\n}> = ({ children, sessionId, setSessionId, addToolCallRef, onConnect, onDisconnect, onError }) => {\n\tconst threadRuntime = useThreadRuntime()\n\tconst voiceMode = useOptionalVoiceModeContext()\n\n\t// Track last transcript to detect changes\n\tconst lastUserTranscriptRef = useRef<string>('')\n\tconst lastAssistantTranscriptRef = useRef<string>('')\n\tconst wasActiveRef = useRef(false)\n\n\t// Refs for callbacks\n\tconst onConnectRef = useRef(onConnect)\n\tconst onDisconnectRef = useRef(onDisconnect)\n\tconst onErrorRef = useRef(onError)\n\tonConnectRef.current = onConnect\n\tonDisconnectRef.current = onDisconnect\n\tonErrorRef.current = onError\n\n\t/**\n\t * Set up the callback for adding tool calls to thread.\n\t * This is called by toolExecutor when a voice tool call completes.\n\t */\n\tuseEffect(() => {\n\t\taddToolCallRef.current = (data: VoiceToolCallData) => {\n\t\t\tif (!sessionId) {\n\t\t\t\tconsole.warn('[VoiceThreadIntegrator] Cannot add tool call - no active session')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Append complete tool-call message to thread\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tthreadRuntime.append({\n\t\t\t\trole: 'assistant',\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'tool-call',\n\t\t\t\t\t\ttoolCallId: data.toolCallId,\n\t\t\t\t\t\ttoolName: data.toolName,\n\t\t\t\t\t\targs: data.args,\n\t\t\t\t\t\targsText: JSON.stringify(data.args),\n\t\t\t\t\t\tresult: data.result,\n\t\t\t\t\t\tisError: data.isError,\n\t\t\t\t\t\tartifact: data.artifact,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tmetadata: {\n\t\t\t\t\tcustom: {\n\t\t\t\t\t\tsource: 'voice',\n\t\t\t\t\t\tvoiceSessionId: sessionId,\n\t\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t} as any)\n\t\t}\n\n\t\treturn () => {\n\t\t\taddToolCallRef.current = null\n\t\t}\n\t}, [threadRuntime, sessionId, addToolCallRef])\n\n\t/**\n\t * Add a user message to the thread (from voice transcript)\n\t */\n\tconst addUserMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (!sessionId || !text.trim()) return\n\n\t\t\t// Use custom metadata for voice messages\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst metadata: any = {\n\t\t\t\tcustom: {\n\t\t\t\t\tsource: 'voice',\n\t\t\t\t\tvoiceSessionId: sessionId,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthreadRuntime.append({\n\t\t\t\trole: 'user',\n\t\t\t\tcontent: [{ type: 'text', text }],\n\t\t\t\tmetadata,\n\t\t\t})\n\t\t},\n\t\t[threadRuntime, sessionId]\n\t)\n\n\t/**\n\t * Add an assistant message to the thread (from voice transcript)\n\t */\n\tconst addAssistantMessage = useCallback(\n\t\t(text: string) => {\n\t\t\tif (!sessionId || !text.trim()) return\n\n\t\t\t// Use custom metadata for voice messages\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst metadata: any = {\n\t\t\t\tcustom: {\n\t\t\t\t\tsource: 'voice',\n\t\t\t\t\tvoiceSessionId: sessionId,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthreadRuntime.append({\n\t\t\t\trole: 'assistant',\n\t\t\t\tcontent: [{ type: 'text', text }],\n\t\t\t\tmetadata,\n\t\t\t})\n\t\t},\n\t\t[threadRuntime, sessionId]\n\t)\n\n\t// Track session state changes\n\tuseEffect(() => {\n\t\tif (!voiceMode) return\n\n\t\tconst isActive = voiceMode.isActive || voiceMode.isConnecting\n\n\t\t// Session just started\n\t\tif (!wasActiveRef.current && isActive && !sessionId) {\n\t\t\tconst newSessionId = generateSessionId()\n\t\t\tsetSessionId(newSessionId)\n\t\t}\n\n\t\t// Session just connected\n\t\tif (!wasActiveRef.current && voiceMode.isActive) {\n\t\t\tonConnectRef.current?.()\n\t\t}\n\n\t\t// Session just ended\n\t\tif (wasActiveRef.current && !isActive) {\n\t\t\t// Add final assistant message if we have one\n\t\t\t// CRITICAL: Clear refs immediately after use to prevent race condition with transcript effect\n\t\t\t// Both effects can fire in the same render cycle, causing duplicate message IDs\n\t\t\tif (lastAssistantTranscriptRef.current) {\n\t\t\t\taddAssistantMessage(lastAssistantTranscriptRef.current)\n\t\t\t\tlastAssistantTranscriptRef.current = ''\n\t\t\t}\n\t\t\tlastUserTranscriptRef.current = ''\n\n\t\t\t// Clear any remaining pending thread elicitations to prevent duplicate approval UI\n\t\t\tresolveAllPendingToolCalls(threadRuntime, VOICE_TOOL_RESULT_MESSAGES.sessionEnded)\n\n\t\t\t// Clear session\n\t\t\tsetSessionId(null)\n\n\t\t\t// Notify disconnect (duration is not easily available here, use 0)\n\t\t\tonDisconnectRef.current?.(0)\n\t\t}\n\n\t\twasActiveRef.current = isActive\n\t}, [\n\t\tvoiceMode?.isActive,\n\t\tvoiceMode?.isConnecting,\n\t\tsessionId,\n\t\tsetSessionId,\n\t\taddAssistantMessage,\n\t\tthreadRuntime,\n\t])\n\n\t// Track transcript changes and push to thread\n\tuseEffect(() => {\n\t\tif (!voiceMode?.transcript || !sessionId) return\n\n\t\tconst { type, text, isDone } = voiceMode.transcript\n\n\t\tif (type === 'user' && isDone && text !== lastUserTranscriptRef.current) {\n\t\t\t// If we had a pending assistant message, add it first to maintain order\n\t\t\tif (lastAssistantTranscriptRef.current) {\n\t\t\t\taddAssistantMessage(lastAssistantTranscriptRef.current)\n\t\t\t\tlastAssistantTranscriptRef.current = ''\n\t\t\t}\n\n\t\t\t// User finished speaking - add to thread\n\t\t\taddUserMessage(text)\n\t\t\tlastUserTranscriptRef.current = text\n\t\t} else if (type === 'assistant' && isDone && text !== lastAssistantTranscriptRef.current) {\n\t\t\t// Store assistant transcript - we'll add it to thread when:\n\t\t\t// 1. User speaks next (to maintain conversation order)\n\t\t\t// 2. Session ends\n\t\t\tlastAssistantTranscriptRef.current = text\n\t\t}\n\t}, [voiceMode?.transcript, sessionId, addUserMessage, addAssistantMessage])\n\n\t// Track errors\n\tuseEffect(() => {\n\t\tif (voiceMode?.isError && voiceMode?.error) {\n\t\t\tonErrorRef.current?.(voiceMode.error)\n\t\t}\n\t}, [voiceMode?.isError, voiceMode?.error])\n\n\treturn <>{children}</>\n}\n\n/**\n * Inner component that creates the approval-aware tool executor.\n * Must be inside VoiceToolApprovalProvider to access the approval context.\n */\nconst ApprovalAwareVoiceBridge: FC<{\n\tchildren: ReactNode\n\ttokenEndpoint: string\n\tvoiceTools: RegisteredTool[]\n\tsessionId: string | null\n\tsetSessionId: (id: string | null) => void\n\taddToolCallRef: MutableRefObject<AddToolCallToThread | null>\n\tonConnect?: () => void\n\tonDisconnect?: (durationSeconds: number) => void\n\tonError?: (error: string) => void\n}> = ({\n\tchildren,\n\ttokenEndpoint,\n\tvoiceTools,\n\tsessionId,\n\tsetSessionId,\n\taddToolCallRef,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst mcpTools = useOptionalMCPTools()\n\tconst toolApproval = useOptionalToolApproval()\n\tconst voiceToolApproval = useOptionalVoiceToolApproval()\n\tconst threadRuntime = useThreadRuntime()\n\n\t// Tool executor that routes to MCP with approval checking\n\tconst toolExecutor: ToolExecutor = useCallback(\n\t\tasync (name: string, args: Record<string, unknown>) => {\n\t\t\tif (!mcpTools?.callTool) {\n\t\t\t\tthrow new Error('MCP tools not available')\n\t\t\t}\n\n\t\t\t// Check if tool requires approval\n\t\t\tconst tool = mcpTools.tools.find((t) => t.name === name)\n\t\t\tconst needsApproval = tool && toolApproval?.requiresApproval(tool)\n\n\t\t\tif (needsApproval && voiceToolApproval) {\n\t\t\t\t// Generate a call ID for this approval request\n\t\t\t\tconst callId = `voice-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n\n\t\t\t\t// Request approval and wait for response\n\t\t\t\tconst approved = await voiceToolApproval.requestApproval(callId, name, args)\n\n\t\t\t\t// Sync voice approval to thread to prevent duplicate approval UI in text mode\n\t\t\t\tconst resultMessage = approved ? VOICE_TOOL_RESULT_MESSAGES.handled : TOOL_DENIED_MESSAGE\n\t\t\t\tresolveAllPendingToolCallsByName(threadRuntime, name, resultMessage)\n\n\t\t\t\tif (!approved) {\n\t\t\t\t\t// User denied or timeout - return denial message\n\t\t\t\t\treturn TOOL_DENIED_MESSAGE\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Execute the tool\n\t\t\tconst result = await mcpTools.callTool(name, args)\n\n\t\t\t// Extract text content from MCP result\n\t\t\tconst textContent = result.content?.find(\n\t\t\t\t(c: { type: string; text?: string }): c is { type: 'text'; text: string } =>\n\t\t\t\t\tc.type === 'text'\n\t\t\t)\n\t\t\treturn textContent?.text ?? JSON.stringify(result)\n\t\t},\n\t\t[mcpTools, toolApproval, voiceToolApproval, threadRuntime]\n\t)\n\n\treturn (\n\t\t<VoiceModeProvider tokenEndpoint={tokenEndpoint} tools={voiceTools} toolExecutor={toolExecutor}>\n\t\t\t<VoiceThreadIntegrator\n\t\t\t\tsessionId={sessionId}\n\t\t\t\tsetSessionId={setSessionId}\n\t\t\t\taddToolCallRef={addToolCallRef}\n\t\t\t\tonConnect={onConnect}\n\t\t\t\tonDisconnect={onDisconnect}\n\t\t\t\tonError={onError}\n\t\t\t>\n\t\t\t\t<VoiceThreadContextProvider sessionId={sessionId}>{children}</VoiceThreadContextProvider>\n\t\t\t</VoiceThreadIntegrator>\n\t\t</VoiceModeProvider>\n\t)\n}\n\n/**\n * Bridge component that integrates voice mode with the assistant-ui thread.\n *\n * When voice events occur:\n * 1. User transcripts are added as user messages to the thread\n * 2. Assistant transcripts are added as assistant messages\n * 3. Tool calls are added as tool-call parts with full metadata (timing, source)\n * This ensures the thread is the single source of truth for all conversation history,\n * including tool calls from voice mode with the same metadata as text mode.\n *\n * Voice tool approval:\n * When a destructive tool is called during voice mode, the VoiceToolApprovalProvider\n * pauses execution and shows an approval UI. User can approve via voice keywords\n * (\"approve\", \"yes\") or by tapping buttons.\n */\nexport const VoiceThreadBridge: FC<VoiceThreadBridgeProps> = ({\n\tchildren,\n\ttokenEndpoint,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst mcpTools = useOptionalMCPTools()\n\n\t// Session ID managed at this level so it persists across voice mode restarts\n\tconst [sessionId, setSessionId] = useState<string | null>(null)\n\n\t// Ref for adding tool calls to thread (set by VoiceThreadIntegrator)\n\tconst addToolCallRef = useRef<AddToolCallToThread | null>(null)\n\n\t// Convert MCP tools for voice mode\n\tconst voiceTools = useMemo<RegisteredTool[]>(() => {\n\t\tif (!mcpTools?.tools) return []\n\t\treturn mcpTools.tools.map(convertToRegisteredTool)\n\t}, [mcpTools?.tools])\n\n\treturn (\n\t\t<VoiceToolApprovalProvider>\n\t\t\t<ApprovalAwareVoiceBridge\n\t\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\t\tvoiceTools={voiceTools}\n\t\t\t\tsessionId={sessionId}\n\t\t\t\tsetSessionId={setSessionId}\n\t\t\t\taddToolCallRef={addToolCallRef}\n\t\t\t\tonConnect={onConnect}\n\t\t\t\tonDisconnect={onDisconnect}\n\t\t\t\tonError={onError}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</ApprovalAwareVoiceBridge>\n\t\t</VoiceToolApprovalProvider>\n\t)\n}\n\n/**\n * Internal provider that exposes voice thread context\n */\nconst VoiceThreadContextProvider: FC<{ children: ReactNode; sessionId: string | null }> = ({\n\tchildren,\n\tsessionId,\n}) => {\n\tconst voiceMode = useOptionalVoiceModeContext()\n\n\t// Build context value from voice mode\n\tconst contextValue = useMemo<VoiceThreadContextValue | null>(() => {\n\t\tif (!voiceMode) return null\n\n\t\treturn {\n\t\t\tisActive: voiceMode.isActive,\n\t\t\tisConnecting: voiceMode.isConnecting,\n\t\t\tisError: voiceMode.isError,\n\t\t\tisMuted: voiceMode.isMuted,\n\t\t\tisSupported: voiceMode.isSupported,\n\t\t\terror: voiceMode.error,\n\t\t\tsessionId,\n\t\t\taudioLevel: voiceMode.audioLevel\n\t\t\t\t? {\n\t\t\t\t\t\tmicLevel: voiceMode.audioLevel.micLevel,\n\t\t\t\t\t\tspeakerLevel: voiceMode.audioLevel.speakerLevel,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\ttranscript: voiceMode.transcript\n\t\t\t\t? {\n\t\t\t\t\t\ttype: voiceMode.transcript.type,\n\t\t\t\t\t\ttext: voiceMode.transcript.text,\n\t\t\t\t\t\tisDone: voiceMode.transcript.isDone,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\ttoolCall: voiceMode.toolCall\n\t\t\t\t? {\n\t\t\t\t\t\tstatus: voiceMode.toolCall.status,\n\t\t\t\t\t\ttoolName: voiceMode.toolCall.toolName,\n\t\t\t\t\t\terror: voiceMode.toolCall.error,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tstart: voiceMode.startSession,\n\t\t\tstop: voiceMode.stopSession,\n\t\t\ttoggleMute: voiceMode.toggleMute,\n\t\t\tsendMessage: voiceMode.sendMessage,\n\t\t\tpauseAudio: voiceMode.pauseAudio,\n\t\t\tresumeAudio: voiceMode.resumeAudio,\n\t\t}\n\t}, [voiceMode, sessionId])\n\n\tif (!contextValue) {\n\t\treturn <>{children}</>\n\t}\n\n\treturn <VoiceThreadContext.Provider value={contextValue}>{children}</VoiceThreadContext.Provider>\n}\n\n/**\n * Hook to access voice thread controls\n * @throws Error if used outside VoiceThreadBridge\n */\nexport function useVoiceThread(): VoiceThreadContextValue {\n\tconst context = useContext(VoiceThreadContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceThread must be used within a VoiceThreadBridge')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access voice thread controls\n */\nexport function useOptionalVoiceThread(): VoiceThreadContextValue | null {\n\treturn useContext(VoiceThreadContext)\n}\n\n/**\n * Hook to check if voice mode is available and active\n */\nexport function useIsVoiceActive(): boolean {\n\tconst context = useOptionalVoiceThread()\n\treturn context?.isActive ?? false\n}\n","/**\n * useAgent - Unified Agent Hook\n *\n * The main hook for accessing agent state and capabilities.\n * This is a thin facade over assistant-ui's thread state.\n *\n * Thread state (messages, actions) comes from @assistant-ui/react.\n * Voice transcripts and tool calls are also stored in the thread\n * (via VoiceThreadBridge), making assistant-ui the single source of truth.\n *\n * @example Basic usage\n * ```tsx\n * function MyComponent() {\n * const agent = useAgent()\n *\n * return (\n * <div>\n * {agent.isRunning && <p>Processing...</p>}\n * {agent.messages.map(m => <Message key={m.id} {...m} />)}\n * {agent.voice?.isActive && <p>Voice active</p>}\n * </div>\n * )\n * }\n * ```\n */\n\nimport { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { useLatestSummary } from '../../components/pill/SummaryBlock'\nimport {\n\tuseActions,\n\tuseCurrentAction,\n\tuseLastCompletedAction,\n\tuseRecentActions,\n} from '../../hooks/useActions'\nimport { useOptionalMCPTools } from '../../providers/MCPToolsProvider'\nimport { useOptionalVoiceThread } from '../../providers/VoiceThreadBridge'\n\nimport type { CallToolResult, Prompt, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { Action } from '../../hooks/useActions'\n\n/**\n * Voice mode state and controls\n */\nexport interface AgentVoice {\n\t/** Whether voice session is active */\n\tisActive: boolean\n\t/** Whether voice is connecting */\n\tisConnecting: boolean\n\t/** Whether there's an error */\n\tisError: boolean\n\t/** Whether microphone is muted */\n\tisMuted: boolean\n\t/** Whether voice mode is supported */\n\tisSupported: boolean\n\t/** Current error message */\n\terror?: string\n\t/** Current voice session ID */\n\tsessionId: string | null\n\t/** Audio level for visualization */\n\taudioLevel?: { micLevel: number; speakerLevel: number }\n\t/** Current transcript being spoken */\n\ttranscript?: { type: 'user' | 'assistant'; text: string; isDone: boolean }\n\t/** Start voice session */\n\tstart: () => Promise<void>\n\t/** Stop voice session */\n\tstop: () => void\n\t/** Toggle microphone mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send text message while in voice mode */\n\tsendMessage: (text: string) => void\n}\n\n/**\n * MCP tools state and controls\n */\nexport interface AgentTools {\n\t/** All available tools */\n\tlist: ToolWithSource[]\n\t/** Call a tool by name */\n\tcall: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>\n\t/** Available prompts */\n\tprompts: Prompt[]\n\t/** Get expanded prompt content */\n\tgetPrompt: ((name: string) => Promise<GetPromptResult>) | undefined\n}\n\n/**\n * Thread message type (simplified for external consumers)\n */\nexport interface AgentMessage {\n\tid: string\n\trole: 'user' | 'assistant' | 'system'\n\tcontent: readonly unknown[]\n\tstatus?: { type: string }\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tmetadata?: Record<string, any>\n}\n\n/**\n * Agent state and controls returned by useAgent\n */\nexport interface AgentState {\n\t// Thread state (from assistant-ui - single source of truth)\n\t/** All messages in the thread (includes both text and voice messages) */\n\tmessages: readonly AgentMessage[]\n\t/** Whether the agent is currently processing */\n\tisRunning: boolean\n\t/** Whether thread has any messages */\n\thasMessages: boolean\n\n\t// Actions (derived from thread messages - both text and voice)\n\t/** All actions derived from tool calls in the thread */\n\tactions: Action[]\n\t/** Currently running action (if any) */\n\tcurrentAction: Action | null\n\t/** Recently completed actions */\n\trecentActions: Action[]\n\t/** Last completed action (success or error) */\n\tlastCompletedAction: Action | null\n\n\t// Summary (derived from last assistant message)\n\t/** Summary text from the last assistant message */\n\tsummary: string | null\n\n\t// Voice mode (null if not configured)\n\tvoice: AgentVoice | null\n\n\t// MCP tools (null if not in MCP context)\n\ttools: AgentTools | null\n\n\t// Derived state\n\t/** Whether voice mode is currently active */\n\tisVoiceActive: boolean\n}\n\n/**\n * Main agent hook - provides unified access to all agent capabilities\n *\n * This is a thin facade over assistant-ui. All thread state comes from\n * the assistant-ui runtime, including voice messages (which are pushed\n * into the thread by VoiceThreadBridge).\n */\nexport function useAgent(): AgentState {\n\t// Thread state from assistant-ui (single source of truth)\n\tconst threadMessages = useThread((thread) => thread.messages)\n\tconst isRunning = useThread((thread) => thread.isRunning)\n\n\t// Actions derived from thread messages (includes both text and voice tool calls)\n\tconst actions = useActions()\n\tconst currentAction = useCurrentAction()\n\tconst recentActions = useRecentActions(3)\n\tconst lastCompletedAction = useLastCompletedAction()\n\n\t// Summary from last assistant message\n\tconst summary = useLatestSummary()\n\n\t// Voice controls from VoiceThreadBridge\n\tconst voiceThread = useOptionalVoiceThread()\n\n\t// MCP tools (optional - may not be in MCP context)\n\tconst mcpContext = useOptionalMCPTools()\n\n\t// Derived: is voice active\n\tconst isVoiceActive = !!(\n\t\tvoiceThread?.isActive ||\n\t\tvoiceThread?.isConnecting ||\n\t\tvoiceThread?.isError\n\t)\n\n\t// Has messages\n\tconst hasMessages = (threadMessages?.length ?? 0) > 0\n\n\t// Build voice interface\n\tconst voice: AgentVoice | null = useMemo(() => {\n\t\tif (!voiceThread) return null\n\n\t\treturn {\n\t\t\tisActive: voiceThread.isActive,\n\t\t\tisConnecting: voiceThread.isConnecting,\n\t\t\tisError: voiceThread.isError,\n\t\t\tisMuted: voiceThread.isMuted,\n\t\t\tisSupported: voiceThread.isSupported,\n\t\t\terror: voiceThread.error,\n\t\t\tsessionId: voiceThread.sessionId,\n\t\t\taudioLevel: voiceThread.audioLevel,\n\t\t\ttranscript: voiceThread.transcript,\n\t\t\tstart: voiceThread.start,\n\t\t\tstop: voiceThread.stop,\n\t\t\ttoggleMute: voiceThread.toggleMute,\n\t\t\tsendMessage: voiceThread.sendMessage,\n\t\t}\n\t}, [voiceThread])\n\n\t// Build tools interface\n\tconst tools: AgentTools | null = useMemo(() => {\n\t\tif (!mcpContext) return null\n\n\t\treturn {\n\t\t\tlist: mcpContext.tools,\n\t\t\tcall: mcpContext.callTool,\n\t\t\tprompts: mcpContext.prompts ?? [],\n\t\t\tgetPrompt: mcpContext.getPrompt,\n\t\t}\n\t}, [mcpContext])\n\n\t// Build the full agent state\n\treturn useMemo<AgentState>(\n\t\t() => ({\n\t\t\t// Thread (single source of truth)\n\t\t\tmessages: (threadMessages ?? []) as readonly AgentMessage[],\n\t\t\tisRunning,\n\t\t\thasMessages,\n\n\t\t\t// Actions (derived from thread)\n\t\t\tactions,\n\t\t\tcurrentAction,\n\t\t\trecentActions,\n\t\t\tlastCompletedAction,\n\n\t\t\t// Summary\n\t\t\tsummary,\n\n\t\t\t// Voice\n\t\t\tvoice,\n\n\t\t\t// Tools\n\t\t\ttools,\n\n\t\t\t// Derived\n\t\t\tisVoiceActive,\n\t\t}),\n\t\t[\n\t\t\tthreadMessages,\n\t\t\tisRunning,\n\t\t\thasMessages,\n\t\t\tactions,\n\t\t\tcurrentAction,\n\t\t\trecentActions,\n\t\t\tlastCompletedAction,\n\t\t\tsummary,\n\t\t\tvoice,\n\t\t\ttools,\n\t\t\tisVoiceActive,\n\t\t]\n\t)\n}\n","/**\n * AgentUIProvider\n *\n * Manages non-thread UI state that persists across thread switches.\n * This includes open/close status, pill mode, position, and unread indicators.\n *\n * Thread-level state (messages, tool calls, etc.) is managed by @assistant-ui/react.\n * This provider only handles UI-specific state that is independent of the current thread.\n *\n * @example Basic usage\n * ```tsx\n * import { AgentUIProvider, useAgentUI } from '@mcp-b/embedded-agent'\n *\n * function App() {\n * return (\n * <AgentUIProvider>\n * <MyComponent />\n * </AgentUIProvider>\n * )\n * }\n *\n * function MyComponent() {\n * const { isOpen, setOpen, userMode, setUserMode } = useAgentUI()\n * // ...\n * }\n * ```\n */\n\nimport { createContext, useCallback, useContext, useMemo, useRef, useState } from 'react'\n\nimport type { FC, ReactNode } from 'react'\n\n/** UI mode for the pill widget */\nexport type PillMode = 'collapsed' | 'hovered' | 'composing' | 'active' | 'expanded'\n\n/** Position for draggable elements */\nexport interface Position {\n\tx: number\n\ty: number\n}\n\n/**\n * Agent UI state - non-thread state that persists across sessions\n */\nexport interface AgentUIState {\n\t/** Whether the agent UI is open (modal or expanded pill) */\n\tisOpen: boolean\n\n\t/** Current pill mode */\n\tuserMode: PillMode\n\n\t/** Drag position offset for the pill */\n\tposition: Position\n\n\t/** Whether there are unread messages */\n\thasUnread: boolean\n\n\t/** Whether voice mode is currently active */\n\tisVoiceActive: boolean\n\n\t/** Whether the pill is in full-screen mode */\n\tisFullScreen: boolean\n}\n\n/**\n * Agent UI context value with state and actions\n */\nexport interface AgentUIContextValue extends AgentUIState {\n\t/** Set the open state */\n\tsetOpen: (open: boolean) => void\n\n\t/** Toggle the open state */\n\ttoggleOpen: () => void\n\n\t/** Set the pill mode */\n\tsetUserMode: (mode: PillMode) => void\n\n\t/** Set the drag position */\n\tsetPosition: (position: Position) => void\n\n\t/** Reset position to default */\n\tresetPosition: () => void\n\n\t/** Mark messages as read */\n\tmarkRead: () => void\n\n\t/** Mark messages as unread */\n\tmarkUnread: () => void\n\n\t/** Set voice active state */\n\tsetVoiceActive: (active: boolean) => void\n\n\t/** Collapse the pill to its default state */\n\tcollapse: () => void\n\n\t/** Expand the pill to composing mode */\n\texpand: () => void\n\n\t/** Enter full-screen mode */\n\tenterFullScreen: () => void\n\n\t/** Exit full-screen mode */\n\texitFullScreen: () => void\n\n\t/** Toggle full-screen mode */\n\ttoggleFullScreen: () => void\n}\n\nconst AgentUIContext = createContext<AgentUIContextValue | null>(null)\n\nconst DEFAULT_POSITION: Position = { x: 0, y: 0 }\n\nexport interface AgentUIProviderProps {\n\tchildren: ReactNode\n\n\t/** Initial open state (default: false) */\n\tdefaultOpen?: boolean\n\n\t/** Initial pill mode (default: 'collapsed') */\n\tdefaultMode?: PillMode\n\n\t/** Callback when open state changes */\n\tonOpenChange?: (open: boolean) => void\n\n\t/** Callback when mode changes */\n\tonModeChange?: (mode: PillMode) => void\n}\n\n/**\n * Provider for non-thread UI state.\n *\n * This state persists across:\n * - Thread switches\n * - Modal open/close\n * - Component remounts\n */\nexport const AgentUIProvider: FC<AgentUIProviderProps> = ({\n\tchildren,\n\tdefaultOpen = false,\n\tdefaultMode = 'collapsed',\n\tonOpenChange,\n\tonModeChange,\n}) => {\n\t// Core UI state\n\tconst [isOpen, setIsOpenState] = useState(defaultOpen)\n\tconst [userMode, setUserModeState] = useState<PillMode>(defaultMode)\n\tconst [position, setPositionState] = useState<Position>(DEFAULT_POSITION)\n\tconst [hasUnread, setHasUnread] = useState(false)\n\tconst [isVoiceActive, setIsVoiceActiveState] = useState(false)\n\tconst [isFullScreen, setIsFullScreen] = useState(false)\n\n\t// Callback refs to avoid stale closures\n\tconst onOpenChangeRef = useRef(onOpenChange)\n\tconst onModeChangeRef = useRef(onModeChange)\n\tonOpenChangeRef.current = onOpenChange\n\tonModeChangeRef.current = onModeChange\n\n\t// Actions\n\tconst setOpen = useCallback((open: boolean) => {\n\t\tsetIsOpenState(open)\n\t\tonOpenChangeRef.current?.(open)\n\t}, [])\n\n\tconst toggleOpen = useCallback(() => {\n\t\tsetIsOpenState((prev) => {\n\t\t\tconst next = !prev\n\t\t\tonOpenChangeRef.current?.(next)\n\t\t\treturn next\n\t\t})\n\t}, [])\n\n\tconst setUserMode = useCallback((mode: PillMode) => {\n\t\tsetUserModeState(mode)\n\t\tonModeChangeRef.current?.(mode)\n\t}, [])\n\n\tconst setPosition = useCallback((pos: Position) => {\n\t\tsetPositionState(pos)\n\t}, [])\n\n\tconst resetPosition = useCallback(() => {\n\t\tsetPositionState(DEFAULT_POSITION)\n\t}, [])\n\n\tconst markRead = useCallback(() => {\n\t\tsetHasUnread(false)\n\t}, [])\n\n\tconst markUnread = useCallback(() => {\n\t\tsetHasUnread(true)\n\t}, [])\n\n\tconst setVoiceActive = useCallback((active: boolean) => {\n\t\tsetIsVoiceActiveState(active)\n\t}, [])\n\n\tconst collapse = useCallback(() => {\n\t\tsetUserModeState('collapsed')\n\t\tsetPositionState(DEFAULT_POSITION)\n\t\tsetIsFullScreen(false)\n\t\tonModeChangeRef.current?.('collapsed')\n\t}, [])\n\n\tconst expand = useCallback(() => {\n\t\tsetUserModeState('composing')\n\t\tonModeChangeRef.current?.('composing')\n\t}, [])\n\n\tconst enterFullScreen = useCallback(() => {\n\t\tsetIsFullScreen(true)\n\t}, [])\n\n\tconst exitFullScreen = useCallback(() => {\n\t\tsetIsFullScreen(false)\n\t}, [])\n\n\tconst toggleFullScreen = useCallback(() => {\n\t\tsetIsFullScreen((prev) => !prev)\n\t}, [])\n\n\t// Memoized context value\n\tconst value = useMemo<AgentUIContextValue>(\n\t\t() => ({\n\t\t\t// State\n\t\t\tisOpen,\n\t\t\tuserMode,\n\t\t\tposition,\n\t\t\thasUnread,\n\t\t\tisVoiceActive,\n\t\t\tisFullScreen,\n\n\t\t\t// Actions\n\t\t\tsetOpen,\n\t\t\ttoggleOpen,\n\t\t\tsetUserMode,\n\t\t\tsetPosition,\n\t\t\tresetPosition,\n\t\t\tmarkRead,\n\t\t\tmarkUnread,\n\t\t\tsetVoiceActive,\n\t\t\tcollapse,\n\t\t\texpand,\n\t\t\tenterFullScreen,\n\t\t\texitFullScreen,\n\t\t\ttoggleFullScreen,\n\t\t}),\n\t\t[\n\t\t\tisOpen,\n\t\t\tuserMode,\n\t\t\tposition,\n\t\t\thasUnread,\n\t\t\tisVoiceActive,\n\t\t\tisFullScreen,\n\t\t\tsetOpen,\n\t\t\ttoggleOpen,\n\t\t\tsetUserMode,\n\t\t\tsetPosition,\n\t\t\tresetPosition,\n\t\t\tmarkRead,\n\t\t\tmarkUnread,\n\t\t\tsetVoiceActive,\n\t\t\tcollapse,\n\t\t\texpand,\n\t\t\tenterFullScreen,\n\t\t\texitFullScreen,\n\t\t\ttoggleFullScreen,\n\t\t]\n\t)\n\n\treturn <AgentUIContext.Provider value={value}>{children}</AgentUIContext.Provider>\n}\n\n/**\n * Hook to access agent UI state and actions\n * @throws Error if used outside AgentUIProvider\n */\nexport function useAgentUI(): AgentUIContextValue {\n\tconst context = useContext(AgentUIContext)\n\tif (!context) {\n\t\tthrow new Error('useAgentUI must be used within an AgentUIProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access agent UI state (returns null if not in provider)\n */\nexport function useOptionalAgentUI(): AgentUIContextValue | null {\n\treturn useContext(AgentUIContext)\n}\n\n/**\n * Hook to get just the pill mode (for components that only need mode)\n */\nexport function usePillMode(): PillMode {\n\tconst { userMode } = useAgentUI()\n\treturn userMode\n}\n\n/**\n * Hook to check if agent has unread messages\n */\nexport function useHasUnread(): boolean {\n\tconst { hasUnread } = useAgentUI()\n\treturn hasUnread\n}\n","'use client'\n\nimport { useCallback, useEffect, useState } from 'react'\n\nimport { KEYBOARD_VISIBILITY_THRESHOLD_PX } from '../lib/constants'\n\ninterface KeyboardState {\n\t/** Whether the soft keyboard is currently visible */\n\tisKeyboardVisible: boolean\n\t/** Height of the keyboard in pixels (0 if not visible) */\n\tkeyboardHeight: number\n\t/** Visible viewport height (excluding keyboard) */\n\tvisibleHeight: number\n}\n\n/**\n * Hook to detect and respond to soft keyboard visibility on mobile devices.\n *\n * Uses the Visual Viewport API for reliable keyboard detection.\n * Falls back gracefully on unsupported browsers.\n *\n * Usage:\n * ```tsx\n * const { isKeyboardVisible, keyboardHeight } = useKeyboardAware()\n * // Adjust UI based on keyboard state\n * ```\n */\nexport function useKeyboardAware(): KeyboardState {\n\tconst [state, setState] = useState<KeyboardState>({\n\t\tisKeyboardVisible: false,\n\t\tkeyboardHeight: 0,\n\t\tvisibleHeight: typeof window !== 'undefined' ? window.innerHeight : 0,\n\t})\n\n\tconst updateKeyboardState = useCallback(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst visualViewport = window.visualViewport\n\t\tif (!visualViewport) {\n\t\t\t// Fallback for browsers without Visual Viewport API\n\t\t\tsetState({\n\t\t\t\tisKeyboardVisible: false,\n\t\t\t\tkeyboardHeight: 0,\n\t\t\t\tvisibleHeight: window.innerHeight,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst windowHeight = window.innerHeight\n\t\tconst viewportHeight = visualViewport.height\n\n\t\t// Keyboard is likely visible if viewport is significantly smaller than window\n\t\tconst heightDiff = windowHeight - viewportHeight\n\t\tconst isKeyboardVisible = heightDiff > KEYBOARD_VISIBILITY_THRESHOLD_PX\n\n\t\tsetState({\n\t\t\tisKeyboardVisible,\n\t\t\tkeyboardHeight: isKeyboardVisible ? heightDiff : 0,\n\t\t\tvisibleHeight: viewportHeight,\n\t\t})\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst visualViewport = window.visualViewport\n\n\t\t// Initial update\n\t\tupdateKeyboardState()\n\n\t\tif (visualViewport) {\n\t\t\t// Visual Viewport API - most reliable\n\t\t\tvisualViewport.addEventListener('resize', updateKeyboardState)\n\t\t\tvisualViewport.addEventListener('scroll', updateKeyboardState)\n\n\t\t\treturn () => {\n\t\t\t\tvisualViewport.removeEventListener('resize', updateKeyboardState)\n\t\t\t\tvisualViewport.removeEventListener('scroll', updateKeyboardState)\n\t\t\t}\n\t\t} else {\n\t\t\t// Fallback: listen for window resize\n\t\t\twindow.addEventListener('resize', updateKeyboardState)\n\n\t\t\treturn () => {\n\t\t\t\twindow.removeEventListener('resize', updateKeyboardState)\n\t\t\t}\n\t\t}\n\t}, [updateKeyboardState])\n\n\treturn state\n}\n\n/**\n * Returns a CSS transform value to offset an element above the keyboard.\n * Use this with fixed-position elements that should stay visible when keyboard appears.\n *\n * @param keyboardHeight - Height of keyboard from useKeyboardAware\n * @param additionalOffset - Extra pixels to add above keyboard (default: 8)\n */\nexport function getKeyboardOffset(keyboardHeight: number, additionalOffset = 8): string {\n\tif (keyboardHeight <= 0) return 'translateY(0)'\n\treturn `translateY(-${keyboardHeight + additionalOffset}px)`\n}\n\nexport default useKeyboardAware\n","'use client'\n\nimport { useEffect, useState } from 'react'\n\n/**\n * Hook to detect if the current device is a mobile/touch device.\n * Uses media queries for reliable detection that works with SSR.\n *\n * Detection strategy:\n * 1. (hover: none) - Device has no hover capability (touch-only)\n * 2. (pointer: coarse) - Device uses imprecise pointer (finger vs mouse)\n *\n * Returns:\n * - isMobile: true if device is likely a mobile/touch device\n * - isTouchDevice: true if device supports touch input\n * - isCoarsePointer: true if primary input is coarse (finger)\n */\nexport function useMobileDetect() {\n\tconst [isMobile, setIsMobile] = useState(false)\n\tconst [isTouchDevice, setIsTouchDevice] = useState(false)\n\tconst [isCoarsePointer, setIsCoarsePointer] = useState(false)\n\n\tuseEffect(() => {\n\t\t// Check for touch capability\n\t\tconst hasTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0\n\n\t\t// Check media queries\n\t\tconst hoverNone = window.matchMedia('(hover: none)')\n\t\tconst pointerCoarse = window.matchMedia('(pointer: coarse)')\n\n\t\tconst updateState = () => {\n\t\t\tsetIsTouchDevice(hasTouch)\n\t\t\tsetIsCoarsePointer(pointerCoarse.matches)\n\t\t\t// Consider mobile if no hover OR coarse pointer\n\t\t\tsetIsMobile(hoverNone.matches || pointerCoarse.matches)\n\t\t}\n\n\t\tupdateState()\n\n\t\t// Listen for changes (e.g., connecting mouse to tablet)\n\t\tconst handleHoverChange = () => updateState()\n\t\tconst handlePointerChange = () => updateState()\n\n\t\thoverNone.addEventListener('change', handleHoverChange)\n\t\tpointerCoarse.addEventListener('change', handlePointerChange)\n\n\t\treturn () => {\n\t\t\thoverNone.removeEventListener('change', handleHoverChange)\n\t\t\tpointerCoarse.removeEventListener('change', handlePointerChange)\n\t\t}\n\t}, [])\n\n\treturn { isMobile, isTouchDevice, isCoarsePointer }\n}\n\n/**\n * Static check for mobile - useful for SSR fallback\n * Returns true on server/initial render to be safe\n */\nexport function checkIsMobileSSR(): boolean {\n\tif (typeof window === 'undefined') return false\n\treturn (\n\t\twindow.matchMedia('(hover: none)').matches || window.matchMedia('(pointer: coarse)').matches\n\t)\n}\n\nexport default useMobileDetect\n","/**\n * usePendingToolCalls Hook\n *\n * Derives pending tool call state from assistant-ui's thread state.\n * This replaces the external pendingApprovalStore by using the single source of truth.\n *\n * Benefits:\n * - No external store synchronization needed\n * - No registration/unregistration logic\n * - No infinite loop issues from useSyncExternalStore\n * - Naturally reactive to thread state changes\n *\n * For non-reactive utilities (callbacks/effects), see lib/thread-utils.ts\n */\nimport { useThread, useThreadRuntime } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport type { ThreadAssistantMessage } from '@assistant-ui/react'\n// Import the type for internal use\nimport type { PendingToolCallInfo } from '../lib/thread-utils'\n\n// Re-export the shared type for backwards compatibility\nexport type { PendingToolCallInfo as PendingToolCall } from '../lib/thread-utils'\n\n/**\n * Hook to get all pending tool calls that require user approval.\n * Derives state from assistant-ui's thread messages.\n *\n * This is a reactive hook - it will re-render when thread state changes.\n * For non-reactive access in callbacks, use getPendingToolCalls() from lib/thread-utils.ts\n */\nexport function usePendingToolCalls(): PendingToolCallInfo[] {\n\tconst messages = useThread((t) => t.messages)\n\n\treturn useMemo(() => {\n\t\tconst result: PendingToolCallInfo[] = []\n\n\t\tfor (const msg of messages) {\n\t\t\t// Only assistant messages can have tool calls\n\t\t\tif (msg.role !== 'assistant') continue\n\n\t\t\t// Cast to assistant message to access status\n\t\t\tconst assistantMsg = msg as ThreadAssistantMessage\n\n\t\t\t// Only process messages waiting for tool results\n\t\t\t// Check for requires-action status (don't check reason - it may vary)\n\t\t\tif (assistantMsg.status?.type !== 'requires-action') continue\n\n\t\t\t// Find tool-call parts without results\n\t\t\tfor (const part of assistantMsg.content) {\n\t\t\t\tif (part.type !== 'tool-call') continue\n\t\t\t\tif (part.result !== undefined) continue\n\n\t\t\t\tresult.push({\n\t\t\t\t\tmessageId: msg.id,\n\t\t\t\t\ttoolCallId: part.toolCallId,\n\t\t\t\t\ttoolName: part.toolName,\n\t\t\t\t\targs: (part.args as Record<string, unknown>) ?? {},\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}, [messages])\n}\n\n/**\n * Hook to check if there are any pending tool calls.\n * Optimized for conditional rendering - returns boolean instead of array.\n */\nexport function useHasPendingToolCalls(): boolean {\n\tconst messages = useThread((t) => t.messages)\n\n\treturn useMemo(() => {\n\t\tfor (const msg of messages) {\n\t\t\tif (msg.role !== 'assistant') continue\n\n\t\t\tconst assistantMsg = msg as ThreadAssistantMessage\n\n\t\t\t// Check for requires-action status (don't check reason - it may vary)\n\t\t\tif (assistantMsg.status?.type !== 'requires-action') continue\n\n\t\t\tfor (const part of assistantMsg.content) {\n\t\t\t\tif (part.type === 'tool-call' && part.result === undefined) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn false\n\t}, [messages])\n}\n\n/**\n * Hook to get the thread runtime for calling addToolResult.\n * Re-exported for convenience.\n */\nexport { useThreadRuntime }\n","'use client'\n\nimport { useCallback, useRef } from 'react'\n\nimport { PINCH_GESTURE_CONFIG } from '../lib/constants'\n\nimport type { TouchEvent as ReactTouchEvent } from 'react'\n\ninterface PinchGestureOptions {\n\t/** Callback when pinch-out (expand) gesture detected */\n\tonPinchOut?: () => void\n\t/** Callback when pinch-in (collapse) gesture detected */\n\tonPinchIn?: () => void\n\t/** Whether gesture detection is enabled */\n\tenabled?: boolean\n\t/** Minimum scale change to trigger (default from PINCH_GESTURE_CONFIG) */\n\tthreshold?: number\n}\n\ninterface PinchState {\n\tinitialDistance: number | null\n\tlastDistance: number | null\n\tisActive: boolean\n}\n\n/** Minimal touch point interface for distance calculation */\ninterface TouchPoint {\n\tclientX: number\n\tclientY: number\n}\n\n/**\n * Calculate distance between two touch points\n */\nfunction getTouchDistance(touch1: TouchPoint, touch2: TouchPoint): number {\n\tconst dx = touch2.clientX - touch1.clientX\n\tconst dy = touch2.clientY - touch1.clientY\n\treturn Math.sqrt(dx * dx + dy * dy)\n}\n\n/**\n * Hook for detecting two-finger pinch gestures.\n *\n * Implements pinch-to-expand (out) and pinch-to-collapse (in) detection\n * using native Touch Events for maximum compatibility.\n *\n * @example\n * ```tsx\n * const { handlers } = usePinchGesture({\n * onPinchOut: () => enterFullScreen(),\n * onPinchIn: () => exitFullScreen(),\n * enabled: isMobile && isExpanded,\n * })\n *\n * return <div {...handlers}>Content</div>\n * ```\n */\nexport function usePinchGesture({\n\tonPinchOut,\n\tonPinchIn,\n\tenabled = true,\n\tthreshold = PINCH_GESTURE_CONFIG.threshold,\n}: PinchGestureOptions) {\n\tconst stateRef = useRef<PinchState>({\n\t\tinitialDistance: null,\n\t\tlastDistance: null,\n\t\tisActive: false,\n\t})\n\n\tconst handleTouchStart = useCallback(\n\t\t(e: ReactTouchEvent) => {\n\t\t\tif (!enabled) return\n\t\t\tif (e.touches.length === 2) {\n\t\t\t\tconst distance = getTouchDistance(e.touches[0], e.touches[1])\n\n\t\t\t\t// Only start tracking if fingers are far enough apart\n\t\t\t\tif (distance >= PINCH_GESTURE_CONFIG.minInitialDistance) {\n\t\t\t\t\tstateRef.current = {\n\t\t\t\t\t\tinitialDistance: distance,\n\t\t\t\t\t\tlastDistance: distance,\n\t\t\t\t\t\tisActive: true,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[enabled]\n\t)\n\n\tconst handleTouchMove = useCallback(\n\t\t(e: ReactTouchEvent) => {\n\t\t\tif (!enabled || !stateRef.current.isActive) return\n\t\t\tif (e.touches.length !== 2) return\n\n\t\t\t// Track the latest distance during the gesture\n\t\t\tconst currentDistance = getTouchDistance(e.touches[0], e.touches[1])\n\t\t\tstateRef.current.lastDistance = currentDistance\n\t\t},\n\t\t[enabled]\n\t)\n\n\tconst handleTouchEnd = useCallback(\n\t\t(e: ReactTouchEvent) => {\n\t\t\tif (!enabled || !stateRef.current.isActive) return\n\n\t\t\tconst { initialDistance, lastDistance } = stateRef.current\n\n\t\t\t// When gesture ends, evaluate if it was a pinch\n\t\t\tif (e.touches.length < 2 && initialDistance !== null && lastDistance !== null) {\n\t\t\t\tconst scaleDelta = (lastDistance - initialDistance) / initialDistance\n\n\t\t\t\tif (scaleDelta > threshold) {\n\t\t\t\t\tonPinchOut?.()\n\t\t\t\t} else if (scaleDelta < -threshold) {\n\t\t\t\t\tonPinchIn?.()\n\t\t\t\t}\n\n\t\t\t\t// Reset state\n\t\t\t\tstateRef.current = {\n\t\t\t\t\tinitialDistance: null,\n\t\t\t\t\tlastDistance: null,\n\t\t\t\t\tisActive: false,\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[enabled, threshold, onPinchOut, onPinchIn]\n\t)\n\n\treturn {\n\t\thandlers: {\n\t\t\tonTouchStart: handleTouchStart,\n\t\t\tonTouchMove: handleTouchMove,\n\t\t\tonTouchEnd: handleTouchEnd,\n\t\t},\n\t}\n}\n\nexport default usePinchGesture\n","/**\n * ActivityIndicator Component\n *\n * Shows what the agent is currently doing based on thread state.\n * Displays in the composer area when the agent is running.\n *\n * Activity states:\n * - \"Thinking...\" - Agent is processing, no tools called yet\n * - \"Running {toolName}...\" - Single tool is executing\n * - \"Running {n} tools...\" - Multiple tools executing in parallel\n * - Shows streaming text preview when available\n */\n'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport {\n\tCamera,\n\tFileText,\n\tLoader2,\n\tMousePointer,\n\tNavigation,\n\tPenLine,\n\tSearch,\n\tTrash2,\n\tWrench,\n} from 'lucide-react'\nimport { useMemo } from 'react'\n\nimport { humanizeToolName } from '../../lib/format'\nimport { cn } from '../../lib/utils'\n\nimport type { LucideIcon } from 'lucide-react'\nimport type { FC } from 'react'\n\n// ============================================================================\n// Tool Icon Mapping\n// ============================================================================\n\n/**\n * Get an appropriate icon for a tool based on its name.\n * Uses pattern matching to categorize tools.\n */\nexport function getToolIcon(toolName: string): LucideIcon {\n\tconst name = toolName.toLowerCase()\n\n\t// Search/find operations\n\tif (\n\t\tname.includes('search') ||\n\t\tname.includes('find') ||\n\t\tname.includes('grep') ||\n\t\tname.includes('glob')\n\t) {\n\t\treturn Search\n\t}\n\n\t// Read/get operations\n\tif (\n\t\tname.includes('read') ||\n\t\tname.includes('get') ||\n\t\tname.includes('fetch') ||\n\t\tname.includes('list')\n\t) {\n\t\treturn FileText\n\t}\n\n\t// Write/create operations\n\tif (\n\t\tname.includes('write') ||\n\t\tname.includes('create') ||\n\t\tname.includes('add') ||\n\t\tname.includes('insert')\n\t) {\n\t\treturn PenLine\n\t}\n\n\t// Delete/remove operations\n\tif (name.includes('delete') || name.includes('remove') || name.includes('clear')) {\n\t\treturn Trash2\n\t}\n\n\t// Navigation operations\n\tif (name.includes('navigate') || name.includes('goto') || name.includes('open')) {\n\t\treturn Navigation\n\t}\n\n\t// UI interaction operations\n\tif (\n\t\tname.includes('click') ||\n\t\tname.includes('fill') ||\n\t\tname.includes('type') ||\n\t\tname.includes('hover')\n\t) {\n\t\treturn MousePointer\n\t}\n\n\t// Screenshot/snapshot operations\n\tif (name.includes('screenshot') || name.includes('snapshot') || name.includes('capture')) {\n\t\treturn Camera\n\t}\n\n\t// Default\n\treturn Wrench\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface ActivityState {\n\ttype: 'idle' | 'thinking' | 'tool' | 'parallel_tools' | 'streaming'\n\tlabel: string\n\ticon: LucideIcon\n\ttoolNames?: string[]\n\tstreamingText?: string\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to derive current activity state from the thread.\n */\nexport function useActivityState(): ActivityState | null {\n\tconst messages = useThread((thread) => thread.messages)\n\tconst isRunning = useThread((thread) => thread.isRunning)\n\n\treturn useMemo(() => {\n\t\tif (!isRunning) return null\n\n\t\t// Find the last assistant message\n\t\tconst lastAssistantMessage = messages\n\t\t\t? [...messages].reverse().find((m) => m.role === 'assistant')\n\t\t\t: null\n\n\t\tif (!lastAssistantMessage) {\n\t\t\t// No assistant message yet - thinking\n\t\t\treturn {\n\t\t\t\ttype: 'thinking',\n\t\t\t\tlabel: 'Thinking...',\n\t\t\t\ticon: Loader2,\n\t\t\t}\n\t\t}\n\n\t\t// Get running tool calls from the message\n\t\tconst runningToolNames: string[] = []\n\t\tlet lastText: string | undefined\n\n\t\tfor (const part of lastAssistantMessage.content) {\n\t\t\tif (part.type === 'tool-call') {\n\t\t\t\t// Check if this tool call is running (no status means running, or status.type === 'running')\n\t\t\t\tconst toolPart = part as { toolName: string; status?: { type: string } }\n\t\t\t\tif (!toolPart.status || toolPart.status.type === 'running') {\n\t\t\t\t\trunningToolNames.push(toolPart.toolName)\n\t\t\t\t}\n\t\t\t} else if (part.type === 'text') {\n\t\t\t\tconst textPart = part as { text: string }\n\t\t\t\tlastText = textPart.text\n\t\t\t}\n\t\t}\n\n\t\t// Determine activity state\n\t\tif (runningToolNames.length === 0) {\n\t\t\t// No running tools\n\t\t\tif (lastText && lastText.length > 0) {\n\t\t\t\t// Has text content - streaming response\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'streaming',\n\t\t\t\t\tlabel: 'Writing response...',\n\t\t\t\t\ticon: PenLine,\n\t\t\t\t\tstreamingText: lastText,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// No text either - still thinking\n\t\t\treturn {\n\t\t\t\ttype: 'thinking',\n\t\t\t\tlabel: 'Thinking...',\n\t\t\t\ticon: Loader2,\n\t\t\t}\n\t\t}\n\n\t\tif (runningToolNames.length === 1) {\n\t\t\t// Single tool running\n\t\t\tconst toolName = runningToolNames[0]\n\t\t\treturn {\n\t\t\t\ttype: 'tool',\n\t\t\t\tlabel: humanizeToolName(toolName, true),\n\t\t\t\ticon: getToolIcon(toolName),\n\t\t\t\ttoolNames: [toolName],\n\t\t\t}\n\t\t}\n\n\t\t// Multiple tools running in parallel\n\t\treturn {\n\t\t\ttype: 'parallel_tools',\n\t\t\tlabel: `Running ${runningToolNames.length} tools...`,\n\t\t\ticon: Loader2,\n\t\t\ttoolNames: runningToolNames,\n\t\t}\n\t}, [messages, isRunning])\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface ActivityIndicatorProps {\n\tclassName?: string\n}\n\n/**\n * Displays the current agent activity.\n * Shows in the composer area when the agent is running.\n */\nexport const ActivityIndicator: FC<ActivityIndicatorProps> = ({ className }) => {\n\tconst activity = useActivityState()\n\n\tif (!activity) return null\n\n\tconst Icon = activity.icon\n\tconst isSpinning = activity.type === 'thinking' || activity.type === 'parallel_tools'\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center gap-2 px-3 py-2',\n\t\t\t\t'rounded-lg bg-blue-500/10 border border-blue-500/20',\n\t\t\t\t'text-sm text-blue-400',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<Icon className={cn('h-4 w-4 flex-shrink-0', isSpinning && 'animate-spin')} />\n\t\t\t<span className=\"truncate\">{activity.label}</span>\n\n\t\t\t{/* Show parallel tool names on hover/expand */}\n\t\t\t{activity.type === 'parallel_tools' && activity.toolNames && (\n\t\t\t\t<div className=\"hidden sm:flex items-center gap-1 ml-1\">\n\t\t\t\t\t{activity.toolNames.slice(0, 3).map((name, i) => {\n\t\t\t\t\t\tconst ToolIcon = getToolIcon(name)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<span key={i} title={humanizeToolName(name, true)}>\n\t\t\t\t\t\t\t\t<ToolIcon className=\"h-3 w-3 text-blue-400/60\" />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t\t{activity.toolNames.length > 3 && (\n\t\t\t\t\t\t<span className=\"text-xs text-blue-400/60\">+{activity.toolNames.length - 3}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\nexport default ActivityIndicator\n","/**\n * Approval Mode Toggle\n *\n * A compact toggle for switching between 'auto' and 'ask' modes\n * for destructive tool approval. Shows in the pill header.\n */\nimport { Shield, ShieldOff } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\nimport { useOptionalToolApproval } from '../../providers/ToolApprovalProvider'\n\nimport type { FC } from 'react'\n\nexport interface ApprovalModeToggleProps {\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Compact toggle button for approval mode.\n * Shows a shield icon that indicates current mode.\n */\nexport const ApprovalModeToggle: FC<ApprovalModeToggleProps> = ({ className }) => {\n\tconst toolApproval = useOptionalToolApproval()\n\n\t// Don't render if no approval context\n\tif (!toolApproval) return null\n\n\tconst { mode, toggleMode } = toolApproval\n\tconst isAskMode = mode === 'ask'\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={toggleMode}\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center gap-1 rounded-md px-1.5 py-1',\n\t\t\t\t'text-[10px] font-medium uppercase tracking-wide',\n\t\t\t\t'transition-colors duration-150',\n\t\t\t\tisAskMode\n\t\t\t\t\t? 'bg-amber-500/20 text-amber-400 hover:bg-amber-500/30'\n\t\t\t\t\t: 'bg-zinc-700/50 text-white/40 hover:bg-zinc-700 hover:text-white/60',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\ttitle={\n\t\t\t\tisAskMode ? 'Ask before action (click to auto-approve)' : 'Auto-approve (click to ask)'\n\t\t\t}\n\t\t>\n\t\t\t{isAskMode ? (\n\t\t\t\t<>\n\t\t\t\t\t<Shield className=\"h-3 w-3\" />\n\t\t\t\t\t<span>Ask</span>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<ShieldOff className=\"h-3 w-3\" />\n\t\t\t\t\t<span>Auto</span>\n\t\t\t\t</>\n\t\t\t)}\n\t\t</button>\n\t)\n}\n\n/**\n * Inline approval mode indicator for the pill header.\n * Shows current mode with ability to toggle.\n */\nexport const ApprovalModeIndicator: FC<ApprovalModeToggleProps> = ({ className }) => {\n\tconst toolApproval = useOptionalToolApproval()\n\n\t// Don't render if no approval context\n\tif (!toolApproval) return null\n\n\tconst { mode, toggleMode } = toolApproval\n\tconst isAskMode = mode === 'ask'\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={toggleMode}\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-center justify-center rounded-full p-1',\n\t\t\t\t'transition-colors duration-150',\n\t\t\t\tisAskMode\n\t\t\t\t\t? 'text-amber-500 hover:bg-amber-500/20'\n\t\t\t\t\t: 'text-white/30 hover:bg-white/10 hover:text-white/50',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\ttitle={\n\t\t\t\tisAskMode\n\t\t\t\t\t? 'Ask before destructive actions (click to auto-approve)'\n\t\t\t\t\t: 'Auto-approve all actions (click to ask first)'\n\t\t\t}\n\t\t>\n\t\t\t{isAskMode ? <Shield className=\"h-3.5 w-3.5\" /> : <ShieldOff className=\"h-3.5 w-3.5\" />}\n\t\t</button>\n\t)\n}\n\nexport default ApprovalModeToggle\n","'use client'\n\nimport { AlertCircle, CheckCircle2, Circle, Loader2 } from 'lucide-react'\n\nimport { cn } from '../../lib/utils'\n\nimport type { FC } from 'react'\nimport type { Action } from '../../hooks/useActions'\n\ninterface CurrentActivityProps {\n\tcurrentAction: Action | null\n\trecentActions?: Action[]\n\tshowRecent?: boolean\n\tclassName?: string\n}\n\n/**\n * Displays the current action the agent is performing,\n * with optional recent completed steps shown below.\n */\nexport const CurrentActivity: FC<CurrentActivityProps> = ({\n\tcurrentAction,\n\trecentActions = [],\n\tshowRecent = true,\n\tclassName,\n}) => {\n\treturn (\n\t\t<div className={cn('space-y-2', className)}>\n\t\t\t{/* Current action - prominent display */}\n\t\t\t{currentAction ? (\n\t\t\t\t<div className=\"flex items-center gap-2.5\">\n\t\t\t\t\t<ActionStatusIcon status={currentAction.status} />\n\t\t\t\t\t<span className=\"text-sm font-medium text-white\">{currentAction.label}...</span>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t/* Thinking indicator - when running but no specific action yet */\n\t\t\t\t<div className=\"flex items-center gap-2.5\">\n\t\t\t\t\t<Loader2 className=\"h-4 w-4 text-blue-400 animate-spin\" />\n\t\t\t\t\t<span className=\"text-sm font-medium text-white/80\">Thinking...</span>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Recent completed actions - muted, smaller */}\n\t\t\t{showRecent && recentActions.length > 0 && (\n\t\t\t\t<div className=\"ml-1 border-l border-white/20 pl-3 space-y-1\">\n\t\t\t\t\t{recentActions.map((action) => (\n\t\t\t\t\t\t<div key={action.id} className=\"flex items-center gap-2 text-xs text-white/60\">\n\t\t\t\t\t\t\t<ActionStatusIcon status={action.status} size=\"sm\" />\n\t\t\t\t\t\t\t<span className={cn(action.status === 'error' && 'text-red-400')}>\n\t\t\t\t\t\t\t\t{action.label}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\ninterface ActionStatusIconProps {\n\tstatus: Action['status']\n\tsize?: 'sm' | 'md'\n\tclassName?: string\n}\n\n/**\n * Icon component for action status\n */\nexport const ActionStatusIcon: FC<ActionStatusIconProps> = ({ status, size = 'md', className }) => {\n\tconst sizeClass = size === 'sm' ? 'h-3 w-3' : 'h-4 w-4'\n\n\tswitch (status) {\n\t\tcase 'running':\n\t\t\treturn <Loader2 className={cn(sizeClass, 'text-blue-400 animate-spin', className)} />\n\t\tcase 'pending':\n\t\t\treturn <Circle className={cn(sizeClass, 'text-amber-400', className)} />\n\t\tcase 'success':\n\t\t\treturn <CheckCircle2 className={cn(sizeClass, 'text-green-400', className)} />\n\t\tcase 'error':\n\t\t\treturn <AlertCircle className={cn(sizeClass, 'text-red-400', className)} />\n\t\tdefault:\n\t\t\treturn <Circle className={cn(sizeClass, 'text-white/40', className)} />\n\t}\n}\n\n/**\n * Idle state indicator when no actions are running\n */\nexport const IdleIndicator: FC<{ className?: string }> = ({ className }) => {\n\treturn (\n\t\t<div className={cn('flex items-center gap-2 text-white/50', className)}>\n\t\t\t<div className=\"h-2 w-2 rounded-full bg-green-400/60\" />\n\t\t\t<span className=\"text-xs\">Ready</span>\n\t\t</div>\n\t)\n}\n","/**\n * MCP Tool Registry Component\n *\n * Registers all MCP tools with the assistant-ui runtime.\n * Uses the unified callTool function which auto-routes based on tool source.\n *\n * Supports destructive tool approval when ToolApprovalProvider is present:\n * - Tools with destructiveHint: true require user confirmation before execution\n * - Approval mode can be 'ask' (require confirmation) or 'auto' (execute immediately)\n * - Approval UI is handled by UnifiedToolFallback using the HITL pattern\n *\n * Tool execution captures metadata (timing, source info) and stores it in the\n * assistant-ui thread via ToolResponse artifacts. This enables:\n * - Performance monitoring (duration tracking)\n * - Source attribution (which MCP server handled the call)\n * - Error tracking (including abort status)\n *\n * Usage:\n * <MCPToolRegistry />\n *\n * This component should be placed inside both MCPToolsProvider and AssistantRuntimeProvider.\n */\nimport { useAssistantTool } from '@assistant-ui/react'\nimport { ToolResponse } from 'assistant-stream'\n\nimport { useMCPTools } from '../providers/MCPToolsProvider'\nimport { useOptionalToolApproval } from '../providers/ToolApprovalProvider'\n\nimport type { CallToolResult, ToolCallMetadata, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { ReadonlyJSONValue } from 'assistant-stream/utils'\nimport type { FC } from 'react'\n\n// ============================================================================\n// Tool Result Formatting\n// ============================================================================\n\n/**\n * Format tool result content for the assistant\n */\nexport function formatToolResult(result: CallToolResult): string {\n\tconst textContent = result.content\n\t\t.map((c: { type: string; text?: string }) => {\n\t\t\tif ('text' in c && typeof c.text === 'string') {\n\t\t\t\treturn c.text\n\t\t\t}\n\t\t\treturn JSON.stringify(c)\n\t\t})\n\t\t.join('\\n')\n\n\treturn textContent || 'Tool executed successfully'\n}\n\n// ============================================================================\n// Tool Bridge Components\n// ============================================================================\n\n/**\n * Bridge component that registers a single tool with assistant-ui.\n * Executes the tool immediately via MCP.\n * Captures execution metadata (timing, source) and stores in thread artifacts.\n */\nconst ToolBridge: FC<{\n\ttool: ToolWithSource\n\tcallTool: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>\n}> = ({ tool, callTool }) => {\n\tuseAssistantTool({\n\t\ttoolName: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tparameters: (tool.inputSchema ?? {}) as Record<string, unknown>,\n\t\texecute: async (args) => {\n\t\t\tconst startedAt = Date.now()\n\t\t\tlet isError = false\n\t\t\tlet wasAborted = false\n\n\t\t\ttry {\n\t\t\t\tconst result = await callTool(tool.name, args)\n\n\t\t\t\t// Check if the result indicates an error\n\t\t\t\tisError = result.isError === true\n\n\t\t\t\t// Check if the call was aborted (tool removed during execution)\n\t\t\t\twasAborted = result.content.some(\n\t\t\t\t\t(c) =>\n\t\t\t\t\t\tc.type === 'text' && typeof c.text === 'string' && c.text.includes('Tool call aborted')\n\t\t\t\t)\n\n\t\t\t\t// Build metadata artifact for thread persistence\n\t\t\t\tconst metadata = {\n\t\t\t\t\tstartedAt,\n\t\t\t\t\tduration: Date.now() - startedAt,\n\t\t\t\t\tsourceId: tool._sourceId,\n\t\t\t\t\tisError,\n\t\t\t\t\twasAborted,\n\t\t\t\t} satisfies ToolCallMetadata\n\n\t\t\t\t// Return ToolResponse with artifact for thread storage\n\t\t\t\treturn new ToolResponse({\n\t\t\t\t\tresult: formatToolResult(result),\n\t\t\t\t\tartifact: metadata as unknown as ReadonlyJSONValue,\n\t\t\t\t\tisError,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(`[ToolBridge] Tool '${tool.name}' execution failed:`, error)\n\n\t\t\t\t// Still capture metadata for failed calls\n\t\t\t\tconst metadata = {\n\t\t\t\t\tstartedAt,\n\t\t\t\t\tduration: Date.now() - startedAt,\n\t\t\t\t\tsourceId: tool._sourceId,\n\t\t\t\t\tisError: true,\n\t\t\t\t\twasAborted: false,\n\t\t\t\t} satisfies ToolCallMetadata\n\n\t\t\t\t// Return error as ToolResponse with metadata\n\t\t\t\treturn new ToolResponse({\n\t\t\t\t\tresult: `Error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tartifact: metadata as unknown as ReadonlyJSONValue,\n\t\t\t\t\tisError: true,\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t})\n\n\treturn null\n}\n\n/**\n * Bridge component for destructive tools that require approval.\n *\n * IMPORTANT: No execute function is provided!\n * This makes assistant-ui wait for the fallback to call addResult().\n * The model pauses until the user approves/denies via the fallback UI.\n */\nconst DestructiveToolBridge: FC<{\n\ttool: ToolWithSource\n}> = ({ tool }) => {\n\t// Register tool WITHOUT execute - this is key for HITL!\n\t// The fallback component handles execution via addResult()\n\tuseAssistantTool({\n\t\ttoolName: tool.name,\n\t\tdescription: tool.description ?? '',\n\t\tparameters: (tool.inputSchema ?? {}) as Record<string, unknown>,\n\t\t// No execute function = model waits for addResult()\n\t})\n\n\treturn null\n}\n\n// ============================================================================\n// Main Registry Component\n// ============================================================================\n\n/**\n * Tool registry that registers all MCP tools with assistant-ui.\n * Routes tool calls automatically based on _sourceId.\n * Uses DestructiveToolBridge for tools that require approval.\n */\nexport const MCPToolRegistry: FC = () => {\n\tconst { tools, callTool } = useMCPTools()\n\tconst toolApproval = useOptionalToolApproval()\n\n\treturn (\n\t\t<>\n\t\t\t{tools.map((tool) => {\n\t\t\t\t// Check if this tool requires approval\n\t\t\t\tconst needsApproval = toolApproval?.requiresApproval(tool) ?? false\n\n\t\t\t\tif (needsApproval) {\n\t\t\t\t\treturn <DestructiveToolBridge key={`${tool._sourceId}-${tool.name}`} tool={tool} />\n\t\t\t\t}\n\n\t\t\t\treturn <ToolBridge key={`${tool._sourceId}-${tool.name}`} tool={tool} callTool={callTool} />\n\t\t\t})}\n\t\t</>\n\t)\n}\n","/**\n * ElicitationButtonBar Component\n *\n * Renders an approval card above the composer when a tool requires approval.\n * Shows the tool name, description, and input arguments so users know\n * exactly what they're approving.\n *\n * - Accept: Executes the tool and returns the result\n * - Deny: Stops the thread entirely (user doesn't want to continue)\n */\n'use client'\n\nimport { useThreadRuntime } from '@assistant-ui/react'\nimport { AlertTriangle, Check, Loader2, X } from 'lucide-react'\nimport { useState } from 'react'\n\nimport { usePendingToolCalls } from '../../hooks/usePendingToolCalls'\nimport { formatArgs, humanizeToolName, TOOL_DENIED_MESSAGE } from '../../lib/format'\nimport { resolveAllPendingToolCalls } from '../../lib/thread-utils'\nimport { cn } from '../../lib/utils'\nimport { useMCPTools } from '../../providers/MCPToolsProvider'\nimport { formatToolResult } from '../MCPToolRegistry'\n\nimport type { FC } from 'react'\n\nexport interface ElicitationButtonBarProps {\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Approval card for tool execution that sits above the composer.\n * Shows tool name, description, and arguments when a tool requires approval.\n *\n * Returns null if there are no pending approvals.\n */\nexport const ElicitationButtonBar: FC<ElicitationButtonBarProps> = ({ className }) => {\n\tconst [isExecuting, setIsExecuting] = useState(false)\n\tconst pendingToolCalls = usePendingToolCalls()\n\tconst threadRuntime = useThreadRuntime()\n\tconst { callTool, tools } = useMCPTools()\n\n\t// Don't render if no pending approvals\n\tif (pendingToolCalls.length === 0) {\n\t\treturn null\n\t}\n\n\t// Get the first pending tool call\n\tconst firstTool = pendingToolCalls[0]\n\n\t// Get tool metadata\n\tconst humanizedName = humanizeToolName(firstTool.toolName)\n\tconst toolDescription = tools.find((t) => t.name === firstTool.toolName)?.description\n\tconst hasArgs = Object.keys(firstTool.args).length > 0\n\tconst formattedArgs = hasArgs ? formatArgs(firstTool.args) : null\n\n\t// Get the message part runtime for this tool call\n\tconst getPartRuntime = () => {\n\t\tconst messageRuntime = threadRuntime?.getMessageById(firstTool.messageId)\n\t\treturn messageRuntime?.getMessagePartByToolCallId(firstTool.toolCallId)\n\t}\n\n\tconst handleAccept = async () => {\n\t\tsetIsExecuting(true)\n\t\ttry {\n\t\t\tconst toolResult = await callTool(firstTool.toolName, firstTool.args)\n\t\t\tconst partRuntime = getPartRuntime()\n\t\t\tpartRuntime?.addToolResult(formatToolResult(toolResult))\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\t\t\tconst partRuntime = getPartRuntime()\n\t\t\tpartRuntime?.addToolResult(`Error: ${errorMessage}`)\n\t\t} finally {\n\t\t\tsetIsExecuting(false)\n\t\t}\n\t}\n\n\tconst handleDeny = () => {\n\t\t// Resolve all pending tool calls with denial message to prevent stuck state\n\t\tresolveAllPendingToolCalls(threadRuntime, TOOL_DENIED_MESSAGE)\n\t\t// Stop the thread entirely - user doesn't want to continue\n\t\tthreadRuntime.cancelRun()\n\t}\n\n\t// Show loading state while executing\n\tif (isExecuting) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn('rounded-xl border border-blue-500/30 bg-blue-500/10 px-3 py-2.5', className)}\n\t\t\t>\n\t\t\t\t<div className=\"flex items-center justify-center gap-2\">\n\t\t\t\t\t<Loader2 className=\"h-4 w-4 animate-spin text-blue-400\" />\n\t\t\t\t\t<span className=\"text-sm text-white/80\">\n\t\t\t\t\t\tExecuting <span className=\"font-medium text-blue-400\">{humanizedName}</span>\n\t\t\t\t\t\t...\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('rounded-xl border border-amber-500/30 bg-amber-500/10 px-3 py-2.5', className)}\n\t\t>\n\t\t\t{/* Header: Warning icon + tool name */}\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<AlertTriangle className=\"h-4 w-4 shrink-0 text-amber-500\" />\n\t\t\t\t<span className=\"text-sm text-white/90\">\n\t\t\t\t\tApprove <span className=\"font-medium text-amber-400\">{humanizedName}</span>?\n\t\t\t\t</span>\n\t\t\t</div>\n\n\t\t\t{/* Tool description (if available) */}\n\t\t\t{toolDescription && (\n\t\t\t\t<p className=\"mt-1.5 pl-6 text-xs leading-relaxed text-white/50\">{toolDescription}</p>\n\t\t\t)}\n\n\t\t\t{/* Arguments preview */}\n\t\t\t{formattedArgs && (\n\t\t\t\t<pre className=\"mt-2 max-h-24 overflow-auto whitespace-pre-wrap rounded-lg bg-white/5 p-2 font-mono text-[11px] leading-relaxed text-white/60\">\n\t\t\t\t\t{formattedArgs}\n\t\t\t\t</pre>\n\t\t\t)}\n\n\t\t\t{/* Accept/Deny buttons */}\n\t\t\t<div className=\"mt-2.5 flex items-center gap-2\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleDeny}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t'border border-white/20 text-white/70',\n\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t'hover:border-red-500/50 hover:bg-red-500/10 hover:text-red-400',\n\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<X className=\"h-3.5 w-3.5\" />\n\t\t\t\t\tDeny\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={handleAccept}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t'border border-amber-500/50 bg-amber-500/20 text-amber-400',\n\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t'hover:border-amber-500 hover:bg-amber-500/30',\n\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Check className=\"h-3.5 w-3.5\" />\n\t\t\t\t\tApprove\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default ElicitationButtonBar\n","'use client'\n\nimport {\n\tComposerPrimitive,\n\tThreadPrimitive,\n\tuseComposer,\n\tuseComposerRuntime,\n} from '@assistant-ui/react'\nimport { Mic, Send, Square } from 'lucide-react'\nimport { useCallback, useRef } from 'react'\n\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport { COMPOSER_MAX_CHARS } from '../../lib/constants'\nimport { cn } from '../../lib/utils'\n\nimport type { FC } from 'react'\n\ninterface PillComposerProps {\n\tplaceholder?: string\n\tshowVoiceButton?: boolean\n\tisVoiceActive?: boolean\n\tonVoiceToggle?: () => void\n\tshowCharCount?: boolean\n\tclassName?: string\n\t/** Whether in elicitation mode (tool approval pending) */\n\tisEliciting?: boolean\n\t/** Called when user submits text during elicitation (denial with reason) */\n\tonElicitationSubmit?: (reason: string) => void\n}\n\n/**\n * Character count indicator\n */\nconst CharacterCount: FC = () => {\n\tconst composer = useComposer((c) => c.text)\n\tconst charCount = composer?.length ?? 0\n\n\t// Only show when approaching limit or over\n\tif (charCount < COMPOSER_MAX_CHARS * 0.8) return null\n\n\tconst isOver = charCount > COMPOSER_MAX_CHARS\n\tconst remaining = COMPOSER_MAX_CHARS - charCount\n\n\treturn (\n\t\t<span className={cn('text-[10px] tabular-nums', isOver ? 'text-red-400' : 'text-white/40')}>\n\t\t\t{remaining}\n\t\t</span>\n\t)\n}\n\n/**\n * Compact composer for the pill UI.\n * Uses assistant-ui primitives for data binding.\n * Features auto-growing textarea and character count.\n */\nexport const PillComposer: FC<PillComposerProps> = ({\n\tplaceholder = 'Ask something...',\n\tshowVoiceButton = false,\n\tisVoiceActive = false,\n\tonVoiceToggle,\n\tshowCharCount = true,\n\tclassName,\n\tisEliciting = false,\n\tonElicitationSubmit,\n}) => {\n\t// Don't auto-focus on mobile to avoid triggering the keyboard immediately\n\tconst { isMobile } = useMobileDetect()\n\tconst inputRef = useRef<HTMLTextAreaElement>(null)\n\tconst composerRuntime = useComposerRuntime()\n\n\t// Dynamic placeholder based on elicitation state\n\tconst effectivePlaceholder = isEliciting ? 'Tell Char what to do differently' : placeholder\n\n\t// Blur input on submit to dismiss mobile keyboard\n\tconst handleSubmit = useCallback(() => {\n\t\tif (isMobile && inputRef.current) {\n\t\t\tinputRef.current.blur()\n\t\t}\n\t}, [isMobile])\n\n\t// Handle elicitation submission (denial with reason)\n\tconst handleElicitationSubmit = useCallback(() => {\n\t\tconst text = composerRuntime.getState().text.trim()\n\t\tif (text && onElicitationSubmit) {\n\t\t\tonElicitationSubmit(text)\n\t\t\tcomposerRuntime.setText('')\n\t\t\tif (isMobile && inputRef.current) {\n\t\t\t\tinputRef.current.blur()\n\t\t\t}\n\t\t}\n\t}, [composerRuntime, onElicitationSubmit, isMobile])\n\n\t// Handle Enter key during elicitation - prevent normal form submission\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent) => {\n\t\t\tif (isEliciting && e.key === 'Enter' && !e.shiftKey) {\n\t\t\t\te.preventDefault()\n\t\t\t\thandleElicitationSubmit()\n\t\t\t}\n\t\t},\n\t\t[isEliciting, handleElicitationSubmit]\n\t)\n\n\treturn (\n\t\t<ComposerPrimitive.Root\n\t\t\tclassName={cn(\n\t\t\t\t'flex items-end gap-1.5',\n\t\t\t\t'rounded-xl',\n\t\t\t\t'bg-white/8 border border-white/8',\n\t\t\t\t'px-2 py-1',\n\t\t\t\t'focus-within:border-white/15 focus-within:bg-white/10',\n\t\t\t\t'transition-colors duration-150',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tonSubmit={handleSubmit}\n\t\t>\n\t\t\t{/* Text input - auto-grows with content */}\n\t\t\t<ComposerPrimitive.Input\n\t\t\t\tref={inputRef}\n\t\t\t\tplaceholder={effectivePlaceholder}\n\t\t\t\tminRows={1}\n\t\t\t\tmaxRows={6}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex-1 min-w-0',\n\t\t\t\t\t'bg-transparent',\n\t\t\t\t\t'text-sm leading-[21px] text-white placeholder:text-white/40',\n\t\t\t\t\t'outline-none',\n\t\t\t\t\t'resize-none',\n\t\t\t\t\t'overflow-y-auto scroll-touch'\n\t\t\t\t)}\n\t\t\t\tstyle={{ touchAction: 'pan-y' }}\n\t\t\t\tautoFocus={!isMobile}\n\t\t\t\t// Stop pointer events from bubbling to drag handler when typing\n\t\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t\t// Intercept Enter key during elicitation to call handleElicitationSubmit\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t/>\n\n\t\t\t{/* Character count */}\n\t\t\t{showCharCount && <CharacterCount />}\n\n\t\t\t{/* Voice button (optional) */}\n\t\t\t{showVoiceButton && onVoiceToggle && (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={onVoiceToggle}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\tisVoiceActive\n\t\t\t\t\t\t\t? 'bg-white/20 text-white'\n\t\t\t\t\t\t\t: 'hover:bg-white/10 text-white/50 hover:text-white/80'\n\t\t\t\t\t)}\n\t\t\t\t\taria-label={isVoiceActive ? 'Stop voice input' : 'Start voice input'}\n\t\t\t\t>\n\t\t\t\t\t<Mic className=\"h-4.5 w-4.5 sm:h-4 sm:w-4\" />\n\t\t\t\t</button>\n\t\t\t)}\n\n\t\t\t{/* Send button - shown when not running */}\n\t\t\t<ThreadPrimitive.If running={false}>\n\t\t\t\t{isEliciting ? (\n\t\t\t\t\t/* During elicitation: custom button that sends denial with reason */\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleElicitationSubmit}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t\t'bg-white/90 text-slate-900',\n\t\t\t\t\t\t\t'hover:bg-white',\n\t\t\t\t\t\t\t'disabled:opacity-40 disabled:cursor-not-allowed',\n\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-label=\"Send feedback\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Send className=\"h-4.5 w-4.5 sm:h-4 sm:w-4\" />\n\t\t\t\t\t</button>\n\t\t\t\t) : (\n\t\t\t\t\t/* Normal mode: use ComposerPrimitive.Send for standard message sending */\n\t\t\t\t\t<ComposerPrimitive.Send asChild>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t\t\t'bg-white/90 text-slate-900',\n\t\t\t\t\t\t\t\t'hover:bg-white',\n\t\t\t\t\t\t\t\t'disabled:opacity-40 disabled:cursor-not-allowed',\n\t\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\taria-label=\"Send message\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Send className=\"h-4.5 w-4.5 sm:h-4 sm:w-4\" />\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</ComposerPrimitive.Send>\n\t\t\t\t)}\n\t\t\t</ThreadPrimitive.If>\n\n\t\t\t{/* Cancel button - shown when running */}\n\t\t\t<ThreadPrimitive.If running>\n\t\t\t\t<ComposerPrimitive.Cancel asChild>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t'p-2 sm:p-1.5 rounded-full',\n\t\t\t\t\t\t\t'bg-white/20 text-white',\n\t\t\t\t\t\t\t'hover:bg-white/30',\n\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\taria-label=\"Stop generating\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Square className=\"h-4 w-4 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t</button>\n\t\t\t\t</ComposerPrimitive.Cancel>\n\t\t\t</ThreadPrimitive.If>\n\t\t</ComposerPrimitive.Root>\n\t)\n}\n","'use client'\n\nimport { useEffect, useRef } from 'react'\n\n/**\n * Hook to manage aria-hidden on background content when a modal is open.\n *\n * This hook sets aria-hidden=\"true\" on all direct children of <body> except\n * the element containing the dialog, making the background inaccessible to\n * screen readers while the modal is active.\n *\n * Per WCAG, this is important because some mobile screen readers don't\n * consistently respect aria-modal=\"true\", so we need to explicitly hide\n * the background content.\n *\n * @param isActive - Whether the modal is currently active\n * @param containerRef - Ref to the modal container element\n */\nexport function useAriaHidden(\n\tisActive: boolean,\n\tcontainerRef: React.RefObject<HTMLElement | null>\n): void {\n\t// Track elements we've modified so we can restore them\n\tconst modifiedElementsRef = useRef<Map<Element, string | null>>(new Map())\n\n\tuseEffect(() => {\n\t\tif (!isActive) {\n\t\t\t// Restore all modified elements when modal closes\n\t\t\tmodifiedElementsRef.current.forEach((originalValue, element) => {\n\t\t\t\tif (originalValue === null) {\n\t\t\t\t\telement.removeAttribute('aria-hidden')\n\t\t\t\t} else {\n\t\t\t\t\telement.setAttribute('aria-hidden', originalValue)\n\t\t\t\t}\n\t\t\t})\n\t\t\tmodifiedElementsRef.current.clear()\n\t\t\treturn\n\t\t}\n\n\t\t// Find the container element's root ancestor (direct child of body)\n\t\tconst container = containerRef.current\n\t\tif (!container) return\n\n\t\t// Walk up to find the direct child of body\n\t\tlet dialogRoot: Element | null = container\n\t\twhile (dialogRoot && dialogRoot.parentElement !== document.body) {\n\t\t\tdialogRoot = dialogRoot.parentElement\n\t\t}\n\n\t\tif (!dialogRoot) return\n\n\t\t// Get all direct children of body\n\t\tconst bodyChildren = Array.from(document.body.children)\n\n\t\t// Hide all siblings of the dialog root\n\t\tbodyChildren.forEach((child) => {\n\t\t\t// Skip the dialog's root ancestor\n\t\t\tif (child === dialogRoot) return\n\n\t\t\t// Skip script and style elements\n\t\t\tif (child.tagName === 'SCRIPT' || child.tagName === 'STYLE' || child.tagName === 'LINK') {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Store the original aria-hidden value\n\t\t\tconst originalValue = child.getAttribute('aria-hidden')\n\t\t\tmodifiedElementsRef.current.set(child, originalValue)\n\n\t\t\t// Set aria-hidden to true\n\t\t\tchild.setAttribute('aria-hidden', 'true')\n\t\t})\n\n\t\t// Cleanup function to restore original values\n\t\treturn () => {\n\t\t\tmodifiedElementsRef.current.forEach((originalValue, element) => {\n\t\t\t\tif (originalValue === null) {\n\t\t\t\t\telement.removeAttribute('aria-hidden')\n\t\t\t\t} else {\n\t\t\t\t\telement.setAttribute('aria-hidden', originalValue)\n\t\t\t\t}\n\t\t\t})\n\t\t\tmodifiedElementsRef.current.clear()\n\t\t}\n\t}, [isActive, containerRef])\n}\n","'use client'\n\nimport { useCallback, useEffect, useRef } from 'react'\n\n/** Selector for all focusable elements within a container */\nconst FOCUSABLE_SELECTOR = [\n\t'a[href]',\n\t'button:not([disabled])',\n\t'input:not([disabled])',\n\t'select:not([disabled])',\n\t'textarea:not([disabled])',\n\t'[tabindex]:not([tabindex=\"-1\"])',\n\t'[contenteditable=\"true\"]',\n].join(', ')\n\ninterface UseFocusTrapOptions {\n\t/** Whether the focus trap is active */\n\tisActive: boolean\n\t/** Callback when user attempts to escape (e.g., pressing Escape) */\n\tonEscape?: () => void\n\t/** Whether to auto-focus the first focusable element when activated */\n\tautoFocus?: boolean\n\t/** Whether to return focus to the trigger element when deactivated */\n\treturnFocus?: boolean\n\t/** Whether to skip returning focus to input elements (prevents mobile keyboard re-trigger) */\n\tskipInputFocusReturn?: boolean\n}\n\ninterface UseFocusTrapReturn {\n\t/** Ref to attach to the container element */\n\tcontainerRef: React.RefObject<HTMLDivElement | null>\n\t/** Store the trigger element before activating the trap */\n\tstoreTrigger: () => void\n}\n\n/**\n * Focus trap hook for modal dialogs.\n *\n * Implements WCAG 2.4.3 Focus Order requirements:\n * - Traps Tab/Shift+Tab within the container\n * - Returns focus to trigger element on close\n * - Supports Escape key to close\n *\n * @example\n * ```tsx\n * const { containerRef, storeTrigger } = useFocusTrap({\n * isActive: isDialogOpen,\n * onEscape: () => setIsDialogOpen(false),\n * })\n *\n * // Before opening dialog:\n * storeTrigger()\n * setIsDialogOpen(true)\n *\n * // In JSX:\n * <div ref={containerRef} role=\"dialog\">...</div>\n * ```\n */\nexport function useFocusTrap({\n\tisActive,\n\tonEscape,\n\tautoFocus = true,\n\treturnFocus = true,\n\tskipInputFocusReturn = false,\n}: UseFocusTrapOptions): UseFocusTrapReturn {\n\tconst containerRef = useRef<HTMLDivElement | null>(null)\n\tconst triggerRef = useRef<HTMLElement | null>(null)\n\tconst previouslyFocusedRef = useRef<HTMLElement | null>(null)\n\n\t/** Store the currently focused element as the trigger */\n\tconst storeTrigger = useCallback(() => {\n\t\ttriggerRef.current = document.activeElement as HTMLElement\n\t}, [])\n\n\t/** Get all focusable elements within the container */\n\tconst getFocusableElements = useCallback((): HTMLElement[] => {\n\t\tif (!containerRef.current) return []\n\t\treturn Array.from(containerRef.current.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR))\n\t}, [])\n\n\t// Handle focus trap activation/deactivation\n\tuseEffect(() => {\n\t\tif (isActive) {\n\t\t\t// Store the currently focused element before trapping\n\t\t\tpreviouslyFocusedRef.current = document.activeElement as HTMLElement\n\n\t\t\t// Auto-focus the first focusable element\n\t\t\tif (autoFocus) {\n\t\t\t\t// Small delay to ensure container is mounted and visible\n\t\t\t\tconst timeoutId = setTimeout(() => {\n\t\t\t\t\tconst focusableElements = getFocusableElements()\n\t\t\t\t\tif (focusableElements.length > 0) {\n\t\t\t\t\t\tfocusableElements[0].focus()\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no focusable elements, focus the container itself\n\t\t\t\t\t\tcontainerRef.current?.focus()\n\t\t\t\t\t}\n\t\t\t\t}, 50)\n\n\t\t\t\treturn () => clearTimeout(timeoutId)\n\t\t\t}\n\t\t} else {\n\t\t\t// Return focus to the trigger element\n\t\t\tif (returnFocus && triggerRef.current && triggerRef.current.isConnected) {\n\t\t\t\t// Skip returning focus to inputs/textareas if configured (prevents mobile keyboard re-trigger)\n\t\t\t\tconst isInputElement =\n\t\t\t\t\ttriggerRef.current.tagName === 'INPUT' || triggerRef.current.tagName === 'TEXTAREA'\n\n\t\t\t\tif (skipInputFocusReturn && isInputElement) {\n\t\t\t\t\t// Blur the input instead of focusing it\n\t\t\t\t\ttriggerRef.current.blur()\n\t\t\t\t} else {\n\t\t\t\t\ttriggerRef.current.focus()\n\t\t\t\t}\n\t\t\t} else if (returnFocus && previouslyFocusedRef.current?.isConnected) {\n\t\t\t\tconst isInputElement =\n\t\t\t\t\tpreviouslyFocusedRef.current.tagName === 'INPUT' ||\n\t\t\t\t\tpreviouslyFocusedRef.current.tagName === 'TEXTAREA'\n\n\t\t\t\tif (skipInputFocusReturn && isInputElement) {\n\t\t\t\t\tpreviouslyFocusedRef.current.blur()\n\t\t\t\t} else {\n\t\t\t\t\tpreviouslyFocusedRef.current.focus()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}, [isActive, autoFocus, returnFocus, skipInputFocusReturn, getFocusableElements])\n\n\t// Handle keyboard navigation\n\tuseEffect(() => {\n\t\tif (!isActive) return\n\n\t\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\t\t// Handle Escape key\n\t\t\tif (event.key === 'Escape' && onEscape) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tonEscape()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Handle Tab key for focus trapping\n\t\t\tif (event.key === 'Tab') {\n\t\t\t\tconst focusableElements = getFocusableElements()\n\t\t\t\tif (focusableElements.length === 0) return\n\n\t\t\t\tconst firstElement = focusableElements[0]\n\t\t\t\tconst lastElement = focusableElements[focusableElements.length - 1]\n\t\t\t\tconst activeElement = document.activeElement\n\n\t\t\t\t// Shift+Tab from first element -> go to last\n\t\t\t\tif (event.shiftKey && activeElement === firstElement) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tlastElement.focus()\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Tab from last element -> go to first\n\t\t\t\tif (!event.shiftKey && activeElement === lastElement) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tfirstElement.focus()\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// If focus is outside the container, bring it back\n\t\t\t\tif (!containerRef.current?.contains(activeElement)) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tfirstElement.focus()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('keydown', handleKeyDown)\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown)\n\t}, [isActive, onEscape, getFocusableElements])\n\n\treturn {\n\t\tcontainerRef,\n\t\tstoreTrigger,\n\t}\n}\n","'use client'\n\nimport { AnimatePresence, motion, useReducedMotion } from 'motion/react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { useAriaHidden } from '../../hooks/useAriaHidden'\nimport { useFocusTrap } from '../../hooks/useFocusTrap'\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport {\n\tARIA_IDS,\n\tARIA_LABELS,\n\tclampSize,\n\tFULL_SCREEN_CONFIG,\n\tPILL_BORDER_RADIUS,\n\tPILL_CONTAINER_SIZES,\n\tUI_TIMING,\n} from '../../lib/constants'\nimport { cn } from '../../lib/utils'\n\nimport type { Variants } from 'motion/react'\nimport type { FC, ReactNode } from 'react'\nimport type { PillMode } from '../../core/providers/AgentUIProvider'\n\n// Re-export PillMode for consumers who import from this file\nexport type { PillMode } from '../../core/providers/AgentUIProvider'\n\ninterface PillContainerProps {\n\tmode: PillMode\n\tchildren: ReactNode\n\tonModeChange?: (mode: PillMode) => void\n\t/** Whether the pill is in full-screen expanded mode */\n\tisFullScreen?: boolean\n\tclassName?: string\n}\n\n// Spring configuration for size changes - snappy but smooth\nconst sizeSpring = {\n\ttype: 'spring' as const,\n\tstiffness: 400,\n\tdamping: 35,\n\tmass: 0.8,\n}\n\n// Smooth tween for full-screen transitions (spring is too aggressive for large viewport changes)\nconst fullScreenTween = {\n\ttype: 'tween' as const,\n\tduration: 0.35,\n\tease: [0.4, 0, 0.2, 1], // Material Design standard easing\n}\n\n// Reduced motion alternative - instant transitions\nconst reducedMotionTransition = {\n\tduration: 0,\n}\n\n// Container size variants - derived from centralized PILL_CONTAINER_SIZES config\n// See lib/constants.ts for the source of truth\n// Padding reduced for better mobile information density\nconst sizes = PILL_CONTAINER_SIZES\nconst containerVariants: Record<\n\tPillMode,\n\t{ width: string; height: string; padding: string; borderRadius: string }\n> = {\n\tcollapsed: {\n\t\twidth: clampSize(sizes.collapsed.width),\n\t\theight: clampSize(sizes.collapsed.height),\n\t\tpadding: '0px',\n\t\tborderRadius: PILL_BORDER_RADIUS.pill,\n\t},\n\thovered: {\n\t\twidth: clampSize(sizes.hovered.width),\n\t\theight: clampSize(sizes.hovered.height),\n\t\tpadding: '0px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.pill,\n\t},\n\tcomposing: {\n\t\twidth: clampSize(sizes.composing.width),\n\t\theight: 'auto',\n\t\tpadding: '8px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.rounded,\n\t},\n\tactive: {\n\t\twidth: clampSize(sizes.active.width),\n\t\theight: 'auto',\n\t\tpadding: '8px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.rounded,\n\t},\n\texpanded: {\n\t\twidth: clampSize(sizes.expanded.width),\n\t\theight: 'auto',\n\t\tpadding: '10px 10px',\n\t\tborderRadius: PILL_BORDER_RADIUS.rounded,\n\t},\n}\n\n// Full-screen variant - uses the same animation system\nconst fullScreenVariant = {\n\twidth: `min(${FULL_SCREEN_CONFIG.widthPercent}vw, ${FULL_SCREEN_CONFIG.maxWidth})`,\n\theight: `${FULL_SCREEN_CONFIG.heightPercent}vh`,\n\tpadding: `${FULL_SCREEN_CONFIG.padding}px`,\n\tborderRadius: PILL_BORDER_RADIUS.rounded,\n}\n\n// Content animation variants - simple fade, no transform\nconst contentVariants: Variants = {\n\thidden: {\n\t\topacity: 0,\n\t},\n\tvisible: {\n\t\topacity: 1,\n\t\ttransition: {\n\t\t\tduration: 0.15,\n\t\t\tdelay: 0.1, // Wait for container to expand first\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\ttransition: {\n\t\t\tduration: 0.1,\n\t\t},\n\t},\n}\n\n// Hint text animation - simple fade\nconst hintVariants: Variants = {\n\thidden: { opacity: 0 },\n\tvisible: {\n\t\topacity: 1,\n\t\ttransition: { delay: 0.05, duration: 0.15 },\n\t},\n\texit: {\n\t\topacity: 0,\n\t\ttransition: { duration: 0.08 },\n\t},\n}\n\n// Collapsed bar animation\nconst barVariants: Variants = {\n\tidle: {\n\t\topacity: 0.6,\n\t\tscaleX: 1,\n\t},\n\thover: {\n\t\topacity: 1,\n\t\tscaleX: 1.1,\n\t\ttransition: { duration: 0.2 },\n\t},\n}\n\n/**\n * Morphing container that changes size and shape based on state.\n * Uses spring animations for smooth, natural transitions.\n *\n * States:\n * - collapsed: Tiny 4px tall bar (ambient)\n * - hovered: Medium pill with prompt\n * - composing: User is typing\n * - active: Agent is working\n * - expanded: Full panel with summary/forms\n */\nexport const PillContainer: FC<PillContainerProps> = ({\n\tmode,\n\tchildren,\n\tonModeChange,\n\tisFullScreen = false,\n\tclassName,\n}) => {\n\tconst [isHovered, setIsHovered] = useState(false)\n\tconst hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n\tconst prefersReducedMotion = useReducedMotion()\n\n\t// Track previous full-screen state for smooth exit animations\n\tconst wasFullScreenRef = useRef(isFullScreen)\n\tconst isTransitioningFullScreen = isFullScreen !== wasFullScreenRef.current\n\t// Update ref after render\n\tuseEffect(() => {\n\t\twasFullScreenRef.current = isFullScreen\n\t}, [isFullScreen])\n\n\t// Detect mobile/touch devices\n\tconst { isMobile } = useMobileDetect()\n\n\t// Determine if dialog mode (for focus trap)\n\tconst isDialogActive = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t// Focus trap for accessibility - traps focus when in dialog mode\n\tconst { containerRef: focusTrapRef, storeTrigger } = useFocusTrap({\n\t\tisActive: isDialogActive,\n\t\tonEscape: () => {\n\t\t\t// Only collapse if not in active mode (agent is working)\n\t\t\tif (mode !== 'active') {\n\t\t\t\tonModeChange?.('collapsed')\n\t\t\t}\n\t\t},\n\t\tautoFocus: true,\n\t\treturnFocus: true,\n\t\t// On mobile, don't return focus to inputs (prevents keyboard re-triggering)\n\t\tskipInputFocusReturn: isMobile,\n\t})\n\n\t// Store trigger element before transitioning to dialog mode\n\tconst prevModeRef = useRef(mode)\n\tuseEffect(() => {\n\t\tconst wasCollapsedOrHovered =\n\t\t\tprevModeRef.current === 'collapsed' || prevModeRef.current === 'hovered'\n\t\tconst isNowDialog = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t\tif (wasCollapsedOrHovered && isNowDialog) {\n\t\t\tstoreTrigger()\n\t\t}\n\n\t\tprevModeRef.current = mode\n\t}, [mode, storeTrigger])\n\n\t// Hide background content from screen readers when in dialog mode\n\t// This is a fallback for mobile screen readers that don't respect aria-modal\n\tuseAriaHidden(isDialogActive, focusTrapRef)\n\n\t// Handle hover with debounce - only on non-touch devices\n\tconst handleMouseEnter = useCallback(() => {\n\t\t// Skip hover behavior on touch devices\n\t\tif (isMobile) return\n\n\t\tif (hoverTimeoutRef.current) {\n\t\t\tclearTimeout(hoverTimeoutRef.current)\n\t\t}\n\t\thoverTimeoutRef.current = setTimeout(() => {\n\t\t\tsetIsHovered(true)\n\t\t\tif (mode === 'collapsed') {\n\t\t\t\tonModeChange?.('hovered')\n\t\t\t}\n\t\t}, UI_TIMING.hoverDebounce)\n\t}, [mode, onModeChange, isMobile])\n\n\tconst handleMouseLeave = useCallback(() => {\n\t\t// Skip hover behavior on touch devices\n\t\tif (isMobile) return\n\n\t\tif (hoverTimeoutRef.current) {\n\t\t\tclearTimeout(hoverTimeoutRef.current)\n\t\t}\n\t\tsetIsHovered(false)\n\t\tif (mode === 'hovered') {\n\t\t\t// Small delay before collapsing to prevent flicker\n\t\t\thoverTimeoutRef.current = setTimeout(() => {\n\t\t\t\tonModeChange?.('collapsed')\n\t\t\t}, UI_TIMING.collapseDelay)\n\t\t}\n\t}, [mode, onModeChange, isMobile])\n\n\t// Handle click/tap to expand - on mobile, skip hover and go straight to composing\n\tconst handleClick = useCallback(() => {\n\t\tif (mode === 'collapsed' || mode === 'hovered') {\n\t\t\tonModeChange?.('composing')\n\t\t}\n\t}, [mode, onModeChange])\n\n\t// Handle focus for keyboard navigation - also helps on touch\n\tconst handleFocus = useCallback(() => {\n\t\tif (mode === 'collapsed' && !isMobile) {\n\t\t\tonModeChange?.('hovered')\n\t\t}\n\t}, [mode, onModeChange, isMobile])\n\n\tconst handleBlur = useCallback(() => {\n\t\tif (mode === 'hovered' && !isMobile) {\n\t\t\tonModeChange?.('collapsed')\n\t\t}\n\t}, [mode, onModeChange, isMobile])\n\n\t// Handle keyboard shortcuts (Cmd+Shift+K to toggle, Escape to close)\n\tuseEffect(() => {\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tconst isShortcut = (e.ctrlKey || e.metaKey) && e.shiftKey && e.key.toLowerCase() === 'k'\n\t\t\tconst isEscape = e.key === 'Escape'\n\n\t\t\tif (isShortcut) {\n\t\t\t\te.preventDefault()\n\t\t\t\tif (mode === 'collapsed') {\n\t\t\t\t\tonModeChange?.('composing')\n\t\t\t\t} else if (mode === 'composing' || mode === 'hovered') {\n\t\t\t\t\tonModeChange?.('collapsed')\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Escape to close (only when expanded, not when agent is running)\n\t\t\tif (isEscape && (mode === 'composing' || mode === 'expanded' || mode === 'hovered')) {\n\t\t\t\te.preventDefault()\n\t\t\t\tonModeChange?.('collapsed')\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('keydown', handleKeyDown)\n\t\treturn () => window.removeEventListener('keydown', handleKeyDown)\n\t}, [mode, onModeChange])\n\n\t// Clean up timeout on unmount\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\tif (hoverTimeoutRef.current) {\n\t\t\t\tclearTimeout(hoverTimeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst showContent = mode !== 'collapsed' && mode !== 'hovered'\n\t// Use full-screen variant when in full-screen mode, otherwise use mode-based variant\n\tconst currentVariant = isFullScreen ? fullScreenVariant : containerVariants[mode]\n\tconst isDialogMode = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t// Combine refs for motion.div (focus trap ref + internal needs)\n\tconst setContainerRef = useCallback(\n\t\t(node: HTMLDivElement | null) => {\n\t\t\t// Update the focus trap ref\n\t\t\tif (focusTrapRef) {\n\t\t\t\tfocusTrapRef.current = node\n\t\t\t}\n\t\t},\n\t\t[focusTrapRef]\n\t)\n\n\t// Determine glass styling class based on mode\n\tconst glassClassName = cn(\n\t\t'relative',\n\t\t// Full-screen: allow scrolling. Normal: clip overflow during animations\n\t\tisFullScreen ? 'overflow-y-auto scrollbar-thin scroll-touch' : 'overflow-hidden',\n\t\t// GPU acceleration hint (skip if reduced motion)\n\t\t!prefersReducedMotion && 'will-change-transform',\n\t\t// Focus states for keyboard navigation\n\t\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/30 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent',\n\t\t// Base glass styling (overridden by mode-specific classes)\n\t\tmode === 'collapsed' && 'glass-pill-collapsed',\n\t\tmode === 'hovered' && 'glass-pill-hovered',\n\t\t(mode === 'composing' || mode === 'expanded') && 'glass-pill',\n\t\tmode === 'active' && 'glass-pill glass-active',\n\t\tclassName\n\t)\n\n\t// Use reduced motion transition when user prefers it\n\t// Use smooth tween for full-screen transitions (spring is too aggressive for large viewport changes)\n\tconst transition = prefersReducedMotion\n\t\t? reducedMotionTransition\n\t\t: isTransitioningFullScreen || isFullScreen\n\t\t\t? fullScreenTween\n\t\t\t: sizeSpring\n\n\treturn (\n\t\t<motion.div\n\t\t\tref={setContainerRef}\n\t\t\tclassName={glassClassName}\n\t\t\tinitial={false}\n\t\t\tanimate={{\n\t\t\t\twidth: currentVariant.width,\n\t\t\t\theight: currentVariant.height,\n\t\t\t\tpadding: currentVariant.padding,\n\t\t\t\tborderRadius: currentVariant.borderRadius,\n\t\t\t}}\n\t\t\ttransition={transition}\n\t\t\tonMouseEnter={handleMouseEnter}\n\t\t\tonMouseLeave={handleMouseLeave}\n\t\t\tonClick={handleClick}\n\t\t\tonFocus={handleFocus}\n\t\t\tonBlur={handleBlur}\n\t\t\t// Button mode: collapsed/hovered - acts as a button to open\n\t\t\trole={isDialogMode ? 'dialog' : 'button'}\n\t\t\ttabIndex={isDialogMode ? -1 : 0}\n\t\t\t// Dialog mode: composing/active/expanded - acts as a modal dialog\n\t\t\taria-modal={isDialogMode ? true : undefined}\n\t\t\taria-labelledby={isDialogMode ? ARIA_IDS.pillTitle : undefined}\n\t\t\taria-label={!isDialogMode ? ARIA_LABELS.openAssistant : undefined}\n\t\t>\n\t\t\t{/* Collapsed state - glass shimmer highlight */}\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{mode === 'collapsed' && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tkey=\"collapsed-bar\"\n\t\t\t\t\t\tclassName=\"absolute inset-0\"\n\t\t\t\t\t\tvariants={barVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\tanimate={isHovered ? 'hover' : 'idle'}\n\t\t\t\t\t\texit={{ opacity: 0, transition: { duration: 0.1 } }}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: 'linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent)',\n\t\t\t\t\t\t\tbackgroundSize: '200% 100%',\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Hovered state - hint text */}\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{mode === 'hovered' && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tkey=\"hover-hint\"\n\t\t\t\t\t\tclassName=\"relative z-10 flex h-full w-full items-center justify-center\"\n\t\t\t\t\t\tvariants={hintVariants}\n\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\texit=\"exit\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<span className=\"text-xs text-white/70\">\n\t\t\t\t\t\t\tClick or{' '}\n\t\t\t\t\t\t\t<kbd className=\"rounded bg-white/10 px-1.5 py-0.5 font-mono text-[10px]\">⌘⇧K</kbd>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Expanded content - z-10 ensures content sits above glass highlight overlays */}\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{showContent && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tkey=\"content\"\n\t\t\t\t\t\tclassName=\"relative z-10 flex flex-col gap-1.5\"\n\t\t\t\t\t\tvariants={contentVariants}\n\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\texit=\"exit\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{/* Visually hidden title for screen readers (referenced by aria-labelledby) */}\n\t\t\t\t\t\t<span id={ARIA_IDS.pillTitle} className=\"sr-only\">\n\t\t\t\t\t\t\tAI Assistant\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\t\t</motion.div>\n\t)\n}\n","import { Slot } from '@radix-ui/react-slot'\nimport { cva } from 'class-variance-authority'\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nimport type { VariantProps } from 'class-variance-authority'\n\nexport interface ButtonProps\n\textends React.ComponentProps<'button'>,\n\t\tVariantProps<typeof buttonVariants> {\n\tasChild?: boolean\n}\n\nconst buttonVariants = cva(\n\t\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\",\n\t{\n\t\tvariants: {\n\t\t\tvariant: {\n\t\t\t\tdefault: 'bg-primary text-primary-foreground hover:bg-primary/90',\n\t\t\t\tdestructive:\n\t\t\t\t\t'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n\t\t\t\toutline:\n\t\t\t\t\t'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n\t\t\t\tsecondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n\t\t\t\tghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n\t\t\t\tlink: 'text-primary underline-offset-4 hover:underline',\n\t\t\t},\n\t\t\tsize: {\n\t\t\t\tdefault: 'h-9 px-4 py-2 has-[>svg]:px-3',\n\t\t\t\tsm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',\n\t\t\t\tlg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n\t\t\t\ticon: 'size-9',\n\t\t\t\t'icon-sm': 'size-8',\n\t\t\t\t'icon-lg': 'size-10',\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tvariant: 'default',\n\t\t\tsize: 'default',\n\t\t},\n\t}\n)\n\nfunction Button({\n\tclassName,\n\tvariant,\n\tsize,\n\tasChild = false,\n\t...props\n}: React.ComponentProps<'button'> &\n\tVariantProps<typeof buttonVariants> & {\n\t\tasChild?: boolean\n\t}) {\n\tconst Comp = asChild ? Slot : 'button'\n\n\treturn (\n\t\t<Comp\n\t\t\tdata-slot=\"button\"\n\t\t\tclassName={cn(buttonVariants({ variant, size, className }))}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Button, buttonVariants }\n","/**\n * UnifiedToolFallback Component\n *\n * A unified fallback component that handles ALL tool call states:\n * - Running: Shows activity indicator with tool name\n * - Pending approval: Shows approval dialog for destructive tools\n * - Completed: Shows success indicator with collapsible args/result\n * - Error: Shows error state\n *\n * This provides an alternative to separate ActionList/CurrentActivity components\n * by rendering tool states directly in the message thread.\n */\n'use client'\n\nimport { AlertCircle, AlertTriangle, Check, ChevronDownIcon, ChevronUpIcon, X } from 'lucide-react'\nimport { useCallback, useState } from 'react'\n\nimport { formatArgs, humanizeToolName, TOOL_DENIED_MESSAGE } from '../lib/format'\nimport { cn } from '../lib/utils'\nimport { useMCPTools } from '../providers/MCPToolsProvider'\nimport { Button } from './button'\nimport { formatToolResult } from './MCPToolRegistry'\nimport { getToolIcon } from './pill/ActivityIndicator'\n\nimport type { ToolCallMessagePartComponent } from '@assistant-ui/react'\n\n// ============================================================================\n// Approval Result Types\n// ============================================================================\n\ninterface ApprovedResult {\n\tapproved: true\n\tresult: string\n}\n\nfunction isApprovedResult(result: unknown): result is ApprovedResult {\n\treturn (\n\t\ttypeof result === 'object' &&\n\t\tresult !== null &&\n\t\t'approved' in result &&\n\t\t(result as ApprovedResult).approved === true &&\n\t\t'result' in result\n\t)\n}\n\n/**\n * Check if result indicates a denied tool execution.\n * Handles both string format (legacy) and structured format.\n */\nfunction isDeniedResult(result: unknown): boolean {\n\t// Check for string denial message\n\tif (typeof result === 'string' && result === TOOL_DENIED_MESSAGE) {\n\t\treturn true\n\t}\n\t// Check for structured denial (future-proofing)\n\tif (\n\t\ttypeof result === 'object' &&\n\t\tresult !== null &&\n\t\t'approved' in result &&\n\t\t(result as { approved: boolean }).approved === false\n\t) {\n\t\treturn true\n\t}\n\treturn false\n}\n\n/**\n * Type guard for status with error property\n */\nfunction hasStatusError(status: { type: string }): status is { type: string; error: string } {\n\treturn 'error' in status && typeof (status as { error?: unknown }).error === 'string'\n}\n\n// ============================================================================\n// Sub-Components for Each State\n// ============================================================================\n\n/**\n * Running state - tool is currently executing\n */\nconst RunningToolDisplay: React.FC<{\n\ttoolName: string\n}> = ({ toolName }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-white/5 px-2 py-1.5 text-sm text-white/70\">\n\t\t\t<ToolIcon className=\"h-3.5 w-3.5 animate-pulse text-white/50\" />\n\t\t\t<span>\n\t\t\t\t<strong className=\"text-white/90\">{humanizeToolName(toolName)}</strong>\n\t\t\t</span>\n\t\t</div>\n\t)\n}\n\n/**\n * Approval dialog for destructive tools (HITL pattern)\n * Used when a tool has no execute function and requires user approval.\n */\nconst ApprovalDialog: React.FC<{\n\ttoolName: string\n\ttoolDescription?: string\n\tinputArgs: Record<string, unknown>\n\tonApprove: () => void\n\tonDeny: () => void\n\tisExecuting: boolean\n}> = ({ toolName, toolDescription, inputArgs, onApprove, onDeny, isExecuting }) => {\n\tconst [isHovered, setIsHovered] = useState<'approve' | 'deny' | null>(null)\n\tconst ToolIcon = getToolIcon(toolName)\n\n\tif (isExecuting) {\n\t\treturn (\n\t\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-white/5 px-2 py-1.5 text-sm text-white/70\">\n\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 animate-pulse text-white/50\" />\n\t\t\t\t<span>\n\t\t\t\t\t<strong className=\"text-white/90\">{humanizeToolName(toolName)}</strong>\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div className={cn('my-1 overflow-hidden rounded-lg', 'bg-white/5')}>\n\t\t\t{/* Header - compact */}\n\t\t\t<div className=\"flex items-center gap-1.5 px-2 py-1.5 border-b border-white/5\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/70\" />\n\t\t\t\t\t<AlertTriangle className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/70\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"text-xs font-medium text-white/90\">{humanizeToolName(toolName)}</span>\n\t\t\t</div>\n\n\t\t\t{/* Content */}\n\t\t\t<div className=\"px-2 py-2\">\n\t\t\t\t{toolDescription && <div className=\"mb-2 text-xs text-white/50\">{toolDescription}</div>}\n\n\t\t\t\t{/* Arguments - compact */}\n\t\t\t\t{inputArgs && Object.keys(inputArgs).length > 0 && (\n\t\t\t\t\t<div className=\"mb-2 rounded bg-white/5 p-1.5\">\n\t\t\t\t\t\t<pre className=\"whitespace-pre-wrap text-[11px] text-white/60\">\n\t\t\t\t\t\t\t{formatArgs(inputArgs)}\n\t\t\t\t\t\t</pre>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Action buttons - compact */}\n\t\t\t\t<div className=\"flex justify-end gap-1.5\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onDeny}\n\t\t\t\t\t\tonMouseEnter={() => setIsHovered('deny')}\n\t\t\t\t\t\tonMouseLeave={() => setIsHovered(null)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex items-center gap-1 rounded px-2.5 py-1.5 text-xs font-medium sm:px-2 sm:py-1',\n\t\t\t\t\t\t\t'border border-white/10 text-white/60',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisHovered === 'deny' ? 'bg-white/10 text-white/80' : 'hover:bg-white/5'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<X className=\"h-3.5 w-3.5 sm:h-3 sm:w-3\" />\n\t\t\t\t\t\tDeny\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onApprove}\n\t\t\t\t\t\tonMouseEnter={() => setIsHovered('approve')}\n\t\t\t\t\t\tonMouseLeave={() => setIsHovered(null)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex items-center gap-1 rounded px-2.5 py-1.5 text-xs font-medium sm:px-2 sm:py-1',\n\t\t\t\t\t\t\t'bg-white/90 text-slate-900',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisHovered === 'approve' ? 'bg-white' : 'hover:bg-white/95'\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Check className=\"h-3.5 w-3.5 sm:h-3 sm:w-3\" />\n\t\t\t\t\t\tOK\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/**\n * Completed tool display - success state with collapsible details\n */\nconst CompletedToolDisplay: React.FC<{\n\ttoolName: string\n\targsText: string\n\tresult: unknown\n}> = ({ toolName, argsText, result }) => {\n\tconst [isExpanded, setIsExpanded] = useState(false)\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-white/5\">\n\t\t\t{/* Header - compact */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setIsExpanded(!isExpanded)}\n\t\t\t\tclassName=\"flex w-full items-center gap-1.5 px-2 py-1.5 text-left transition-colors hover:bg-white/5\"\n\t\t\t>\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/50\" />\n\t\t\t\t\t<Check className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/50\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"flex-grow text-xs font-medium text-white/80\">\n\t\t\t\t\t{humanizeToolName(toolName)}\n\t\t\t\t</span>\n\t\t\t\t<Button variant=\"ghost\" size=\"sm\" className=\"h-5 w-5 p-0\" asChild>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t{isExpanded ? (\n\t\t\t\t\t\t\t<ChevronUpIcon className=\"h-3 w-3 text-white/40\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<ChevronDownIcon className=\"h-3 w-3 text-white/40\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t</Button>\n\t\t\t</button>\n\n\t\t\t{/* Expandable content */}\n\t\t\t{isExpanded && (\n\t\t\t\t<div className=\"border-t border-white/5 px-2 py-1.5\">\n\t\t\t\t\t{/* Input args */}\n\t\t\t\t\t{argsText && (\n\t\t\t\t\t\t<div className=\"mb-1.5\">\n\t\t\t\t\t\t\t<div className=\"mb-0.5 text-[10px] font-medium uppercase tracking-wide text-white/40\">\n\t\t\t\t\t\t\t\tInput\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<pre className=\"max-h-24 overflow-auto whitespace-pre-wrap rounded bg-white/5 p-1.5 font-mono text-[11px] text-white/60\">\n\t\t\t\t\t\t\t\t{argsText}\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Output result */}\n\t\t\t\t\t{result !== undefined && (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div className=\"mb-0.5 text-[10px] font-medium uppercase tracking-wide text-white/40\">\n\t\t\t\t\t\t\t\tOutput\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<pre className=\"max-h-32 overflow-auto whitespace-pre-wrap rounded bg-white/5 p-1.5 font-mono text-[11px] text-white/60\">\n\t\t\t\t\t\t\t\t{typeof result === 'string' ? result : JSON.stringify(result, null, 2)}\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/**\n * Error state display\n */\nconst ErrorToolDisplay: React.FC<{\n\ttoolName: string\n\terror?: string\n}> = ({ toolName, error }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-white/5\">\n\t\t\t<div className=\"flex items-center gap-1.5 px-2 py-1.5\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/50\" />\n\t\t\t\t\t<AlertCircle className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/50\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"text-xs font-medium text-white/70\">\n\t\t\t\t\t{humanizeToolName(toolName)} failed\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t{error && (\n\t\t\t\t<div className=\"border-t border-white/5 px-2 py-1.5\">\n\t\t\t\t\t<pre className=\"whitespace-pre-wrap font-mono text-[11px] text-white/50\">{error}</pre>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\n/**\n * Denied approval display\n */\nconst DeniedToolDisplay: React.FC<{\n\ttoolName: string\n}> = ({ toolName }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-white/5 px-2 py-1.5 text-xs text-white/60\">\n\t\t\t<div className=\"relative\">\n\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-white/40\" />\n\t\t\t\t<X className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-white/40\" />\n\t\t\t</div>\n\t\t\t<span>\n\t\t\t\t<strong className=\"text-white/70\">{humanizeToolName(toolName)}</strong> denied\n\t\t\t</span>\n\t\t</div>\n\t)\n}\n\n// ============================================================================\n// Main Unified Fallback Component\n// ============================================================================\n\n/**\n * Unified fallback component that handles all tool call states.\n * This is the single source of truth for tool rendering in the thread.\n *\n * HITL Pattern: For tools without an execute function (destructive tools),\n * the model pauses and waits for addResult() to be called. This component\n * shows an approval dialog and handles the execution on user approval.\n */\nexport const UnifiedToolFallback: ToolCallMessagePartComponent = ({\n\ttoolCallId: _toolCallId,\n\ttoolName,\n\targsText,\n\targs,\n\tstatus,\n\tresult,\n\taddResult,\n}) => {\n\tconst { callTool, tools } = useMCPTools()\n\tconst [isExecuting, setIsExecuting] = useState(false)\n\n\t// Parse args - use args prop if available, otherwise parse from argsText\n\tconst parsedArgs: Record<string, unknown> =\n\t\targs ??\n\t\t(() => {\n\t\t\ttry {\n\t\t\t\treturn argsText ? JSON.parse(argsText) : {}\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn(`[UnifiedToolFallback] Failed to parse args for tool \"${toolName}\":`, e)\n\t\t\t\treturn {}\n\t\t\t}\n\t\t})()\n\n\t// Get tool description from registered tools\n\tconst toolDescription = tools.find((t) => t.name === toolName)?.description\n\n\t// Handle approval - execute the tool and add result\n\tconst handleApprove = useCallback(async () => {\n\t\tsetIsExecuting(true)\n\t\ttry {\n\t\t\tconst toolResult = await callTool(toolName, parsedArgs)\n\t\t\taddResult(formatToolResult(toolResult))\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\t\t\taddResult(`Error: ${errorMessage}`)\n\t\t} finally {\n\t\t\tsetIsExecuting(false)\n\t\t}\n\t}, [toolName, parsedArgs, callTool, addResult])\n\n\t// Handle denial - add denial result using shared constant\n\tconst handleDeny = useCallback(() => {\n\t\taddResult(TOOL_DENIED_MESSAGE)\n\t}, [addResult])\n\n\t// Determine the current state and render accordingly\n\tconst statusType = status.type\n\n\t// Check if this is a pending approval\n\tconst isPendingApproval = statusType === 'requires-action' && result === undefined\n\n\t// Case 1: HITL - Tool requires action (no execute function, waiting for approval)\n\t// This is the key case for destructive tools!\n\tif (isPendingApproval) {\n\t\treturn (\n\t\t\t<ApprovalDialog\n\t\t\t\ttoolName={toolName}\n\t\t\t\ttoolDescription={toolDescription}\n\t\t\t\tinputArgs={parsedArgs}\n\t\t\t\tonApprove={handleApprove}\n\t\t\t\tonDeny={handleDeny}\n\t\t\t\tisExecuting={isExecuting}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Case 2: Tool was denied (result contains denial message)\n\tif (isDeniedResult(result)) {\n\t\treturn <DeniedToolDisplay toolName={toolName} />\n\t}\n\n\t// Case 3: Tool is currently running (has execute function)\n\tif (statusType === 'running') {\n\t\treturn <RunningToolDisplay toolName={toolName} />\n\t}\n\n\t// Case 4: Tool completed with error\n\tif (statusType === 'incomplete' || hasStatusError(status)) {\n\t\tconst errorMessage = hasStatusError(status) ? status.error : 'Tool execution failed'\n\t\treturn <ErrorToolDisplay toolName={toolName} error={errorMessage} />\n\t}\n\n\t// Case 5: Tool completed successfully\n\tif (statusType === 'complete') {\n\t\t// If it's an approved result object, show the actual result\n\t\tconst displayResult = isApprovedResult(result) ? result.result : result\n\n\t\treturn <CompletedToolDisplay toolName={toolName} argsText={argsText} result={displayResult} />\n\t}\n\n\t// Fallback - shouldn't reach here normally\n\treturn null\n}\n\nexport default UnifiedToolFallback\n","/**\n * PillMessageContent Component\n *\n * Renders assistant message content (tool calls) using assistant-ui primitives.\n * Uses UnifiedToolFallback to render ALL tool states directly in the thread:\n * - Running tools with activity indicator\n * - Pending approval dialogs for destructive tools\n * - Completed tools with collapsible args/result\n * - Error states\n *\n * This provides an alternative to separate ActionList/CurrentActivity components\n * by rendering tool state directly in the conversation flow.\n */\n'use client'\n\nimport { MessagePrimitive, ThreadPrimitive } from '@assistant-ui/react'\n\nimport { UnifiedToolFallback } from '../UnifiedToolFallback'\n\nimport type { FC } from 'react'\n\n/**\n * Renders the thread messages with tool UIs.\n * Uses UnifiedToolFallback to handle all tool call states.\n */\nexport const PillMessageContent: FC = () => {\n\treturn (\n\t\t<ThreadPrimitive.Messages\n\t\t\tcomponents={{\n\t\t\t\t// Skip user messages in pill - we only want tool UIs from assistant\n\t\t\t\tUserMessage: () => null,\n\t\t\t\tAssistantMessage: PillAssistantMessage,\n\t\t\t}}\n\t\t/>\n\t)\n}\n\n/**\n * Assistant message renderer for the pill.\n * Renders tool calls via UnifiedToolFallback.\n * Text content is skipped here (handled by SummaryBlock).\n */\nconst PillAssistantMessage: FC = () => {\n\treturn (\n\t\t<MessagePrimitive.Root>\n\t\t\t<MessagePrimitive.Parts\n\t\t\t\tcomponents={{\n\t\t\t\t\t// Text is handled by SummaryBlock, so we skip it here\n\t\t\t\t\tText: () => null,\n\t\t\t\t\t// UnifiedToolFallback handles ALL tool states:\n\t\t\t\t\t// - Running: activity indicator\n\t\t\t\t\t// - Pending approval: approval dialog\n\t\t\t\t\t// - Completed: success with collapsible details\n\t\t\t\t\t// - Error: error display\n\t\t\t\t\t// - Denied: denied indicator\n\t\t\t\t\ttools: { Fallback: UnifiedToolFallback },\n\t\t\t\t}}\n\t\t\t/>\n\t\t</MessagePrimitive.Root>\n\t)\n}\n","/**\n * PillToolsSection Component\n *\n * A collapsible, scrollable container for tool UIs in the pill.\n * Shows a header with action count that expands/collapses the tool list.\n * Contains PillMessageContent which renders tools via UnifiedToolFallback.\n *\n * Auto-expands when a tool requires approval (HITL pattern).\n */\n'use client'\n\nimport { AlertTriangle, ChevronDown } from 'lucide-react'\nimport { useEffect, useState } from 'react'\n\nimport { useActions } from '../../hooks/useActions'\nimport { cn } from '../../lib/utils'\nimport { PillMessageContent } from './PillMessageContent'\n\nimport type { FC } from 'react'\n\nexport interface PillToolsSectionProps {\n\t/** Start collapsed (default: true) */\n\tdefaultCollapsed?: boolean\n\t/** Additional class name */\n\tclassName?: string\n\t/** Full-screen mode - larger height, starts expanded */\n\tisFullScreen?: boolean\n}\n\n/**\n * Collapsible section containing all tool UIs.\n * Shows \"Actions (completed/total)\" header with expand/collapse toggle.\n * Tool cards render in a scrollable container.\n *\n * Auto-expands when approval is needed for a destructive tool.\n */\nexport const PillToolsSection: FC<PillToolsSectionProps> = ({\n\tdefaultCollapsed = false,\n\tclassName,\n\tisFullScreen = false,\n}) => {\n\t// Start expanded in full-screen mode\n\tconst [isCollapsed, setIsCollapsed] = useState(isFullScreen ? false : defaultCollapsed)\n\tconst actions = useActions()\n\n\t// Count different statuses\n\tconst completedCount = actions.filter((a) => a.status === 'success').length\n\tconst runningCount = actions.filter((a) => a.status === 'running').length\n\tconst pendingCount = actions.filter((a) => a.status === 'pending').length\n\tconst totalCount = actions.length\n\n\t// Auto-expand when approval is needed\n\tuseEffect(() => {\n\t\tif (pendingCount > 0 && isCollapsed) {\n\t\t\tsetIsCollapsed(false)\n\t\t}\n\t}, [pendingCount, isCollapsed])\n\n\t// Don't render if no actions\n\tif (actions.length === 0) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<div className={cn('mt-1.5', className)}>\n\t\t\t{/* Header - compact, no background card */}\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={() => setIsCollapsed(!isCollapsed)}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex w-full items-center justify-between',\n\t\t\t\t\t'px-1 py-1',\n\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t'hover:bg-white/5 rounded'\n\t\t\t\t)}\n\t\t\t\taria-expanded={!isCollapsed}\n\t\t\t>\n\t\t\t\t<div className=\"flex items-center gap-1.5\">\n\t\t\t\t\t<span className=\"text-xs font-medium text-white/70\">Tools</span>\n\t\t\t\t\t<span className=\"text-[11px] text-white/40\">\n\t\t\t\t\t\t{completedCount}/{totalCount}\n\t\t\t\t\t</span>\n\t\t\t\t\t{/* Pending approval indicator */}\n\t\t\t\t\t{pendingCount > 0 && (\n\t\t\t\t\t\t<span className=\"flex items-center gap-1 text-[11px] font-medium text-white/90\">\n\t\t\t\t\t\t\t<AlertTriangle className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t{pendingCount}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t\t{/* Running indicator */}\n\t\t\t\t\t{runningCount > 0 && (\n\t\t\t\t\t\t<span className=\"flex items-center gap-1 text-[11px] text-white/60\">\n\t\t\t\t\t\t\t<span className=\"h-1.5 w-1.5 animate-pulse rounded-full bg-white/60\" />\n\t\t\t\t\t\t\t{runningCount}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<ChevronDown\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'h-3.5 w-3.5 transition-transform duration-200 text-white/40',\n\t\t\t\t\t\t!isCollapsed && 'rotate-180'\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</button>\n\n\t\t\t{/* Expandable content */}\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'grid transition-[grid-template-rows] duration-300 ease-out',\n\t\t\t\t\tisCollapsed ? 'grid-rows-[0fr]' : 'grid-rows-[1fr]'\n\t\t\t\t)}\n\t\t\t\taria-hidden={isCollapsed}\n\t\t\t>\n\t\t\t\t<div className=\"overflow-hidden\">\n\t\t\t\t\t{/* Scrollable tool cards - larger height in full-screen mode */}\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'mt-1 overflow-y-auto scrollbar-thin scroll-touch',\n\t\t\t\t\t\t\tisFullScreen ? 'max-h-[30vh]' : 'max-h-40 sm:max-h-32'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ touchAction: 'pan-y' }}\n\t\t\t\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t\t\t>\n\t\t\t\t\t\t<PillMessageContent />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default PillToolsSection\n","import { useEffect, useRef } from 'react'\n\nimport { cn } from '../lib/utils'\n\nimport type { HTMLAttributes } from 'react'\n\nexport type LiveWaveformProps = HTMLAttributes<HTMLDivElement> & {\n\tactive?: boolean\n\tprocessing?: boolean\n\tbarWidth?: number\n\tbarGap?: number\n\tbarRadius?: number\n\tbarColor?: string\n\tfadeEdges?: boolean\n\tfadeWidth?: number\n\theight?: string | number\n\tsensitivity?: number\n\tsmoothingTimeConstant?: number\n\tmode?: 'scrolling' | 'static'\n\t/** Manual audio level (0-1) instead of using microphone */\n\tmanualAudioLevel?: number\n}\n\nexport const LiveWaveform = ({\n\tactive = false,\n\tprocessing = false,\n\tbarWidth = 3,\n\tbarGap = 1,\n\tbarRadius = 1.5,\n\tbarColor,\n\tfadeEdges = true,\n\tfadeWidth = 24,\n\theight = 64,\n\tsensitivity = 1,\n\tmode = 'static',\n\tmanualAudioLevel,\n\tclassName,\n\t...props\n}: LiveWaveformProps) => {\n\tconst canvasRef = useRef<HTMLCanvasElement>(null)\n\tconst containerRef = useRef<HTMLDivElement>(null)\n\tconst historyRef = useRef<number[]>([])\n\tconst _animationRef = useRef<number>(0)\n\tconst lastUpdateRef = useRef<number>(0)\n\tconst processingAnimationRef = useRef<number | null>(null)\n\tconst lastActiveDataRef = useRef<number[]>([])\n\tconst transitionProgressRef = useRef(0)\n\tconst staticBarsRef = useRef<number[]>([])\n\tconst needsRedrawRef = useRef(true)\n\tconst gradientCacheRef = useRef<CanvasGradient | null>(null)\n\tconst lastWidthRef = useRef(0)\n\n\tconst heightStyle = typeof height === 'number' ? `${height}px` : height\n\tconst historySize = 60\n\tconst updateRate = 30\n\n\t// Handle canvas resizing\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current\n\t\tconst container = containerRef.current\n\t\tif (!canvas || !container) return\n\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\tconst dpr = window.devicePixelRatio || 1\n\n\t\t\tcanvas.width = rect.width * dpr\n\t\t\tcanvas.height = rect.height * dpr\n\t\t\tcanvas.style.width = `${rect.width}px`\n\t\t\tcanvas.style.height = `${rect.height}px`\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (ctx) {\n\t\t\t\tctx.scale(dpr, dpr)\n\t\t\t}\n\n\t\t\tgradientCacheRef.current = null\n\t\t\tlastWidthRef.current = rect.width\n\t\t\tneedsRedrawRef.current = true\n\t\t})\n\n\t\tresizeObserver.observe(container)\n\t\treturn () => resizeObserver.disconnect()\n\t}, [])\n\n\t// Processing animation effect\n\tuseEffect(() => {\n\t\tif (processing && !active) {\n\t\t\tlet time = 0\n\t\t\ttransitionProgressRef.current = 0\n\n\t\t\tconst animateProcessing = () => {\n\t\t\t\ttime += 0.03\n\t\t\t\ttransitionProgressRef.current = Math.min(1, transitionProgressRef.current + 0.02)\n\n\t\t\t\tconst processingData: number[] = []\n\t\t\t\tconst barCount = Math.floor(\n\t\t\t\t\t(containerRef.current?.getBoundingClientRect().width || 200) / (barWidth + barGap)\n\t\t\t\t)\n\n\t\t\t\tif (mode === 'static') {\n\t\t\t\t\tconst halfCount = Math.floor(barCount / 2)\n\n\t\t\t\t\tfor (let i = 0; i < barCount; i++) {\n\t\t\t\t\t\tconst normalizedPosition = (i - halfCount) / halfCount\n\t\t\t\t\t\tconst centerWeight = 1 - Math.abs(normalizedPosition) * 0.4\n\n\t\t\t\t\t\tconst wave1 = Math.sin(time * 1.5 + normalizedPosition * 3) * 0.25\n\t\t\t\t\t\tconst wave2 = Math.sin(time * 0.8 - normalizedPosition * 2) * 0.2\n\t\t\t\t\t\tconst wave3 = Math.cos(time * 2 + normalizedPosition) * 0.15\n\t\t\t\t\t\tconst combinedWave = wave1 + wave2 + wave3\n\t\t\t\t\t\tconst processingValue = (0.2 + combinedWave) * centerWeight\n\n\t\t\t\t\t\tlet finalValue = processingValue\n\t\t\t\t\t\tif (lastActiveDataRef.current.length > 0 && transitionProgressRef.current < 1) {\n\t\t\t\t\t\t\tconst lastDataIndex = Math.min(i, lastActiveDataRef.current.length - 1)\n\t\t\t\t\t\t\tconst lastValue = lastActiveDataRef.current[lastDataIndex] || 0\n\t\t\t\t\t\t\tfinalValue =\n\t\t\t\t\t\t\t\tlastValue * (1 - transitionProgressRef.current) +\n\t\t\t\t\t\t\t\tprocessingValue * transitionProgressRef.current\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprocessingData.push(Math.max(0.05, Math.min(1, finalValue)))\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = 0; i < barCount; i++) {\n\t\t\t\t\t\tconst normalizedPosition = (i - barCount / 2) / (barCount / 2)\n\t\t\t\t\t\tconst centerWeight = 1 - Math.abs(normalizedPosition) * 0.4\n\n\t\t\t\t\t\tconst wave1 = Math.sin(time * 1.5 + i * 0.15) * 0.25\n\t\t\t\t\t\tconst wave2 = Math.sin(time * 0.8 - i * 0.1) * 0.2\n\t\t\t\t\t\tconst wave3 = Math.cos(time * 2 + i * 0.05) * 0.15\n\t\t\t\t\t\tconst combinedWave = wave1 + wave2 + wave3\n\t\t\t\t\t\tconst processingValue = (0.2 + combinedWave) * centerWeight\n\n\t\t\t\t\t\tlet finalValue = processingValue\n\t\t\t\t\t\tif (lastActiveDataRef.current.length > 0 && transitionProgressRef.current < 1) {\n\t\t\t\t\t\t\tconst lastDataIndex = Math.floor((i / barCount) * lastActiveDataRef.current.length)\n\t\t\t\t\t\t\tconst lastValue = lastActiveDataRef.current[lastDataIndex] || 0\n\t\t\t\t\t\t\tfinalValue =\n\t\t\t\t\t\t\t\tlastValue * (1 - transitionProgressRef.current) +\n\t\t\t\t\t\t\t\tprocessingValue * transitionProgressRef.current\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprocessingData.push(Math.max(0.05, Math.min(1, finalValue)))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (mode === 'static') {\n\t\t\t\t\tstaticBarsRef.current = processingData\n\t\t\t\t} else {\n\t\t\t\t\thistoryRef.current = processingData\n\t\t\t\t}\n\n\t\t\t\tneedsRedrawRef.current = true\n\t\t\t\tprocessingAnimationRef.current = requestAnimationFrame(animateProcessing)\n\t\t\t}\n\n\t\t\tanimateProcessing()\n\n\t\t\treturn () => {\n\t\t\t\tif (processingAnimationRef.current) {\n\t\t\t\t\tcancelAnimationFrame(processingAnimationRef.current)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!active && !processing) {\n\t\t\tconst hasData =\n\t\t\t\tmode === 'static' ? staticBarsRef.current.length > 0 : historyRef.current.length > 0\n\n\t\t\tif (hasData) {\n\t\t\t\tlet fadeProgress = 0\n\t\t\t\tconst fadeToIdle = () => {\n\t\t\t\t\tfadeProgress += 0.03\n\t\t\t\t\tif (fadeProgress < 1) {\n\t\t\t\t\t\tif (mode === 'static') {\n\t\t\t\t\t\t\tstaticBarsRef.current = staticBarsRef.current.map(\n\t\t\t\t\t\t\t\t(value) => value * (1 - fadeProgress)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thistoryRef.current = historyRef.current.map((value) => value * (1 - fadeProgress))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tneedsRedrawRef.current = true\n\t\t\t\t\t\trequestAnimationFrame(fadeToIdle)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (mode === 'static') {\n\t\t\t\t\t\t\tstaticBarsRef.current = []\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thistoryRef.current = []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfadeToIdle()\n\t\t\t}\n\t\t}\n\t}, [processing, active, barWidth, barGap, mode])\n\n\t// Animation loop\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current\n\t\tif (!canvas) return\n\n\t\tconst ctx = canvas.getContext('2d')\n\t\tif (!ctx) return\n\n\t\tlet rafId: number\n\n\t\tconst animate = (currentTime: number) => {\n\t\t\tconst rect = canvas.getBoundingClientRect()\n\n\t\t\t// Update audio data if active\n\t\t\tif (active && currentTime - lastUpdateRef.current > updateRate) {\n\t\t\t\tlastUpdateRef.current = currentTime\n\n\t\t\t\t// Use manual audio level if provided\n\t\t\t\tif (manualAudioLevel !== undefined) {\n\t\t\t\t\tconst level = Math.max(0.05, Math.min(1, manualAudioLevel * sensitivity))\n\n\t\t\t\t\tif (mode === 'static') {\n\t\t\t\t\t\tconst barCount = Math.floor(rect.width / (barWidth + barGap))\n\t\t\t\t\t\tconst halfCount = Math.floor(barCount / 2)\n\t\t\t\t\t\tconst newBars: number[] = []\n\n\t\t\t\t\t\t// Create symmetric bars based on manual level\n\t\t\t\t\t\tfor (let i = halfCount - 1; i >= 0; i--) {\n\t\t\t\t\t\t\tconst distanceFromCenter = Math.abs(i - halfCount / 2) / (halfCount / 2)\n\t\t\t\t\t\t\tconst value = level * (1 - distanceFromCenter * 0.3)\n\t\t\t\t\t\t\tnewBars.push(Math.max(0.05, value))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (let i = 0; i < halfCount; i++) {\n\t\t\t\t\t\t\tconst distanceFromCenter = Math.abs(i - halfCount / 2) / (halfCount / 2)\n\t\t\t\t\t\t\tconst value = level * (1 - distanceFromCenter * 0.3)\n\t\t\t\t\t\t\tnewBars.push(Math.max(0.05, value))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstaticBarsRef.current = newBars\n\t\t\t\t\t\tlastActiveDataRef.current = newBars\n\t\t\t\t\t} else {\n\t\t\t\t\t\thistoryRef.current.push(level)\n\t\t\t\t\t\tlastActiveDataRef.current = [...historyRef.current]\n\n\t\t\t\t\t\tif (historyRef.current.length > historySize) {\n\t\t\t\t\t\t\thistoryRef.current.shift()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tneedsRedrawRef.current = true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Only redraw if needed\n\t\t\tif (!needsRedrawRef.current && !active) {\n\t\t\t\trafId = requestAnimationFrame(animate)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tneedsRedrawRef.current = active\n\t\t\tctx.clearRect(0, 0, rect.width, rect.height)\n\n\t\t\tconst computedBarColor =\n\t\t\t\tbarColor ||\n\t\t\t\t(() => {\n\t\t\t\t\tconst style = getComputedStyle(canvas)\n\t\t\t\t\tconst color = style.color\n\t\t\t\t\treturn color || '#000'\n\t\t\t\t})()\n\n\t\t\tconst step = barWidth + barGap\n\t\t\tconst barCount = Math.floor(rect.width / step)\n\t\t\tconst centerY = rect.height / 2\n\n\t\t\t// Draw bars based on mode\n\t\t\tif (mode === 'static') {\n\t\t\t\tconst dataToRender = processing\n\t\t\t\t\t? staticBarsRef.current\n\t\t\t\t\t: active\n\t\t\t\t\t\t? staticBarsRef.current\n\t\t\t\t\t\t: staticBarsRef.current.length > 0\n\t\t\t\t\t\t\t? staticBarsRef.current\n\t\t\t\t\t\t\t: []\n\n\t\t\t\tfor (let i = 0; i < barCount && i < dataToRender.length; i++) {\n\t\t\t\t\tconst value = dataToRender[i] || 0.1\n\t\t\t\t\tconst x = i * step\n\t\t\t\t\tconst barHeight = Math.max(4, value * rect.height * 0.8)\n\t\t\t\t\tconst y = centerY - barHeight / 2\n\n\t\t\t\t\tctx.fillStyle = computedBarColor\n\t\t\t\t\tctx.globalAlpha = 0.4 + value * 0.6\n\n\t\t\t\t\tif (barRadius > 0) {\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.roundRect(x, y, barWidth, barHeight, barRadius)\n\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.fillRect(x, y, barWidth, barHeight)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Scrolling mode\n\t\t\t\tfor (let i = 0; i < barCount && i < historyRef.current.length; i++) {\n\t\t\t\t\tconst dataIndex = historyRef.current.length - 1 - i\n\t\t\t\t\tconst value = historyRef.current[dataIndex] || 0.1\n\t\t\t\t\tconst x = rect.width - (i + 1) * step\n\t\t\t\t\tconst barHeight = Math.max(4, value * rect.height * 0.8)\n\t\t\t\t\tconst y = centerY - barHeight / 2\n\n\t\t\t\t\tctx.fillStyle = computedBarColor\n\t\t\t\t\tctx.globalAlpha = 0.4 + value * 0.6\n\n\t\t\t\t\tif (barRadius > 0) {\n\t\t\t\t\t\tctx.beginPath()\n\t\t\t\t\t\tctx.roundRect(x, y, barWidth, barHeight, barRadius)\n\t\t\t\t\t\tctx.fill()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tctx.fillRect(x, y, barWidth, barHeight)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply edge fading\n\t\t\tif (fadeEdges && fadeWidth > 0 && rect.width > 0) {\n\t\t\t\tif (!gradientCacheRef.current || lastWidthRef.current !== rect.width) {\n\t\t\t\t\tconst gradient = ctx.createLinearGradient(0, 0, rect.width, 0)\n\t\t\t\t\tconst fadePercent = Math.min(0.3, fadeWidth / rect.width)\n\n\t\t\t\t\tgradient.addColorStop(0, 'rgba(255,255,255,1)')\n\t\t\t\t\tgradient.addColorStop(fadePercent, 'rgba(255,255,255,0)')\n\t\t\t\t\tgradient.addColorStop(1 - fadePercent, 'rgba(255,255,255,0)')\n\t\t\t\t\tgradient.addColorStop(1, 'rgba(255,255,255,1)')\n\n\t\t\t\t\tgradientCacheRef.current = gradient\n\t\t\t\t\tlastWidthRef.current = rect.width\n\t\t\t\t}\n\n\t\t\t\tctx.globalCompositeOperation = 'destination-out'\n\t\t\t\tctx.fillStyle = gradientCacheRef.current\n\t\t\t\tctx.fillRect(0, 0, rect.width, rect.height)\n\t\t\t\tctx.globalCompositeOperation = 'source-over'\n\t\t\t}\n\n\t\t\tctx.globalAlpha = 1\n\n\t\t\trafId = requestAnimationFrame(animate)\n\t\t}\n\n\t\trafId = requestAnimationFrame(animate)\n\n\t\treturn () => {\n\t\t\tif (rafId) {\n\t\t\t\tcancelAnimationFrame(rafId)\n\t\t\t}\n\t\t}\n\t}, [\n\t\tactive,\n\t\tprocessing,\n\t\tsensitivity,\n\t\tbarWidth,\n\t\tbarGap,\n\t\tbarRadius,\n\t\tbarColor,\n\t\tfadeEdges,\n\t\tfadeWidth,\n\t\tmode,\n\t\tmanualAudioLevel,\n\t\thistorySize,\n\t\tupdateRate,\n\t])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('relative h-full w-full', className)}\n\t\t\tref={containerRef}\n\t\t\tstyle={{ height: heightStyle }}\n\t\t\taria-label={\n\t\t\t\tactive ? 'Live audio waveform' : processing ? 'Processing audio' : 'Audio waveform idle'\n\t\t\t}\n\t\t\trole=\"img\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{!active && !processing && (\n\t\t\t\t<div className=\"border-muted-foreground/20 absolute top-1/2 right-0 left-0 -translate-y-1/2 border-t-2 border-dotted\" />\n\t\t\t)}\n\t\t\t<canvas className=\"block h-full w-full\" ref={canvasRef} />\n\t\t</div>\n\t)\n}\n","/**\n * PillVoiceApprovalBar Component\n *\n * Approval UI for voice mode. Shows when a destructive tool needs approval.\n * Audio is paused while waiting for the user to tap approve or deny.\n *\n * Features:\n * - Pauses audio playback when approval is pending\n * - Displays tool name and countdown timer\n * - Approve/Deny buttons\n * - Amber warning styling consistent with text mode approval\n * - Resumes audio after approval/denial\n */\n'use client'\n\nimport { AlertTriangle, Check, Loader2, Pause, X } from 'lucide-react'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useEffect, useState } from 'react'\n\nimport { humanizeToolName } from '../../lib/format'\nimport { cn } from '../../lib/utils'\nimport { useOptionalVoiceThread } from '../../providers/VoiceThreadBridge'\nimport { useOptionalVoiceToolApproval } from '../../providers/VoiceToolApprovalProvider'\n\nimport type { FC } from 'react'\n\n// Animation variants\nconst approvalBarVariants = {\n\thidden: {\n\t\topacity: 0,\n\t\theight: 0,\n\t\ty: -8,\n\t},\n\tvisible: {\n\t\topacity: 1,\n\t\theight: 'auto',\n\t\ty: 0,\n\t\ttransition: {\n\t\t\ttype: 'spring' as const,\n\t\t\tstiffness: 400,\n\t\t\tdamping: 30,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\theight: 0,\n\t\ty: -8,\n\t\ttransition: {\n\t\t\tduration: 0.15,\n\t\t},\n\t},\n}\n\nconst countdownVariants = {\n\tpulse: {\n\t\tscale: [1, 1.1, 1],\n\t\ttransition: {\n\t\t\tduration: 1,\n\t\t\trepeat: Infinity,\n\t\t},\n\t},\n}\n\nexport interface PillVoiceApprovalBarProps {\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Voice mode approval bar component.\n *\n * Shows when a destructive tool is waiting for approval in voice mode.\n * Pauses audio while waiting for approval, resumes after user responds.\n */\nexport const PillVoiceApprovalBar: FC<PillVoiceApprovalBarProps> = ({ className }) => {\n\tconst voiceThread = useOptionalVoiceThread()\n\tconst voiceApproval = useOptionalVoiceToolApproval()\n\tconst [isExecuting, setIsExecuting] = useState(false)\n\n\t// Pause audio when approval is pending, resume when resolved\n\tuseEffect(() => {\n\t\tif (voiceApproval?.pendingApproval && voiceThread) {\n\t\t\t// Pause audio when this component mounts (approval pending)\n\t\t\tvoiceThread.pauseAudio()\n\n\t\t\t// Resume audio when this component unmounts (approval resolved)\n\t\t\treturn () => {\n\t\t\t\tvoiceThread.resumeAudio()\n\t\t\t}\n\t\t}\n\t}, [voiceApproval?.pendingApproval, voiceThread])\n\n\t// Don't render if no pending approval\n\tif (!voiceApproval?.pendingApproval) {\n\t\treturn null\n\t}\n\n\tconst { pendingApproval, timeoutRemaining, approve, deny } = voiceApproval\n\tconst toolName = humanizeToolName(pendingApproval.toolName)\n\n\t// Handle approve button click\n\tconst handleApprove = () => {\n\t\tsetIsExecuting(true)\n\t\tapprove()\n\t}\n\n\t// Handle deny button click\n\tconst handleDeny = () => {\n\t\tdeny()\n\t}\n\n\treturn (\n\t\t<AnimatePresence>\n\t\t\t<motion.div\n\t\t\t\tclassName={cn('overflow-hidden', className)}\n\t\t\t\tvariants={approvalBarVariants}\n\t\t\t\tinitial=\"hidden\"\n\t\t\t\tanimate=\"visible\"\n\t\t\t\texit=\"exit\"\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'flex flex-col gap-2 rounded-xl px-4 py-3',\n\t\t\t\t\t\t'border border-amber-500/30 bg-amber-500/10'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{/* Header row: Warning icon, tool name, countdown */}\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<AlertTriangle className=\"h-4 w-4 flex-shrink-0 text-amber-500\" />\n\t\t\t\t\t\t<span className=\"min-w-0 flex-1 truncate text-sm text-white/90\">\n\t\t\t\t\t\t\t<span className=\"font-medium text-amber-400\">Approve</span> {toolName}?\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{/* Countdown timer */}\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium',\n\t\t\t\t\t\t\t\ttimeoutRemaining <= 10\n\t\t\t\t\t\t\t\t\t? 'bg-red-500/20 text-red-400'\n\t\t\t\t\t\t\t\t\t: 'bg-amber-500/20 text-amber-400'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tvariants={timeoutRemaining <= 10 ? countdownVariants : undefined}\n\t\t\t\t\t\t\tanimate={timeoutRemaining <= 10 ? 'pulse' : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{timeoutRemaining}\n\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Audio paused indicator */}\n\t\t\t\t\t<div className=\"flex items-center gap-1.5 text-xs text-white/50\">\n\t\t\t\t\t\t<Pause className=\"h-3 w-3\" />\n\t\t\t\t\t\t<span>Audio paused. Tap to approve or deny.</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Action buttons */}\n\t\t\t\t\t{isExecuting ? (\n\t\t\t\t\t\t<div className=\"flex items-center justify-center gap-2 rounded-lg bg-blue-500/10 px-3 py-2 text-sm text-blue-400\">\n\t\t\t\t\t\t\t<Loader2 className=\"h-4 w-4 animate-spin\" />\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\tExecuting <strong>{toolName}</strong>...\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleDeny}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t\t\t\t'border border-zinc-600 text-white/70',\n\t\t\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\t\t\t'hover:border-red-500/50 hover:bg-red-500/20 hover:text-red-400',\n\t\t\t\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<X className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\tDeny\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\tonClick={handleApprove}\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'flex flex-1 items-center justify-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium',\n\t\t\t\t\t\t\t\t\t'border border-amber-500/50 bg-amber-500/20 text-amber-400',\n\t\t\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\t\t\t'hover:border-amber-500 hover:bg-amber-500/30',\n\t\t\t\t\t\t\t\t\t'active:scale-[0.98]'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Check className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\tApprove\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</motion.div>\n\t\t</AnimatePresence>\n\t)\n}\n\nexport default PillVoiceApprovalBar\n","'use client'\n\nimport { Mic, MicOff, PhoneOff } from 'lucide-react'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useCallback } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { useOptionalVoiceThread } from '../../providers/VoiceThreadBridge'\nimport { useOptionalVoiceToolApproval } from '../../providers/VoiceToolApprovalProvider'\nimport { LiveWaveform } from '../live-waveform'\nimport { PillVoiceApprovalBar } from './PillVoiceApprovalBar'\n\nimport type { FC } from 'react'\nimport type { ToolBorderStatus } from './ToolStatusBorder'\n\ninterface PillVoiceProps {\n\t/** Callback when voice mode ends */\n\tonEnd?: () => void\n\t/** Whether to show a compact version */\n\tcompact?: boolean\n\t/** Additional class name */\n\tclassName?: string\n}\n\n// Animation variants for the voice UI\nconst voiceVariants = {\n\thidden: {\n\t\topacity: 0,\n\t\tscale: 0.95,\n\t\ty: 4,\n\t},\n\tvisible: {\n\t\topacity: 1,\n\t\tscale: 1,\n\t\ty: 0,\n\t\ttransition: {\n\t\t\ttype: 'spring' as const,\n\t\t\tstiffness: 400,\n\t\t\tdamping: 30,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\tscale: 0.95,\n\t\ty: -4,\n\t\ttransition: {\n\t\t\tduration: 0.15,\n\t\t},\n\t},\n}\n\n// Button animation\nconst buttonVariants = {\n\tidle: { scale: 1 },\n\thover: { scale: 1.05 },\n\ttap: { scale: 0.95 },\n}\n\n// Transcript animation\nconst transcriptVariants = {\n\thidden: { opacity: 0, height: 0 },\n\tvisible: {\n\t\topacity: 1,\n\t\theight: 'auto',\n\t\ttransition: {\n\t\t\ttype: 'spring' as const,\n\t\t\tstiffness: 300,\n\t\t\tdamping: 25,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\theight: 0,\n\t\ttransition: {\n\t\t\tduration: 0.1,\n\t\t},\n\t},\n}\n\n/**\n * Convert voice mode tool call status to border status\n */\nexport function voiceToolCallToBorderStatus(toolCall?: {\n\tstatus: 'started' | 'completed'\n\terror?: string\n}): ToolBorderStatus {\n\tif (!toolCall) return 'idle'\n\tif (toolCall.status === 'started') return 'calling'\n\tif (toolCall.status === 'completed') {\n\t\treturn toolCall.error ? 'error' : 'success'\n\t}\n\treturn 'idle'\n}\n\n/**\n * Compact voice mode UI for the pill.\n * Shows waveforms, controls, and transcript preview.\n * Uses motion animations for smooth transitions.\n *\n * Uses VoiceThreadBridge for voice state (integrated with thread).\n */\nexport const PillVoice: FC<PillVoiceProps> = ({ onEnd, compact = false, className }) => {\n\tconst voiceThread = useOptionalVoiceThread()\n\tconst voiceToolApproval = useOptionalVoiceToolApproval()\n\n\tconst handleEnd = useCallback(() => {\n\t\t// Clear any pending voice approvals\n\t\tvoiceToolApproval?.clearPendingApproval()\n\n\t\t// Stop the voice session\n\t\tvoiceThread?.stop()\n\t\tonEnd?.()\n\t}, [voiceThread, voiceToolApproval, onEnd])\n\n\tconst handleToggleMute = useCallback(() => {\n\t\tvoiceThread?.toggleMute()\n\t}, [voiceThread])\n\n\t// Don't render if no voice context or not active/connecting/error\n\tif (\n\t\t!voiceThread ||\n\t\t(!voiceThread.isActive && !voiceThread.isConnecting && !voiceThread.isError)\n\t) {\n\t\treturn null\n\t}\n\n\tconst { isActive, isConnecting, isMuted, isError, error, audioLevel, transcript, toolCall } =\n\t\tvoiceThread\n\n\t// Check if we're waiting for approval\n\tconst isWaitingForApproval = voiceToolApproval?.isWaitingForApproval ?? false\n\tconst micLevel = audioLevel?.micLevel ?? 0\n\tconst speakerLevel = audioLevel?.speakerLevel ?? 0\n\n\treturn (\n\t\t<motion.div\n\t\t\tclassName={cn('flex flex-col gap-3', className)}\n\t\t\tvariants={voiceVariants}\n\t\t\tinitial=\"hidden\"\n\t\t\tanimate=\"visible\"\n\t\t\texit=\"exit\"\n\t\t>\n\t\t\t{/* Waveforms row */}\n\t\t\t<div className=\"flex items-center gap-3\">\n\t\t\t\t{/* User mic indicator */}\n\t\t\t\t<div className=\"flex flex-1 items-center gap-2\">\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-11 w-11 shrink-0 items-center justify-center rounded-full sm:h-7 sm:w-7',\n\t\t\t\t\t\t\tisMuted ? 'bg-red-500/20 text-red-400' : 'bg-white/10 text-white/80'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tanimate={{ opacity: isMuted ? 0.6 : 1 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isMuted ? (\n\t\t\t\t\t\t\t<MicOff className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Mic className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</motion.div>\n\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn('h-5 flex-1', compact ? 'max-w-24 sm:max-w-16' : 'max-w-32 sm:max-w-24')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LiveWaveform\n\t\t\t\t\t\t\tactive={isActive && !isMuted}\n\t\t\t\t\t\t\tprocessing={isConnecting}\n\t\t\t\t\t\t\tmanualAudioLevel={micLevel}\n\t\t\t\t\t\t\tbarWidth={2}\n\t\t\t\t\t\t\tbarGap={1}\n\t\t\t\t\t\t\tbarRadius={1}\n\t\t\t\t\t\t\tbarColor=\"rgba(255, 255, 255, 0.7)\"\n\t\t\t\t\t\t\theight={20}\n\t\t\t\t\t\t\tmode=\"static\"\n\t\t\t\t\t\t\tsensitivity={2.0}\n\t\t\t\t\t\t\tfadeEdges={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Separator */}\n\t\t\t\t<div className=\"h-5 w-px bg-white/10\" />\n\n\t\t\t\t{/* Agent speaker indicator */}\n\t\t\t\t<div className=\"flex flex-1 items-center gap-2\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn('h-5 flex-1', compact ? 'max-w-24 sm:max-w-16' : 'max-w-32 sm:max-w-24')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LiveWaveform\n\t\t\t\t\t\t\tactive={isActive}\n\t\t\t\t\t\t\tprocessing={isConnecting}\n\t\t\t\t\t\t\tmanualAudioLevel={speakerLevel}\n\t\t\t\t\t\t\tbarWidth={2}\n\t\t\t\t\t\t\tbarGap={1}\n\t\t\t\t\t\t\tbarRadius={1}\n\t\t\t\t\t\t\tbarColor=\"rgba(255, 255, 255, 0.4)\"\n\t\t\t\t\t\t\theight={20}\n\t\t\t\t\t\t\tmode=\"static\"\n\t\t\t\t\t\t\tsensitivity={2.0}\n\t\t\t\t\t\t\tfadeEdges={false}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Agent avatar */}\n\t\t\t\t\t<div className=\"flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-white/10 sm:h-7 sm:w-7\">\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tclassName=\"h-2.5 w-2.5 rounded-full bg-green-400\"\n\t\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\t\tscale: speakerLevel > 0.1 ? [1, 1.2, 1] : 1,\n\t\t\t\t\t\t\t\topacity: speakerLevel > 0.1 ? 1 : 0.5,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\ttransition={{ duration: 0.2 }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Separator */}\n\t\t\t\t<div className=\"h-5 w-px bg-white/10\" />\n\n\t\t\t\t{/* Controls */}\n\t\t\t\t<div className=\"flex shrink-0 items-center gap-2 sm:gap-1.5\">\n\t\t\t\t\t{/* Mute button */}\n\t\t\t\t\t<motion.button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleToggleMute}\n\t\t\t\t\t\tdisabled={!isActive}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-11 w-11 items-center justify-center rounded-full sm:h-7 sm:w-7',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisMuted\n\t\t\t\t\t\t\t\t? 'bg-red-500/20 text-red-400 hover:bg-red-500/30'\n\t\t\t\t\t\t\t\t: 'bg-white/10 text-white/70 hover:bg-white/20 hover:text-white'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tvariants={buttonVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\twhileHover=\"hover\"\n\t\t\t\t\t\twhileTap=\"tap\"\n\t\t\t\t\t\taria-label={isMuted ? 'Unmute microphone' : 'Mute microphone'}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isMuted ? (\n\t\t\t\t\t\t\t<MicOff className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Mic className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</motion.button>\n\n\t\t\t\t\t{/* End button */}\n\t\t\t\t\t<motion.button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={handleEnd}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex h-11 w-11 items-center justify-center rounded-full sm:h-7 sm:w-7',\n\t\t\t\t\t\t\t'bg-red-500/20 text-red-400',\n\t\t\t\t\t\t\t'hover:bg-red-500/30 hover:text-red-300',\n\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tvariants={buttonVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\twhileHover=\"hover\"\n\t\t\t\t\t\twhileTap=\"tap\"\n\t\t\t\t\t\taria-label=\"End voice session\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<PhoneOff className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t</motion.button>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Voice Tool Approval Bar - shows when a destructive tool needs approval */}\n\t\t\t<AnimatePresence>{isWaitingForApproval && <PillVoiceApprovalBar />}</AnimatePresence>\n\n\t\t\t{/* Tool call indicator - only show when NOT waiting for approval */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{toolCall && !isWaitingForApproval && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'flex max-w-full items-center gap-2 rounded-full px-3 py-1.5',\n\t\t\t\t\t\t\t'text-xs',\n\t\t\t\t\t\t\ttoolCall.status === 'started' && 'bg-blue-500/10 text-blue-400',\n\t\t\t\t\t\t\ttoolCall.status === 'completed' &&\n\t\t\t\t\t\t\t\t!toolCall.error &&\n\t\t\t\t\t\t\t\t'bg-green-500/10 text-green-400',\n\t\t\t\t\t\t\ttoolCall.status === 'completed' && toolCall.error && 'bg-red-500/10 text-red-400'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tinitial={{ opacity: 0, y: -4 }}\n\t\t\t\t\t\tanimate={{ opacity: 1, y: 0 }}\n\t\t\t\t\t\texit={{ opacity: 0, y: -4 }}\n\t\t\t\t\t\ttransition={{ type: 'spring', stiffness: 400, damping: 30 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<motion.span\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'h-1.5 w-1.5 shrink-0 rounded-full',\n\t\t\t\t\t\t\t\ttoolCall.status === 'started' && 'bg-blue-500',\n\t\t\t\t\t\t\t\ttoolCall.status === 'completed' && !toolCall.error && 'bg-green-500',\n\t\t\t\t\t\t\t\ttoolCall.status === 'completed' && toolCall.error && 'bg-red-500'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tanimate={toolCall.status === 'started' ? { opacity: [1, 0.5, 1] } : {}}\n\t\t\t\t\t\t\ttransition={{ duration: 0.8, repeat: Infinity }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<span className=\"min-w-0 truncate\">{toolCall.toolName}</span>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Transcript preview */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{transcript && transcript.text && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName=\"overflow-hidden\"\n\t\t\t\t\t\tvariants={transcriptVariants}\n\t\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\t\texit=\"exit\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'rounded-lg px-3 py-2 text-xs',\n\t\t\t\t\t\t\t\ttranscript.type === 'user'\n\t\t\t\t\t\t\t\t\t? 'bg-white/10 text-white/80'\n\t\t\t\t\t\t\t\t\t: 'bg-white/5 text-white/60'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"mr-1.5 shrink-0 text-white/40\">\n\t\t\t\t\t\t\t\t{transcript.type === 'user' ? 'You:' : 'Agent:'}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span className={cn('line-clamp-3', !transcript.isDone && 'animate-pulse')}>\n\t\t\t\t\t\t\t\t{transcript.text}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Connecting state */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{isConnecting && !isActive && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName=\"flex items-center justify-center gap-2 py-2 text-xs text-white/50\"\n\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<motion.span\n\t\t\t\t\t\t\tclassName=\"h-1.5 w-1.5 rounded-full bg-amber-500\"\n\t\t\t\t\t\t\tanimate={{ opacity: [1, 0.5, 1] }}\n\t\t\t\t\t\t\ttransition={{ duration: 0.8, repeat: Infinity }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<span>Connecting...</span>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Error state */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{isError && error && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2 text-xs text-red-400\"\n\t\t\t\t\t\tinitial={{ opacity: 0, y: -4 }}\n\t\t\t\t\t\tanimate={{ opacity: 1, y: 0 }}\n\t\t\t\t\t\texit={{ opacity: 0, y: -4 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<span className=\"h-1.5 w-1.5 shrink-0 rounded-full bg-red-500\" />\n\t\t\t\t\t\t<span className=\"line-clamp-2\">{error}</span>\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={handleEnd}\n\t\t\t\t\t\t\tclassName=\"ml-auto shrink-0 text-red-300 hover:text-red-200\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tDismiss\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\t\t</motion.div>\n\t)\n}\n\n/**\n * Hook to get voice border status for the pill container\n */\nexport function useVoiceBorderStatus(): ToolBorderStatus {\n\tconst voiceThread = useOptionalVoiceThread()\n\n\tif (!voiceThread) return 'idle'\n\n\treturn voiceToolCallToBorderStatus(voiceThread.toolCall)\n}\n\nexport default PillVoice\n","/**\n * PromptBadge\n *\n * Intercom-style floating prompt bubbles that appear above the collapsed pill.\n * Shows up to MAX_PROMPT_BUBBLES in a triangular layout with staggered animations.\n *\n * Accessibility:\n * - Focus-visible rings for keyboard navigation\n * - Screen reader live region announces suggestions\n * - Touch-friendly dismiss targets on mobile\n */\nimport { X } from 'lucide-react'\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useCallback, useState } from 'react'\n\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport { MAX_PROMPT_BUBBLES } from '../../lib/constants'\nimport { cn } from '../../lib/utils'\n\nimport type { Prompt } from '@mcp-b/cloud-mirror-types'\nimport type { Variants } from 'motion/react'\nimport type { FC, MouseEvent } from 'react'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PromptBadgeProps {\n\t/** Available prompts to display */\n\tprompts: Prompt[]\n\t/** Callback when a prompt is selected */\n\tonSelect: (prompt: Prompt) => void\n\t/** Additional class name */\n\tclassName?: string\n}\n\n// ============================================================================\n// Animation Configuration\n// ============================================================================\n\n/** Stagger timing for bubble animations (seconds) */\nconst STAGGER_DELAY = 0.08\nconst STAGGER_DELAY_INITIAL = 0.05\nconst STAGGER_DELAY_EXIT = 0.03\n\n/** Container animation variants for staggered children */\nconst containerVariants: Variants = {\n\thidden: { opacity: 0 },\n\tvisible: {\n\t\topacity: 1,\n\t\ttransition: {\n\t\t\tstaggerChildren: STAGGER_DELAY,\n\t\t\tdelayChildren: STAGGER_DELAY_INITIAL,\n\t\t},\n\t},\n\texit: {\n\t\topacity: 0,\n\t\ttransition: {\n\t\t\tstaggerChildren: STAGGER_DELAY_EXIT,\n\t\t\tstaggerDirection: -1,\n\t\t},\n\t},\n}\n\n/** Individual bubble animation variants */\nconst bubbleVariants: Variants = {\n\thidden: { opacity: 0, y: 10, scale: 0.9 },\n\tvisible: {\n\t\topacity: 1,\n\t\ty: 0,\n\t\tscale: 1,\n\t\ttransition: { type: 'spring', stiffness: 400, damping: 25 },\n\t},\n\texit: { opacity: 0, y: 5, scale: 0.95, transition: { duration: 0.1 } },\n}\n\n// ============================================================================\n// Styles\n// ============================================================================\n\n/** Bubble button styles */\nconst bubbleStyles = cn(\n\t'flex items-center px-3 py-1.5',\n\t'bg-white dark:bg-zinc-800',\n\t'rounded-full',\n\t'shadow-lg shadow-black/10 dark:shadow-black/30',\n\t'border border-zinc-200/80 dark:border-zinc-700/80',\n\t'text-sm text-zinc-700 dark:text-zinc-200',\n\t'hover:bg-zinc-50 dark:hover:bg-zinc-700',\n\t'transition-colors duration-100',\n\t'whitespace-nowrap',\n\t// Focus state for keyboard navigation\n\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-1'\n)\n\n/** Dismiss badge base styles (shared between mobile and desktop) */\nconst dismissBadgeBaseStyles = cn(\n\t'absolute -top-1.5 -right-1.5',\n\t'flex items-center justify-center',\n\t'rounded-full',\n\t'bg-zinc-100 dark:bg-zinc-700',\n\t'border border-zinc-200 dark:border-zinc-600',\n\t'text-zinc-400 dark:text-zinc-400',\n\t'hover:bg-zinc-200 dark:hover:bg-zinc-600',\n\t'hover:text-zinc-600 dark:hover:text-zinc-200',\n\t'shadow-sm',\n\t'transition-all duration-150',\n\t// Focus state for keyboard navigation\n\t'focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500'\n)\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Floating prompt bubbles above the pill.\n * Positioned absolutely above parent - parent should be relative.\n */\nexport const PromptBadge: FC<PromptBadgeProps> = ({ prompts, onSelect, className }) => {\n\tconst [isDismissed, setIsDismissed] = useState(false)\n\tconst { isMobile } = useMobileDetect()\n\n\tconst handleSelect = useCallback(\n\t\t(prompt: Prompt) => {\n\t\t\tonSelect(prompt)\n\t\t},\n\t\t[onSelect]\n\t)\n\n\tconst handleDismiss = useCallback((e: MouseEvent) => {\n\t\te.stopPropagation()\n\t\tsetIsDismissed(true)\n\t}, [])\n\n\t// Early return if no prompts or dismissed\n\tif (prompts.length === 0 || isDismissed) {\n\t\treturn null\n\t}\n\n\t// Take up to MAX_PROMPT_BUBBLES prompts\n\tconst visiblePrompts = prompts.slice(0, MAX_PROMPT_BUBBLES)\n\n\t// Dynamic dismiss badge styles based on device type\n\tconst dismissBadgeStyles = cn(\n\t\tdismissBadgeBaseStyles,\n\t\t// Size: 24px on mobile (WCAG AA), 16px on desktop\n\t\tisMobile ? 'w-6 h-6' : 'w-4 h-4',\n\t\t// Visibility: always visible on mobile, hover-only on desktop\n\t\tisMobile\n\t\t\t? 'opacity-100 scale-100'\n\t\t\t: 'opacity-0 group-hover:opacity-100 scale-75 group-hover:scale-100'\n\t)\n\n\treturn (\n\t\t<div className={cn('absolute bottom-full left-1/2 -translate-x-1/2 mb-3 z-20', className)}>\n\t\t\t{/* Screen reader announcement */}\n\t\t\t<div role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n\t\t\t\t{visiblePrompts.length} suggestion{visiblePrompts.length !== 1 ? 's' : ''} available\n\t\t\t</div>\n\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t<motion.div\n\t\t\t\t\tkey=\"bubbles\"\n\t\t\t\t\tvariants={containerVariants}\n\t\t\t\t\tinitial=\"hidden\"\n\t\t\t\t\tanimate=\"visible\"\n\t\t\t\t\texit=\"exit\"\n\t\t\t\t\tclassName=\"flex items-end gap-2\"\n\t\t\t\t\trole=\"group\"\n\t\t\t\t\taria-label=\"Suggested prompts\"\n\t\t\t\t>\n\t\t\t\t\t{visiblePrompts.map((prompt, index) => {\n\t\t\t\t\t\t// Triangular offset: middle bubble (index 1) is raised when showing 3 bubbles\n\t\t\t\t\t\tconst isMiddleBubble = visiblePrompts.length === 3 && index === 1\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<div key={prompt.name} className={cn('group relative', isMiddleBubble && 'mb-3')}>\n\t\t\t\t\t\t\t\t<motion.button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tvariants={bubbleVariants}\n\t\t\t\t\t\t\t\t\tonClick={() => handleSelect(prompt)}\n\t\t\t\t\t\t\t\t\tclassName={bubbleStyles}\n\t\t\t\t\t\t\t\t\ttitle={prompt.description || prompt.name}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span>{prompt.name}</span>\n\t\t\t\t\t\t\t\t</motion.button>\n\n\t\t\t\t\t\t\t\t{/* Dismiss badge - always visible on mobile, hover on desktop */}\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={handleDismiss}\n\t\t\t\t\t\t\t\t\tclassName={dismissBadgeStyles}\n\t\t\t\t\t\t\t\t\taria-label=\"Dismiss suggestions\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X size={isMobile ? 12 : 10} />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t</motion.div>\n\t\t\t</AnimatePresence>\n\t\t</div>\n\t)\n}\n\nexport default PromptBadge\n","/**\n * PromptSuggestions\n *\n * Inline prompt suggestions shown inside the expanded pill.\n * Compact horizontal scrollable list of prompt chips.\n */\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useCallback, useRef } from 'react'\n\nimport { cn } from '../../lib/utils'\n\nimport type { Prompt } from '@mcp-b/cloud-mirror-types'\nimport type { FC } from 'react'\n\nexport interface PromptSuggestionsProps {\n\t/** Available prompts to display */\n\tprompts: Prompt[]\n\t/** Callback when a prompt is selected */\n\tonSelect: (prompt: Prompt) => void\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Inline prompt suggestions for the expanded pill.\n * Horizontally scrollable list of compact prompt chips.\n */\nexport const PromptSuggestions: FC<PromptSuggestionsProps> = ({ prompts, onSelect, className }) => {\n\tconst scrollRef = useRef<HTMLDivElement>(null)\n\n\tconst handleClick = useCallback(\n\t\t(prompt: Prompt) => {\n\t\t\tonSelect(prompt)\n\t\t},\n\t\t[onSelect]\n\t)\n\n\tif (prompts.length === 0) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<motion.div\n\t\t\tinitial={{ opacity: 0, height: 0 }}\n\t\t\tanimate={{ opacity: 1, height: 'auto' }}\n\t\t\texit={{ opacity: 0, height: 0 }}\n\t\t\tclassName={cn('overflow-hidden', className)}\n\t\t>\n\t\t\t<div\n\t\t\t\tref={scrollRef}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex gap-2 overflow-x-auto scrollbar-hide',\n\t\t\t\t\t'pb-1 -mb-1' // Padding for focus ring visibility\n\t\t\t\t)}\n\t\t\t\t// Allow horizontal scrolling within draggable parent\n\t\t\t\tstyle={{ touchAction: 'pan-x' }}\n\t\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t>\n\t\t\t\t<AnimatePresence mode=\"popLayout\">\n\t\t\t\t\t{prompts.map((prompt, index) => (\n\t\t\t\t\t\t<motion.button\n\t\t\t\t\t\t\tkey={prompt.name}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\t\tanimate={{ opacity: 1, scale: 1 }}\n\t\t\t\t\t\t\texit={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\t\ttransition={{\n\t\t\t\t\t\t\t\ttype: 'spring',\n\t\t\t\t\t\t\t\tstiffness: 400,\n\t\t\t\t\t\t\t\tdamping: 25,\n\t\t\t\t\t\t\t\tdelay: index * 0.03,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={() => handleClick(prompt)}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t'flex-shrink-0',\n\t\t\t\t\t\t\t\t'px-2.5 py-1 rounded-full',\n\t\t\t\t\t\t\t\t'bg-white/10 hover:bg-white/20',\n\t\t\t\t\t\t\t\t'text-white/80 hover:text-white',\n\t\t\t\t\t\t\t\t'text-xs font-medium',\n\t\t\t\t\t\t\t\t'border border-white/10 hover:border-white/20',\n\t\t\t\t\t\t\t\t'transition-all duration-150',\n\t\t\t\t\t\t\t\t'cursor-pointer',\n\t\t\t\t\t\t\t\t'whitespace-nowrap'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\ttitle={prompt.description || prompt.name}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{prompt.name}\n\t\t\t\t\t\t</motion.button>\n\t\t\t\t\t))}\n\t\t\t\t</AnimatePresence>\n\t\t\t</div>\n\t\t</motion.div>\n\t)\n}\n\nexport default PromptSuggestions\n","/**\n * StreamingResponse Component\n *\n * Shows the streaming text response from the agent as it's being generated.\n * This provides real-time visibility into what the agent is writing,\n * rather than waiting for the complete response.\n *\n * Features:\n * - Shows text as it streams in\n * - Typing cursor animation\n * - Compact, scrollable container\n * - Fades in/out smoothly\n */\n'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { PillMarkdown } from './PillMarkdown'\n\nimport type { FC } from 'react'\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface TextPart {\n\ttype: 'text'\n\ttext: string\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Hook to get the current streaming text from the thread.\n * Returns null if not currently streaming or no text content.\n */\nexport function useStreamingText(): string | null {\n\tconst messages = useThread((thread) => thread.messages)\n\tconst isRunning = useThread((thread) => thread.isRunning)\n\n\treturn useMemo(() => {\n\t\tif (!isRunning) return null\n\n\t\t// Find the last assistant message\n\t\tconst lastAssistantMessage = messages\n\t\t\t? [...messages].reverse().find((m) => m.role === 'assistant')\n\t\t\t: null\n\n\t\tif (!lastAssistantMessage) return null\n\n\t\t// Get text parts\n\t\tconst textParts = lastAssistantMessage.content.filter(\n\t\t\t(part): part is TextPart => part.type === 'text'\n\t\t)\n\t\tconst lastText = textParts.at(-1)?.text\n\n\t\t// Only return if there's actual text content\n\t\tif (!lastText || lastText.trim().length === 0) return null\n\n\t\treturn lastText\n\t}, [messages, isRunning])\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface StreamingResponseProps {\n\t/** Maximum height before scrolling (ignored when isFullScreen) */\n\tmaxHeight?: string\n\t/** Additional class name */\n\tclassName?: string\n\t/** Full-screen mode - larger text, no height constraints (parent handles scrolling) */\n\tisFullScreen?: boolean\n}\n\n/**\n * Displays the streaming response text as it's being generated.\n * Shows a typing cursor and scrolls to keep latest content visible.\n */\nexport const StreamingResponse: FC<StreamingResponseProps> = ({\n\tmaxHeight = '8rem',\n\tclassName,\n\tisFullScreen = false,\n}) => {\n\tconst streamingText = useStreamingText()\n\n\tif (!streamingText) return null\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'rounded-lg bg-white/5 border border-white/10 p-3',\n\t\t\t\t'overflow-y-auto scrollbar-thin scroll-touch',\n\t\t\t\t// Bottom margin for spacing from tool section\n\t\t\t\t'mb-1.5',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tstyle={isFullScreen ? undefined : { maxHeight }}\n\t\t>\n\t\t\t<div className=\"relative\">\n\t\t\t\t<PillMarkdown content={streamingText} className=\"text-white/90\" compact={!isFullScreen} />\n\t\t\t\t{/* Typing cursor */}\n\t\t\t\t<span className=\"inline-block w-0.5 h-4 bg-blue-400 ml-0.5 animate-pulse align-middle\" />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\nexport default StreamingResponse\n","'use client'\n\nimport { AnimatePresence, motion } from 'motion/react'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { cn } from '../../lib/utils'\n\nimport type { FC, ReactNode } from 'react'\n\n// Minimalist: only idle, calling, and error states\n// Success is the default - no special treatment needed\nexport type ToolBorderStatus = 'idle' | 'calling' | 'success' | 'error'\n\ninterface ToolStatusBorderProps {\n\tstatus: ToolBorderStatus\n\tchildren: ReactNode\n\tclassName?: string\n\tborderRadius?: string\n}\n\n// Animation variants for the border glow\nconst borderVariants = {\n\tidle: {\n\t\topacity: 0,\n\t\tscale: 1,\n\t},\n\tcalling: {\n\t\topacity: 1,\n\t\tscale: 1,\n\t\ttransition: {\n\t\t\topacity: { duration: 0.15 },\n\t\t},\n\t},\n\terror: {\n\t\topacity: 1,\n\t\tscale: 1,\n\t\ttransition: {\n\t\t\topacity: { duration: 0.1 },\n\t\t},\n\t},\n}\n\n// Subtle shake animation for errors only\nconst shakeAnimation = {\n\tx: [0, -2, 2, -2, 2, 0],\n\ttransition: {\n\t\tduration: 0.3,\n\t\tease: [0.25, 0.1, 0.25, 1] as const,\n\t},\n}\n\n/**\n * Minimal animated border for tool execution status.\n *\n * - idle/success: clean, no border (success is the default state)\n * - calling: subtle animated gradient\n * - error: brief red flash with shake\n */\nexport const ToolStatusBorder: FC<ToolStatusBorderProps> = ({\n\tstatus,\n\tchildren,\n\tclassName,\n\tborderRadius = '20px',\n}) => {\n\t// Treat success as idle - no special visual treatment\n\tconst effectiveStatus = status === 'success' ? 'idle' : status\n\n\treturn (\n\t\t<motion.div\n\t\t\tclassName={cn('relative', className)}\n\t\t\tanimate={effectiveStatus === 'error' ? shakeAnimation : undefined}\n\t\t>\n\t\t\t{/* Animated border layer - only for calling and error */}\n\t\t\t<AnimatePresence>\n\t\t\t\t{effectiveStatus !== 'idle' && (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'absolute -inset-[1px] pointer-events-none',\n\t\t\t\t\t\t\teffectiveStatus === 'calling' && 'tool-border-calling',\n\t\t\t\t\t\t\teffectiveStatus === 'error' && 'tool-border-error'\n\t\t\t\t\t\t)}\n\t\t\t\t\t\tstyle={{ borderRadius }}\n\t\t\t\t\t\tvariants={borderVariants}\n\t\t\t\t\t\tinitial=\"idle\"\n\t\t\t\t\t\tanimate={effectiveStatus}\n\t\t\t\t\t\texit={{ opacity: 0, transition: { duration: 0.15 } }}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{/* Inner content container - no ring for cleaner look */}\n\t\t\t<div className=\"relative\" style={{ borderRadius }}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</motion.div>\n\t)\n}\n\n/**\n * Hook to manage tool border status based on actions.\n * Minimalist approach: success returns to idle immediately.\n */\nexport function useToolBorderStatus(\n\thasRunningAction: boolean,\n\tlastActionStatus?: 'success' | 'error' | null\n): ToolBorderStatus {\n\tconst [status, setStatus] = useState<ToolBorderStatus>('idle')\n\tconst timeoutRef = useRef<NodeJS.Timeout | null>(null)\n\n\tuseEffect(() => {\n\t\tif (timeoutRef.current) {\n\t\t\tclearTimeout(timeoutRef.current)\n\t\t\ttimeoutRef.current = null\n\t\t}\n\n\t\tif (hasRunningAction) {\n\t\t\tsetStatus('calling')\n\t\t} else if (lastActionStatus === 'error') {\n\t\t\tsetStatus('error')\n\t\t\t// Brief error flash, then back to idle\n\t\t\ttimeoutRef.current = setTimeout(() => {\n\t\t\t\tsetStatus('idle')\n\t\t\t}, 400)\n\t\t} else {\n\t\t\t// Success or no action = idle (clean state)\n\t\t\tsetStatus('idle')\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (timeoutRef.current) {\n\t\t\t\tclearTimeout(timeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [hasRunningAction, lastActionStatus])\n\n\treturn status\n}\n","'use client'\n\nimport { ThreadPrimitive, useComposerRuntime, useThreadRuntime } from '@assistant-ui/react'\nimport { Expand, GripHorizontal, Minimize, X } from 'lucide-react'\nimport { AnimatePresence, motion, useDragControls } from 'motion/react'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { useAgent } from '../../core/hooks/useAgent'\nimport { useOptionalAgentUI } from '../../core/providers/AgentUIProvider'\nimport { useKeyboardAware } from '../../hooks/useKeyboardAware'\nimport { useMobileDetect } from '../../hooks/useMobileDetect'\nimport { useHasPendingToolCalls, usePendingToolCalls } from '../../hooks/usePendingToolCalls'\nimport { usePinchGesture } from '../../hooks/usePinchGesture'\nimport {\n\tARIA_LABELS,\n\tAUTO_COLLAPSE_TIMEOUT_MS,\n\tdebugLog,\n\tDRAG_OPACITY,\n\tGESTURE_CONFIG,\n\tKEYBOARD_GAP_PX,\n\tPILL_BORDER_RADIUS,\n} from '../../lib/constants'\nimport { formatToolDenialWithReason } from '../../lib/format'\nimport { resolvePendingToolCall } from '../../lib/thread-utils'\nimport { cn } from '../../lib/utils'\nimport { ActivityIndicator } from './ActivityIndicator'\nimport { ApprovalModeIndicator } from './ApprovalModeToggle'\nimport { IdleIndicator } from './CurrentActivity'\nimport { ElicitationButtonBar } from './ElicitationButtonBar'\nimport { PillComposer } from './PillComposer'\nimport { PillContainer } from './PillContainer'\nimport { PillToolsSection } from './PillToolsSection'\nimport { PillVoice, useVoiceBorderStatus } from './PillVoice'\nimport { PromptBadge } from './PromptBadge'\nimport { PromptSuggestions } from './PromptSuggestions'\nimport { StreamingResponse } from './StreamingResponse'\nimport { SummaryBlock, WelcomeMessage } from './SummaryBlock'\nimport { ToolStatusBorder, useToolBorderStatus } from './ToolStatusBorder'\n\nimport type { Prompt } from '@mcp-b/cloud-mirror-types'\nimport type { FC } from 'react'\nimport type { PillMode } from './PillContainer'\n\n/** Position of the pill on screen */\nexport type PillPosition = 'bottom-center' | 'bottom-right'\n\nexport interface AgentPillProps {\n\t/** Position of the pill on screen */\n\tposition?: PillPosition\n\t/** Show voice button in composer */\n\tshowVoiceButton?: boolean\n\t/** Voice mode active state (external control) */\n\tisVoiceActive?: boolean\n\t/** Voice toggle callback */\n\tonVoiceToggle?: () => void\n\t/** Auto-collapse after inactivity (default: true) */\n\tautoCollapse?: boolean\n\t/** Additional class name */\n\tclassName?: string\n}\n\n/**\n * Action-first agent pill UI.\n *\n * A compact, morphing interface that shows:\n * - Current activity when agent is working\n * - Action list (collapsible)\n * - Summary when complete\n * - Input composer\n *\n * Uses assistant-ui primitives for data binding.\n * UI state (mode, position, hasUnread) comes from AgentUIProvider.\n * Thread state (messages, actions) comes from assistant-ui.\n */\nexport const AgentPill: FC<AgentPillProps> = ({\n\tposition = 'bottom-center',\n\tshowVoiceButton = false,\n\tisVoiceActive = false,\n\tonVoiceToggle,\n\tautoCollapse = true,\n\tclassName,\n}) => {\n\t// Get agent state (unified facade over thread, actions, voice, tools)\n\tconst agent = useAgent()\n\n\t// Destructure agent state for convenience\n\tconst {\n\t\tmessages,\n\t\tisRunning,\n\t\thasMessages,\n\t\tcurrentAction,\n\t\tlastCompletedAction,\n\t\tsummary,\n\t\tvoice,\n\t\ttools,\n\t\tisVoiceActive: agentVoiceActive,\n\t} = agent\n\n\t// Check if there are pending approvals (HITL tools) - derived from thread state\n\tconst hasPendingApproval = useHasPendingToolCalls()\n\tconst pendingToolCalls = usePendingToolCalls()\n\tconst threadRuntime = useThreadRuntime()\n\n\t// Get UI state from AgentUIProvider (falls back to local state if not wrapped)\n\tconst agentUI = useOptionalAgentUI()\n\n\t// UI state - prefer provider state, fallback to default\n\tconst userMode = agentUI?.userMode ?? 'collapsed'\n\tconst setUserMode = agentUI?.setUserMode ?? (() => {})\n\tconst hasUnread = agentUI?.hasUnread ?? false\n\tconst markRead = agentUI?.markRead ?? (() => {})\n\tconst markUnread = agentUI?.markUnread ?? (() => {})\n\tconst dragPosition = agentUI?.position ?? { x: 0, y: 0 }\n\tconst setDragPosition = agentUI?.setPosition ?? (() => {})\n\tconst resetPosition = agentUI?.resetPosition ?? (() => {})\n\n\t// Full-screen mode state\n\tconst isFullScreen = agentUI?.isFullScreen ?? false\n\tconst enterFullScreen = agentUI?.enterFullScreen ?? (() => {})\n\tconst exitFullScreen = agentUI?.exitFullScreen ?? (() => {})\n\n\tconst dragControls = useDragControls()\n\tconst constraintsRef = useRef<HTMLDivElement>(null)\n\tconst autoCollapseTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n\tconst lastMessageCountRef = useRef(0)\n\n\t// Keyboard-aware positioning for mobile\n\tconst { isKeyboardVisible, keyboardHeight } = useKeyboardAware()\n\n\t// Mobile detection for gesture handling\n\tconst { isMobile } = useMobileDetect()\n\n\t// Get prompts from tools (if available)\n\tconst prompts = tools?.prompts ?? []\n\tconst getPrompt = tools?.getPrompt\n\n\t// Get composer runtime for programmatic message sending\n\tconst composerRuntime = useComposerRuntime()\n\n\t/**\n\t * Handle drag end - processes both drag-to-reposition and swipe-to-dismiss gestures.\n\t *\n\t * Behavior:\n\t * - Desktop: Drag to reposition only (no swipe gestures)\n\t * - Mobile: Drag to reposition + aggressive swipe-up to dismiss\n\t */\n\tconst handleDragEnd = useCallback(\n\t\t(_: unknown, info: { offset: { x: number; y: number }; velocity: { y: number } }) => {\n\t\t\tconst { offset, velocity } = info\n\t\t\tconst dragDistance = Math.sqrt(offset.x ** 2 + offset.y ** 2)\n\n\t\t\t// Check if pill is in an expanded state (not collapsed or hovered)\n\t\t\tconst isExpanded =\n\t\t\t\tuserMode === 'composing' || userMode === 'active' || userMode === 'expanded'\n\n\t\t\t// === MOBILE: Check for swipe-to-dismiss (aggressive upward swipe) ===\n\t\t\tif (isMobile && isExpanded) {\n\t\t\t\tconst swipeDistance = -offset.y // Positive = upward swipe\n\t\t\t\tconst swipeVelocity = -velocity.y // Positive = upward velocity\n\n\t\t\t\tconst { swipe } = GESTURE_CONFIG\n\t\t\t\tconst isAggressiveSwipe =\n\t\t\t\t\t// Either: distance AND velocity both exceed thresholds\n\t\t\t\t\t(swipeDistance > swipe.minDistance && swipeVelocity > swipe.minVelocity) ||\n\t\t\t\t\t// Or: extremely fast swipe (regardless of distance)\n\t\t\t\t\tswipeVelocity > swipe.velocityOnlyThreshold\n\n\t\t\t\tif (isAggressiveSwipe) {\n\t\t\t\t\tsetUserMode('collapsed')\n\t\t\t\t\tresetPosition()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// === DRAG: Only update position if drag exceeded activation threshold ===\n\t\t\tif (dragDistance >= GESTURE_CONFIG.dragActivationDistance) {\n\t\t\t\tsetDragPosition({\n\t\t\t\t\tx: dragPosition.x + offset.x,\n\t\t\t\t\ty: dragPosition.y + offset.y,\n\t\t\t\t})\n\t\t\t}\n\t\t\t// If drag distance is below threshold, ignore it (allows clean taps)\n\t\t},\n\t\t[\n\t\t\tdragPosition.x,\n\t\t\tdragPosition.y,\n\t\t\tsetDragPosition,\n\t\t\tisMobile,\n\t\t\tuserMode,\n\t\t\tsetUserMode,\n\t\t\tresetPosition,\n\t\t]\n\t)\n\n\t// Track unread messages when collapsed\n\tuseEffect(() => {\n\t\tconst currentCount = messages?.length ?? 0\n\t\tif (userMode === 'collapsed' && currentCount > lastMessageCountRef.current) {\n\t\t\tmarkUnread()\n\t\t}\n\t\tlastMessageCountRef.current = currentCount\n\t}, [messages?.length, userMode, markUnread])\n\n\t// Clear unread when expanded\n\tuseEffect(() => {\n\t\tif (userMode !== 'collapsed') {\n\t\t\tmarkRead()\n\t\t}\n\t}, [userMode, markRead])\n\n\t// Voice border status for animations\n\tconst voiceBorderStatus = useVoiceBorderStatus()\n\n\t// Voice mode is active when connected, connecting, or showing an error\n\tconst isVoiceModeActive = agentVoiceActive || isVoiceActive\n\n\t// Get border status - use voice status when in voice mode\n\tconst textBorderStatus = useToolBorderStatus(\n\t\t!!currentAction,\n\t\tlastCompletedAction?.status === 'success'\n\t\t\t? 'success'\n\t\t\t: lastCompletedAction?.status === 'error'\n\t\t\t\t? 'error'\n\t\t\t\t: null\n\t)\n\tconst borderStatus = isVoiceModeActive ? voiceBorderStatus : textBorderStatus\n\n\t// Determine actual mode based on state\n\tconst mode = useMemo((): PillMode => {\n\t\t// Voice mode is active - always show as active\n\t\tif (isVoiceModeActive) return 'active'\n\n\t\t// User explicitly collapsed\n\t\tif (userMode === 'collapsed') return 'collapsed'\n\t\tif (userMode === 'hovered') return 'hovered'\n\n\t\t// Agent is running or pending approval - show active mode\n\t\tif (isRunning || hasPendingApproval) return 'active'\n\n\t\t// Has messages (completed)\n\t\tif (hasMessages) return 'expanded'\n\n\t\t// User is composing\n\t\tif (userMode === 'composing') return 'composing'\n\n\t\treturn 'collapsed'\n\t}, [userMode, isRunning, hasMessages, isVoiceModeActive, hasPendingApproval])\n\n\t// Handle mode changes\n\tconst handleModeChange = useCallback(\n\t\t(newMode: PillMode) => {\n\t\t\tsetUserMode(newMode)\n\t\t},\n\t\t[setUserMode]\n\t)\n\n\t// Handle collapse - close back to collapsed state\n\tconst handleCollapse = useCallback(() => {\n\t\tsetUserMode('collapsed')\n\t}, [setUserMode])\n\n\t// Reset position when pill collapses (position only applies to expanded state)\n\tuseEffect(() => {\n\t\tif (mode === 'collapsed' || mode === 'hovered') {\n\t\t\tresetPosition()\n\t\t}\n\t}, [mode, resetPosition])\n\n\t// Auto-collapse after inactivity (only when expanded/composing and not running)\n\tuseEffect(() => {\n\t\tif (!autoCollapse) return\n\n\t\t// Clear existing timeout\n\t\tif (autoCollapseTimeoutRef.current) {\n\t\t\tclearTimeout(autoCollapseTimeoutRef.current)\n\t\t\tautoCollapseTimeoutRef.current = null\n\t\t}\n\n\t\t// Only auto-collapse when in composing or expanded mode (not active/running)\n\t\tif (mode === 'composing' || (mode === 'expanded' && !isRunning)) {\n\t\t\tautoCollapseTimeoutRef.current = setTimeout(() => {\n\t\t\t\tsetUserMode('collapsed')\n\t\t\t}, AUTO_COLLAPSE_TIMEOUT_MS)\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (autoCollapseTimeoutRef.current) {\n\t\t\t\tclearTimeout(autoCollapseTimeoutRef.current)\n\t\t\t}\n\t\t}\n\t}, [mode, isRunning, autoCollapse, setUserMode])\n\n\t// Handle voice toggle\n\tconst handleVoiceToggle = useCallback(() => {\n\t\tif (voice) {\n\t\t\tif (voice.isActive || voice.isConnecting) {\n\t\t\t\tvoice.stop()\n\t\t\t} else {\n\t\t\t\tvoid voice.start()\n\t\t\t}\n\t\t}\n\t\tonVoiceToggle?.()\n\t}, [voice, onVoiceToggle])\n\n\t// Handle prompt selection - expand pill and send prompt content\n\tconst handlePromptSelect = useCallback(\n\t\tasync (prompt: Prompt) => {\n\t\t\t// Expand the pill to composing mode\n\t\t\tsetUserMode('composing')\n\n\t\t\tif (!getPrompt) return\n\n\t\t\ttry {\n\t\t\t\t// Get the expanded prompt content\n\t\t\t\tconst result = await getPrompt(prompt.name)\n\n\t\t\t\t// Find the first user message in the prompt result\n\t\t\t\tconst userMessage = result.messages?.find(\n\t\t\t\t\t(m: { role: string; content: unknown }) => m.role === 'user'\n\t\t\t\t)\n\t\t\t\tif (userMessage) {\n\t\t\t\t\t// Extract text content from the message\n\t\t\t\t\tlet textContent = ''\n\t\t\t\t\tif (typeof userMessage.content === 'string') {\n\t\t\t\t\t\ttextContent = userMessage.content\n\t\t\t\t\t} else if (userMessage.content.type === 'text') {\n\t\t\t\t\t\ttextContent = userMessage.content.text\n\t\t\t\t\t}\n\n\t\t\t\t\tif (textContent) {\n\t\t\t\t\t\t// Set the composer text and send\n\t\t\t\t\t\tcomposerRuntime.setText(textContent)\n\t\t\t\t\t\tcomposerRuntime.send()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tdebugLog('AgentPill', 'Failed to get prompt', err)\n\t\t\t}\n\t\t},\n\t\t[getPrompt, composerRuntime, setUserMode]\n\t)\n\n\t// Handle elicitation denial with reason (user tells Char what to do differently)\n\tconst handleElicitationDeny = useCallback(\n\t\t(reason: string) => {\n\t\t\tif (pendingToolCalls.length > 0) {\n\t\t\t\tconst firstTool = pendingToolCalls[0]\n\t\t\t\tconst message = formatToolDenialWithReason(reason)\n\t\t\t\tresolvePendingToolCall(threadRuntime, firstTool.messageId, firstTool.toolCallId, message)\n\t\t\t}\n\t\t},\n\t\t[pendingToolCalls, threadRuntime]\n\t)\n\n\t// Get border radius for current mode\n\tconst borderRadius =\n\t\tmode === 'collapsed' || mode === 'hovered'\n\t\t\t? PILL_BORDER_RADIUS.pill\n\t\t\t: PILL_BORDER_RADIUS.rounded\n\n\t// Check if pill is expanded (can be collapsed and can be dragged)\n\tconst isExpanded = mode === 'composing' || mode === 'active' || mode === 'expanded'\n\n\t// Pinch gesture for mobile expand/collapse to full-screen\n\tconst { handlers: pinchHandlers } = usePinchGesture({\n\t\tonPinchOut: () => {\n\t\t\tif (isExpanded && !isFullScreen && !isVoiceModeActive) {\n\t\t\t\tenterFullScreen()\n\t\t\t}\n\t\t},\n\t\tonPinchIn: () => {\n\t\t\tif (isFullScreen) {\n\t\t\t\texitFullScreen()\n\t\t\t}\n\t\t},\n\t\tenabled: isMobile && (isExpanded || isFullScreen),\n\t})\n\n\t// Deferred composer mount - delays rendering PillComposer until container animation settles\n\t// This fixes a bug where react-textarea-autosize measures wrong height during width animation\n\tconst [isComposerReady, setComposerReady] = useState(false)\n\tuseEffect(() => {\n\t\tif (isExpanded) {\n\t\t\tconst timer = setTimeout(() => setComposerReady(true), 200) // Wait for spring to settle\n\t\t\treturn () => {\n\t\t\t\tclearTimeout(timer)\n\t\t\t\tsetComposerReady(false)\n\t\t\t}\n\t\t} else {\n\t\t\tsetComposerReady(false)\n\t\t}\n\t}, [isExpanded])\n\n\t// Handle Escape key to exit full-screen\n\tuseEffect(() => {\n\t\tif (!isFullScreen) return\n\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\t\tif (e.key === 'Escape') {\n\t\t\t\te.preventDefault()\n\t\t\t\texitFullScreen()\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('keydown', handleKeyDown)\n\t\treturn () => window.removeEventListener('keydown', handleKeyDown)\n\t}, [isFullScreen, exitFullScreen])\n\n\treturn (\n\t\t<>\n\t\t\t{/* Drag constraints - full viewport */}\n\t\t\t<div ref={constraintsRef} className=\"fixed inset-0 pointer-events-none\" />\n\n\t\t\t<ThreadPrimitive.Root\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'fixed z-50 bottom-safe pb-safe',\n\t\t\t\t\tposition === 'bottom-center' && 'left-1/2 -translate-x-1/2',\n\t\t\t\t\tposition === 'bottom-right' && 'right-4',\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<motion.div\n\t\t\t\t\t// Allow dragging when expanded (including full-screen mode)\n\t\t\t\t\tdrag={isExpanded}\n\t\t\t\t\tdragControls={dragControls}\n\t\t\t\t\tdragConstraints={constraintsRef}\n\t\t\t\t\tdragElastic={0.15}\n\t\t\t\t\tdragMomentum={false}\n\t\t\t\t\t// High transparency while dragging lets user see underlying content (useful for reference)\n\t\t\t\t\twhileDrag={{ scale: 1.02, opacity: DRAG_OPACITY.dragging }}\n\t\t\t\t\tonDragEnd={handleDragEnd}\n\t\t\t\t\t// Keyboard positioning: snap to fixed center position above keyboard\n\t\t\t\t\t// This ensures consistent, predictable placement every time keyboard appears\n\t\t\t\t\t// When keyboard hides: restore the user's previous drag position\n\t\t\t\t\tinitial={false}\n\t\t\t\t\tanimate={{\n\t\t\t\t\t\tx: isExpanded ? (isKeyboardVisible ? 0 : dragPosition.x) : 0,\n\t\t\t\t\t\ty: isExpanded\n\t\t\t\t\t\t\t? isKeyboardVisible\n\t\t\t\t\t\t\t\t? -keyboardHeight - KEYBOARD_GAP_PX\n\t\t\t\t\t\t\t\t: dragPosition.y\n\t\t\t\t\t\t\t: 0,\n\t\t\t\t\t}}\n\t\t\t\t\ttransition={{ type: 'spring', stiffness: 400, damping: 30 }}\n\t\t\t\t\tclassName={cn('relative', isExpanded && 'cursor-grab active:cursor-grabbing')}\n\t\t\t\t\t// Prevent touch events from affecting underlying page scroll (only when expanded)\n\t\t\t\t\tstyle={{ touchAction: isExpanded || isFullScreen ? 'none' : 'auto' }}\n\t\t\t\t\t// Pinch gesture handlers for mobile\n\t\t\t\t\t{...pinchHandlers}\n\t\t\t\t>\n\t\t\t\t\t{/* Prompt badge - floating above collapsed pill when prompts exist */}\n\t\t\t\t\t{mode === 'collapsed' && prompts.length > 0 && (\n\t\t\t\t\t\t<PromptBadge prompts={prompts} onSelect={handlePromptSelect} />\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Unread indicator dot - shown when collapsed with unread messages */}\n\t\t\t\t\t{mode === 'collapsed' && hasUnread && (\n\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\tinitial={{ scale: 0 }}\n\t\t\t\t\t\t\tanimate={{ scale: 1 }}\n\t\t\t\t\t\t\tclassName=\"absolute -top-1 -right-1 w-2 h-2 bg-blue-500 rounded-full z-10\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\n\t\t\t\t\t<ToolStatusBorder status={borderStatus} borderRadius={borderRadius}>\n\t\t\t\t\t\t<PillContainer mode={mode} onModeChange={handleModeChange} isFullScreen={isFullScreen}>\n\t\t\t\t\t\t\t{/* Header with drag handle and close button - shown when expanded or in voice mode */}\n\t\t\t\t\t\t\t{(isVoiceModeActive || isExpanded) && (\n\t\t\t\t\t\t\t\t<div className=\"flex items-center justify-between mb-1 -mt-1\">\n\t\t\t\t\t\t\t\t\t{/* Drag handle - visual affordance for repositioning */}\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName=\"flex items-center text-white/30 p-1 -m-1 cursor-grab active:cursor-grabbing\"\n\t\t\t\t\t\t\t\t\t\tonPointerDown={(e) => dragControls.start(e)}\n\t\t\t\t\t\t\t\t\t\taria-label={ARIA_LABELS.dragHandle}\n\t\t\t\t\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\t\t\t\t\ttabIndex={0}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t<GripHorizontal className=\"h-4 w-4 sm:h-3 sm:w-3\" />\n\t\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t\t{/* Right side controls */}\n\t\t\t\t\t\t\t\t\t<div className=\"flex items-center gap-2 sm:gap-1\">\n\t\t\t\t\t\t\t\t\t\t{/* Expand/Minimize button - desktop only, not in voice mode */}\n\t\t\t\t\t\t\t\t\t\t{!isMobile && !isVoiceModeActive && (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={isFullScreen ? exitFullScreen : enterFullScreen}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'min-w-7 min-h-7',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'p-1 rounded-full',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'hover:bg-white/10 active:bg-white/20',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'text-white/40 hover:text-white/70',\n\t\t\t\t\t\t\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\t\tisFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ARIA_LABELS.collapseFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ARIA_LABELS.expandFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{isFullScreen ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Minimize className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<Expand className=\"h-3.5 w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t\t{/* Approval mode toggle */}\n\t\t\t\t\t\t\t\t\t\t<ApprovalModeIndicator />\n\n\t\t\t\t\t\t\t\t\t\t{/* Close button - larger touch target on mobile (min 44px for AAA) */}\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tonClick={\n\t\t\t\t\t\t\t\t\t\t\t\tisVoiceModeActive\n\t\t\t\t\t\t\t\t\t\t\t\t\t? handleVoiceToggle\n\t\t\t\t\t\t\t\t\t\t\t\t\t: isFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? exitFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: handleCollapse\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t// Touch target: 44px on mobile (AAA), 28px on desktop\n\t\t\t\t\t\t\t\t\t\t\t\t'min-w-11 min-h-11 sm:min-w-7 sm:min-h-7',\n\t\t\t\t\t\t\t\t\t\t\t\t'flex items-center justify-center',\n\t\t\t\t\t\t\t\t\t\t\t\t'p-2 sm:p-1 rounded-full',\n\t\t\t\t\t\t\t\t\t\t\t\t'hover:bg-white/10 active:bg-white/20',\n\t\t\t\t\t\t\t\t\t\t\t\t'text-white/40 hover:text-white/70',\n\t\t\t\t\t\t\t\t\t\t\t\t'transition-colors duration-150'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\tisVoiceModeActive\n\t\t\t\t\t\t\t\t\t\t\t\t\t? ARIA_LABELS.endVoiceSession\n\t\t\t\t\t\t\t\t\t\t\t\t\t: isFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t? ARIA_LABELS.collapseFullScreen\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t: ARIA_LABELS.closeAssistant\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<X className=\"h-5 w-5 sm:h-3.5 sm:w-3.5\" />\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Voice mode UI - when voice is active (not in full-screen) */}\n\t\t\t\t\t\t\t{!isFullScreen && (\n\t\t\t\t\t\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t\t\t\t\t\t{isVoiceModeActive && <PillVoice key=\"voice-mode\" onEnd={handleVoiceToggle} />}\n\t\t\t\t\t\t\t\t</AnimatePresence>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{/* Main content - simple flex column, scrolling handled by PillContainer */}\n\t\t\t\t\t\t\t{!isVoiceModeActive && (\n\t\t\t\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t\t\t\t{/* Welcome message - composing without messages */}\n\t\t\t\t\t\t\t\t\t{mode === 'composing' && !hasMessages && <WelcomeMessage />}\n\n\t\t\t\t\t\t\t\t\t{/* Summary - when completed */}\n\t\t\t\t\t\t\t\t\t{mode === 'expanded' && !isRunning && summary && (\n\t\t\t\t\t\t\t\t\t\t<SummaryBlock\n\t\t\t\t\t\t\t\t\t\t\tsummary={summary}\n\t\t\t\t\t\t\t\t\t\t\tisSuccess={!lastCompletedAction?.error}\n\t\t\t\t\t\t\t\t\t\t\tisFullScreen={isFullScreen}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Streaming response - shows text as it's being generated */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') && isRunning && (\n\t\t\t\t\t\t\t\t\t\t<StreamingResponse isFullScreen={isFullScreen} />\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Idle indicator - when expanded but no activity */}\n\t\t\t\t\t\t\t\t\t{mode === 'expanded' && !isRunning && !summary && <IdleIndicator />}\n\n\t\t\t\t\t\t\t\t\t{/* Tool UIs in collapsible, scrollable section */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') && (\n\t\t\t\t\t\t\t\t\t\t<PillToolsSection\n\t\t\t\t\t\t\t\t\t\t\tdefaultCollapsed={mode === 'active' && !isFullScreen}\n\t\t\t\t\t\t\t\t\t\t\tisFullScreen={isFullScreen}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Prompt suggestions - inline chips when expanded and not running (hidden in full-screen) */}\n\t\t\t\t\t\t\t\t\t{!isFullScreen &&\n\t\t\t\t\t\t\t\t\t\t(mode === 'composing' || mode === 'expanded') &&\n\t\t\t\t\t\t\t\t\t\t!isRunning &&\n\t\t\t\t\t\t\t\t\t\t!hasPendingApproval &&\n\t\t\t\t\t\t\t\t\t\tprompts.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t\t<PromptSuggestions prompts={prompts} onSelect={handlePromptSelect} />\n\t\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Elicitation buttons - above composer when approval is needed */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') && hasPendingApproval && (\n\t\t\t\t\t\t\t\t\t\t<ElicitationButtonBar />\n\t\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t\t{/* Activity indicator - shows what agent is doing when running */}\n\t\t\t\t\t\t\t\t\t{(mode === 'active' || mode === 'expanded') &&\n\t\t\t\t\t\t\t\t\t\tisRunning &&\n\t\t\t\t\t\t\t\t\t\t!hasPendingApproval && <ActivityIndicator />}\n\n\t\t\t\t\t\t\t\t\t{/* Composer - always visible when expanded (no longer hidden during approval) */}\n\t\t\t\t\t\t\t\t\t<AnimatePresence>\n\t\t\t\t\t\t\t\t\t\t{isComposerReady &&\n\t\t\t\t\t\t\t\t\t\t\t(mode === 'composing' || mode === 'active' || mode === 'expanded') && (\n\t\t\t\t\t\t\t\t\t\t\t\t<motion.div\n\t\t\t\t\t\t\t\t\t\t\t\t\tinitial={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\tanimate={{ opacity: 1 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\texit={{ opacity: 0 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\ttransition={{ duration: 0.15 }}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"mt-1.5\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<PillComposer\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tshowVoiceButton={showVoiceButton || !!voice?.isSupported}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisVoiceActive={isVoiceActive}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonVoiceToggle={handleVoiceToggle}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tisEliciting={hasPendingApproval}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonElicitationSubmit={handleElicitationDeny}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t</motion.div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</AnimatePresence>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</PillContainer>\n\t\t\t\t\t</ToolStatusBorder>\n\t\t\t\t</motion.div>\n\t\t\t</ThreadPrimitive.Root>\n\t\t</>\n\t)\n}\n\nexport default AgentPill\n","/**\n * AgentProvider\n *\n * Unified provider that wraps all agent infrastructure:\n * - AgentUIProvider (non-thread UI state: open/close, position)\n * - MCPToolsProvider (tool registry and execution)\n * - AssistantRuntimeProvider (chat runtime - single source of truth for thread)\n * - VoiceThreadBridge (voice mode integrated with thread)\n *\n * This is the single entry point for setting up agent capabilities.\n * Widgets (Pill, Modal) and custom UIs should be wrapped by this provider.\n *\n * Architecture:\n * ```\n * AgentUIProvider (UI state - persists across threads)\n * └── MCPToolsProvider (tools - shared across threads)\n * └── AssistantRuntimeProvider (thread state - single source of truth)\n * └── VoiceThreadBridge (voice → thread integration)\n * └── MCPToolRegistry\n * └── children\n * ```\n *\n * @example Basic usage\n * ```tsx\n * import { AgentProvider, AgentPill } from '@mcp-b/embedded-agent'\n *\n * function App() {\n * return (\n * <AgentProvider apiBase=\"https://your-worker.workers.dev\">\n * <AgentPill />\n * </AgentProvider>\n * )\n * }\n * ```\n *\n * @example Headless usage (custom UI)\n * ```tsx\n * import { AgentProvider, useAgent } from '@mcp-b/embedded-agent'\n *\n * function CustomUI() {\n * const agent = useAgent()\n * return <div>{agent.messages.map(m => ...)}</div>\n * }\n *\n * function App() {\n * return (\n * <AgentProvider apiBase=\"https://...\">\n * <CustomUI />\n * </AgentProvider>\n * )\n * }\n * ```\n */\n\nimport { AssistantRuntimeProvider } from '@assistant-ui/react'\nimport { AssistantChatTransport, useChatRuntime } from '@assistant-ui/react-ai-sdk'\nimport { lastAssistantMessageIsCompleteWithToolCalls } from 'ai'\nimport { useMemo } from 'react'\n\nimport { MCPToolRegistry } from '../../components/MCPToolRegistry'\nimport { WEBMCP_PRODUCTION_API_BASE } from '../../lib/constants'\nimport { MCPToolsProvider } from '../../providers/MCPToolsProvider'\nimport { ToolApprovalProvider } from '../../providers/ToolApprovalProvider'\nimport { VoiceThreadBridge } from '../../providers/VoiceThreadBridge'\nimport { AgentUIProvider } from './AgentUIProvider'\n\nimport type { ToolApprovalMode, ToolWithSource } from '@mcp-b/cloud-mirror-types'\nimport type { FC, ReactNode } from 'react'\nimport type { PillMode } from './AgentUIProvider'\n\nexport interface AgentProviderProps {\n\tchildren: ReactNode\n\n\t/** API base URL for chat and token endpoints (defaults to production WebMCP API) */\n\tapiBase?: string\n\n\t/** Voice mode token endpoint (defaults to {apiBase}/api/realtime/session) */\n\ttokenEndpoint?: string\n\n\t/** Auto-connect to local MCP source (default: true) */\n\tautoConnectLocal?: boolean\n\n\t/** Initial open state for UI (default: false) */\n\tdefaultOpen?: boolean\n\n\t/** Initial pill mode (default: 'collapsed') */\n\tdefaultMode?: PillMode\n\n\t/** Initial tool approval mode: 'ask' requires confirmation, 'auto' executes immediately (default: 'ask') */\n\tdefaultApprovalMode?: ToolApprovalMode\n\n\t/** Callback when MCP tools change */\n\tonToolsChange?: (tools: ToolWithSource[]) => void\n\n\t/** Callback when voice mode errors */\n\tonVoiceError?: (error: string) => void\n\n\t/** Callback when voice mode connects */\n\tonVoiceConnect?: () => void\n\n\t/** Callback when voice mode disconnects */\n\tonVoiceDisconnect?: (duration: number) => void\n\n\t/** Callback when UI open state changes */\n\tonOpenChange?: (open: boolean) => void\n\n\t/** Callback when pill mode changes */\n\tonModeChange?: (mode: PillMode) => void\n\n\t/** Callback when tool approval mode changes */\n\tonApprovalModeChange?: (mode: ToolApprovalMode) => void\n}\n\n/**\n * Internal component that sets up the chat runtime and voice bridge.\n * Must be inside MCPToolsProvider so VoiceThreadBridge can access tools.\n */\ninterface AgentRuntimeProps {\n\tchildren: ReactNode\n\tapiBase?: string\n\ttokenEndpoint?: string\n\tonVoiceError?: (error: string) => void\n\tonVoiceConnect?: () => void\n\tonVoiceDisconnect?: (duration: number) => void\n}\n\nconst AgentRuntime: FC<AgentRuntimeProps> = ({\n\tchildren,\n\tapiBase,\n\ttokenEndpoint,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n}) => {\n\t// Resolve API base (defaults to production)\n\tconst resolvedApiBase = apiBase ?? WEBMCP_PRODUCTION_API_BASE\n\n\t// Create transport with API endpoint\n\tconst transport = useMemo(() => {\n\t\tconst chatApi = `${resolvedApiBase}/api/chat`\n\t\treturn new AssistantChatTransport({ api: chatApi })\n\t}, [resolvedApiBase])\n\n\tconst runtime = useChatRuntime({\n\t\ttransport,\n\t\tsendAutomaticallyWhen: (messages) => {\n\t\t\treturn lastAssistantMessageIsCompleteWithToolCalls(messages)\n\t\t},\n\t})\n\n\t// Compute token endpoint from apiBase if not explicitly provided\n\tconst resolvedTokenEndpoint = tokenEndpoint || `${resolvedApiBase}/api/realtime/session`\n\n\treturn (\n\t\t<AssistantRuntimeProvider runtime={runtime}>\n\t\t\t<VoiceThreadBridge\n\t\t\t\ttokenEndpoint={resolvedTokenEndpoint}\n\t\t\t\tonError={onVoiceError}\n\t\t\t\tonConnect={onVoiceConnect}\n\t\t\t\tonDisconnect={onVoiceDisconnect}\n\t\t\t>\n\t\t\t\t<MCPToolRegistry />\n\t\t\t\t{children}\n\t\t\t</VoiceThreadBridge>\n\t\t</AssistantRuntimeProvider>\n\t)\n}\n\n/**\n * Unified provider for all agent capabilities.\n *\n * Provides:\n * - UI state (open/close, position) via AgentUIProvider\n * - MCP tool registry and execution via MCPToolsProvider\n * - Tool approval settings via ToolApprovalProvider\n * - Chat runtime (via @assistant-ui/react) - single source of truth for thread\n * - Voice mode integrated with thread (via VoiceThreadBridge)\n *\n * Use the `useAgent` hook to access agent state and capabilities.\n * Use the `useAgentUI` hook to access UI state (open/close, mode, position).\n * Use the `useToolApproval` hook to access tool approval settings.\n */\nexport const AgentProvider: FC<AgentProviderProps> = ({\n\tchildren,\n\tapiBase,\n\ttokenEndpoint,\n\tautoConnectLocal = true,\n\tdefaultOpen = false,\n\tdefaultMode = 'collapsed',\n\tdefaultApprovalMode,\n\tonToolsChange,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n\tonOpenChange,\n\tonModeChange,\n\tonApprovalModeChange,\n}) => {\n\treturn (\n\t\t<AgentUIProvider\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tdefaultMode={defaultMode}\n\t\t\tonOpenChange={onOpenChange}\n\t\t\tonModeChange={onModeChange}\n\t\t>\n\t\t\t<ToolApprovalProvider defaultMode={defaultApprovalMode} onModeChange={onApprovalModeChange}>\n\t\t\t\t<MCPToolsProvider autoConnectLocal={autoConnectLocal} onToolsChange={onToolsChange}>\n\t\t\t\t\t<AgentRuntime\n\t\t\t\t\t\tapiBase={apiBase}\n\t\t\t\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\t\t\t\tonVoiceError={onVoiceError}\n\t\t\t\t\t\tonVoiceConnect={onVoiceConnect}\n\t\t\t\t\t\tonVoiceDisconnect={onVoiceDisconnect}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</AgentRuntime>\n\t\t\t\t</MCPToolsProvider>\n\t\t\t</ToolApprovalProvider>\n\t\t</AgentUIProvider>\n\t)\n}\n","/**\n * Auto-generated file - DO NOT EDIT\n * Generated by scripts/generate-inline-styles.js\n *\n * Contains the compiled CSS for the web component standalone build.\n */\n\nexport const WEBMCP_STYLES = \"/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tool-border-angle:0deg}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\",\\\"Noto Color Emoji\\\";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\\\"Liberation Mono\\\",\\\"Courier New\\\",monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-indigo-500:oklch(58.5% .233 277.117);--color-purple-600:oklch(55.8% .288 302.321);--color-slate-900:oklch(20.8% .042 265.755);--color-zinc-50:oklch(98.5% 0 0);--color-zinc-100:oklch(96.7% .001 286.375);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-600:oklch(44.2% .017 285.786);--color-zinc-700:oklch(37% .013 285.805);--color-zinc-800:oklch(27.4% .006 286.033);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-xs:.125rem;--ease-out:cubic-bezier(0,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\",\\\"Noto Color Emoji\\\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\\\"Liberation Mono\\\",\\\"Courier New\\\",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--radius:.75rem;--background:oklch(100% 0 0);--foreground:oklch(14.1% .005 285.823);--card:oklch(100% 0 0);--card-foreground:oklch(14.1% .005 285.823);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.1% .005 285.823);--primary:oklch(21% .006 285.885);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(96.7% .001 286.375);--secondary-foreground:oklch(21% .006 285.885);--muted:oklch(96.7% .001 286.375);--muted-foreground:oklch(55.2% .016 285.938);--accent:oklch(96.7% .001 286.375);--accent-foreground:oklch(21% .006 285.885);--destructive:oklch(57.7% .245 27.325);--destructive-foreground:oklch(98.5% 0 0);--border:oklch(92% .004 286.32);--input:oklch(92% .004 286.32);--ring:oklch(70.5% .015 286.067)}.dark{--background:oklch(14.1% .005 285.823);--foreground:oklch(98.5% 0 0);--card:oklch(21% .006 285.885);--card-foreground:oklch(98.5% 0 0);--popover:oklch(21% .006 285.885);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92% .004 286.32);--primary-foreground:oklch(21% .006 285.885);--secondary:oklch(27.4% .006 286.033);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(27.4% .006 286.033);--muted-foreground:oklch(70.5% .015 286.067);--accent:oklch(27.4% .006 286.033);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--destructive-foreground:oklch(98.5% 0 0);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.2% .016 285.938)}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklch,var(--ring),transparent 50%)}}body{background-color:var(--background);color:var(--foreground)}}@layer components{.app-shell{z-index:0;background-color:var(--background);background-image:radial-gradient(80% 60% at -10% -10%,oklch(82% .15 270/.15),#0000),radial-gradient(60% 50% at 110% 10%,oklch(85% .1 220/.12),#0000),radial-gradient(50% 45% at 50% 120%,oklch(95% .02 250/.08),#0000);position:relative}.dark .app-shell{background-image:radial-gradient(80% 60% at -10% -10%,oklch(55% .14 270/.25),#0000),radial-gradient(60% 50% at 110% 15%,oklch(60% .12 220/.22),#0000),radial-gradient(50% 45% at 50% 120%,oklch(35% .04 250/.16),#0000)}.app-shell:before,.app-shell:after{content:\\\"\\\";pointer-events:none;filter:blur(32px);opacity:.6;z-index:-1;border-radius:9999px;position:absolute;inset:auto}.app-shell:before{background:radial-gradient(60% 60% at 40% 40%,oklch(80% .12 270/.3),#0000);width:260px;height:260px;top:-60px;left:-80px}.app-shell:after{background:radial-gradient(60% 60% at 60% 60%,oklch(84% .1 220/.25),#0000);width:300px;height:300px;bottom:-80px;right:-60px}.toolbar-surface{border-top:1px solid var(--border);background:linear-gradient(to right,var(--background),var(--background),var(--background))}@supports (color:color-mix(in lab, red, red)){.toolbar-surface{background:linear-gradient(to right,var(--background),color-mix(in oklch,var(--background),transparent 5%),var(--background))}}.toolbar-surface{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.toolbar-surface{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.toolbar-surface{background:color-mix(in oklch,var(--background),transparent 20%)}}}.toolbar-surface-top{border-bottom:1px solid var(--border);background:linear-gradient(to right,var(--background),var(--background),var(--background))}@supports (color:color-mix(in lab, red, red)){.toolbar-surface-top{background:linear-gradient(to right,var(--background),color-mix(in oklch,var(--background),transparent 5%),var(--background))}}.toolbar-surface-top{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.toolbar-surface-top{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.toolbar-surface-top{background:color-mix(in oklch,var(--background),transparent 20%)}}}.toolbar-inner{justify-content:space-between;align-items:center;padding:.5rem .75rem;display:flex}.toolbar-card{background:var(--card);justify-content:space-between;align-items:center;gap:.5rem;display:flex}@supports (color:color-mix(in lab, red, red)){.toolbar-card{background:color-mix(in oklch,var(--card),transparent 60%)}}.toolbar-card{border:1px solid var(--border);border-radius:.75rem;padding:.5rem .75rem}.toolbar-group{align-items:center;gap:.25rem;display:flex}.btn-toolbar-primary{background:linear-gradient(to right,var(--primary),var(--primary));border-radius:.75rem;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;display:flex}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary{background:linear-gradient(to right,color-mix(in oklch,var(--primary),transparent 95%),color-mix(in oklch,var(--primary),transparent 90%))}}.btn-toolbar-primary{border:1px solid var(--primary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary{border:1px solid color-mix(in oklch,var(--primary),transparent 80%)}}.btn-toolbar-primary{transition:all .2s}.btn-toolbar-primary:hover{background:linear-gradient(to right,var(--primary),var(--primary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary:hover{background:linear-gradient(to right,color-mix(in oklch,var(--primary),transparent 90%),color-mix(in oklch,var(--primary),transparent 80%))}}.btn-toolbar-icon-primary{background:linear-gradient(to bottom right,var(--primary),var(--primary));border-radius:9999px;width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--primary),transparent 90%),color-mix(in oklch,var(--primary),transparent 80%))}}.btn-toolbar-icon-primary{border:1px solid var(--primary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary{border:1px solid color-mix(in oklch,var(--primary),transparent 70%)}}.btn-toolbar-icon-primary{transition:all .2s;box-shadow:0 1px 2px #0000000d}.btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,var(--primary),var(--primary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--primary),transparent 80%),color-mix(in oklch,var(--primary),transparent 70%))}}.btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,var(--secondary),var(--secondary));border-radius:9999px;width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--secondary),transparent 90%),color-mix(in oklch,var(--secondary),transparent 80%))}}.btn-toolbar-icon-secondary{border:1px solid var(--secondary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary{border:1px solid color-mix(in oklch,var(--secondary),transparent 70%)}}.btn-toolbar-icon-secondary{transition:all .2s;box-shadow:0 1px 2px #0000000d}.btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,var(--secondary),var(--secondary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--secondary),transparent 80%),color-mix(in oklch,var(--secondary),transparent 70%))}}.badge-compact{height:1.25rem;padding:0 .5rem;font-size:10px}.badge-mini{height:1rem;padding:0 .375rem;font-size:10px}@keyframes shimmer-bg{0%{background-position:-1000px 0}to{background-position:1000px 0}}.shimmer{background:linear-gradient(90deg,#0000,#ffffff1a,#0000) 0 0/1000px 100%;animation:3s linear infinite shimmer-bg}.animate-shimmer{animation:2s linear infinite shimmer}@keyframes pulse-glow{0%,to{box-shadow:0 0 20px rgba(var(--primary),.1)}50%{box-shadow:0 0 30px rgba(var(--primary),.2)}}.pulse-glow{animation:2s ease-in-out infinite pulse-glow}@keyframes gradient-x{0%,to{background-position:0%}50%{background-position:100%}}.animate-gradient-x{animation:8s ease-in-out infinite gradient-x}.gradient-text{background:linear-gradient(to right,var(--foreground),var(--foreground))}@supports (color:color-mix(in lab, red, red)){.gradient-text{background:linear-gradient(to right,var(--foreground),color-mix(in oklch,var(--foreground),transparent 30%))}}.gradient-text{-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.glass{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.glass{background:color-mix(in oklch,var(--background),transparent 50%)}}.glass{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border)}@supports (color:color-mix(in lab, red, red)){.glass{border:1px solid color-mix(in oklch,var(--border),transparent 50%)}}.tool-card{transition:all .3s ease-out}.tool-card:hover{transform:scale(1.02);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.scrollbar-thin{scrollbar-width:thin}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-track{background:0 0}.scrollbar-thin::-webkit-scrollbar-thumb{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.scrollbar-thin::-webkit-scrollbar-thumb{background-color:color-mix(in oklch,var(--primary),transparent 80%)}}.scrollbar-thin::-webkit-scrollbar-thumb{border-radius:3px}.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:color-mix(in oklch,var(--primary),transparent 70%)}}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.-inset-\\\\[1px\\\\]{inset:-1px}.inset-0{inset:calc(var(--spacing)*0)}.-top-1{top:calc(var(--spacing)*-1)}.-top-1\\\\.5{top:calc(var(--spacing)*-1.5)}.top-1\\\\.5{top:calc(var(--spacing)*1.5)}.top-1\\\\/2{top:50%}.top-4{top:calc(var(--spacing)*4)}.top-\\\\[50\\\\%\\\\]{top:50%}.-right-0\\\\.5{right:calc(var(--spacing)*-.5)}.-right-1{right:calc(var(--spacing)*-1)}.-right-1\\\\.5{right:calc(var(--spacing)*-1.5)}.right-0{right:calc(var(--spacing)*0)}.right-1\\\\.5{right:calc(var(--spacing)*1.5)}.right-4{right:calc(var(--spacing)*4)}.-bottom-0\\\\.5{bottom:calc(var(--spacing)*-.5)}.bottom-full{bottom:100%}.left-0{left:calc(var(--spacing)*0)}.left-1\\\\/2,.left-\\\\[50\\\\%\\\\]{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.col-span-full{grid-column:1/-1}.col-start-1{grid-column-start:1}.row-start-1{grid-row-start:1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-m-1{margin:calc(var(--spacing)*-1)}.m-0{margin:calc(var(--spacing)*0)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.my-2{margin-block:calc(var(--spacing)*2)}.-mt-1{margin-top:calc(var(--spacing)*-1)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\\\\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-2\\\\.5{margin-top:calc(var(--spacing)*2.5)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mr-1\\\\.5{margin-right:calc(var(--spacing)*1.5)}.-mb-1{margin-bottom:calc(var(--spacing)*-1)}.mb-0\\\\.5{margin-bottom:calc(var(--spacing)*.5)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\\\\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-0\\\\.5{margin-left:calc(var(--spacing)*.5)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-2\\\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-14{width:calc(var(--spacing)*14);height:calc(var(--spacing)*14)}.size-\\\\[34px\\\\]{width:34px;height:34px}.size-full{width:100%;height:100%}.h-1\\\\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\\\\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\\\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-4\\\\.5{height:calc(var(--spacing)*4.5)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-11{height:calc(var(--spacing)*11)}.h-auto{height:auto}.h-full{height:100%}.max-h-24{max-height:calc(var(--spacing)*24)}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-40{max-height:calc(var(--spacing)*40)}.max-h-64{max-height:calc(var(--spacing)*64)}.max-h-\\\\[30vh\\\\]{max-height:30vh}.max-h-\\\\[80dvh\\\\]{max-height:80dvh}.max-h-\\\\[80vh\\\\]{max-height:80vh}.min-h-7{min-height:calc(var(--spacing)*7)}.min-h-11{min-height:calc(var(--spacing)*11)}.min-h-screen{min-height:100vh}.w-0\\\\.5{width:calc(var(--spacing)*.5)}.w-1\\\\.5{width:calc(var(--spacing)*1.5)}.w-2{width:calc(var(--spacing)*2)}.w-2\\\\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\\\\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-4\\\\.5{width:calc(var(--spacing)*4.5)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-11{width:calc(var(--spacing)*11)}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-24{max-width:calc(var(--spacing)*24)}.max-w-32{max-width:calc(var(--spacing)*32)}.max-w-\\\\[100px\\\\]{max-width:100px}.max-w-\\\\[calc\\\\(100\\\\%-2rem\\\\)\\\\]{max-width:calc(100% - 2rem)}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-7{min-width:calc(var(--spacing)*7)}.min-w-11{min-width:calc(var(--spacing)*11)}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.border-separate{border-collapse:separate}.border-spacing-0{--tw-border-spacing-x:calc(var(--spacing)*0);--tw-border-spacing-y:calc(var(--spacing)*0);border-spacing:var(--tw-border-spacing-x)var(--tw-border-spacing-y)}.origin-\\\\(--radix-tooltip-content-transform-origin\\\\){transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-1\\\\/2{--tw-translate-x:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-\\\\[-50\\\\%\\\\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\\\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\\\\[-50\\\\%\\\\]{--tw-translate-y:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\\\\[calc\\\\(-50\\\\%_-_2px\\\\)\\\\]{--tw-translate-y:calc(-50% - 2px);translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-75{--tw-scale-x:75%;--tw-scale-y:75%;--tw-scale-z:75%;scale:var(--tw-scale-x)var(--tw-scale-y)}.scale-100{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.rotate-45{rotate:45deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.resize-none{resize:none}.scroll-m-20{scroll-margin:calc(var(--spacing)*20)}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-rows-\\\\[0fr\\\\]{grid-template-rows:0fr}.grid-rows-\\\\[1fr\\\\]{grid-template-rows:1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\\\\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\\\\[2px\\\\]{border-radius:2px}.rounded-\\\\[14px\\\\]{border-radius:14px}.rounded-\\\\[inherit\\\\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-none{border-radius:0}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-xs{border-radius:var(--radius-xs)}.\\\\!rounded-t-none{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-t-lg{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius)}.rounded-b-lg{border-bottom-right-radius:var(--radius);border-bottom-left-radius:var(--radius)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-amber-500\\\\/30{border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\\\/30{border-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.border-amber-500\\\\/50{border-color:#f99c0080}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\\\/50{border-color:color-mix(in oklab,var(--color-amber-500)50%,transparent)}}.border-blue-500\\\\/20{border-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\\\/20{border-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.border-blue-500\\\\/30{border-color:#3080ff4d}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\\\/30{border-color:color-mix(in oklab,var(--color-blue-500)30%,transparent)}}.border-border{border-color:var(--border)}.border-foreground\\\\/20{border-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.border-foreground\\\\/20{border-color:color-mix(in oklab,var(--foreground)20%,transparent)}}.border-input{border-color:var(--input)}.border-muted-foreground\\\\/20{border-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-muted-foreground\\\\/20{border-color:color-mix(in oklab,var(--muted-foreground)20%,transparent)}}.border-transparent{border-color:#0000}.border-white\\\\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/5{border-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.border-white\\\\/8{border-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/8{border-color:color-mix(in oklab,var(--color-white)8%,transparent)}}.border-white\\\\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.border-white\\\\/20{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.border-white\\\\/20{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.border-zinc-200{border-color:var(--color-zinc-200)}.border-zinc-200\\\\/80{border-color:#e4e4e7cc}@supports (color:color-mix(in lab, red, red)){.border-zinc-200\\\\/80{border-color:color-mix(in oklab,var(--color-zinc-200)80%,transparent)}}.border-zinc-600{border-color:var(--color-zinc-600)}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\\\\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\\\/10{background-color:color-mix(in oklab,var(--color-amber-500)10%,transparent)}}.bg-amber-500\\\\/20{background-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\\\/20{background-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.bg-background{background-color:var(--background)}.bg-black{background-color:var(--color-black)}.bg-black\\\\/30{background-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.bg-black\\\\/30{background-color:color-mix(in oklab,var(--color-black)30%,transparent)}}.bg-black\\\\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\\\\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-blue-400{background-color:var(--color-blue-400)}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-500\\\\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\\\\/10{background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.bg-border{background-color:var(--border)}.bg-destructive{background-color:var(--destructive)}.bg-foreground{background-color:var(--foreground)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-400\\\\/60{background-color:#05df7299}@supports (color:color-mix(in lab, red, red)){.bg-green-400\\\\/60{background-color:color-mix(in oklab,var(--color-green-400)60%,transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\\\\/10{background-color:#00c7581a}@supports (color:color-mix(in lab, red, red)){.bg-green-500\\\\/10{background-color:color-mix(in oklab,var(--color-green-500)10%,transparent)}}.bg-muted{background-color:var(--muted)}.bg-muted-foreground\\\\/15{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\\\/15{background-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.bg-muted\\\\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/50{background-color:color-mix(in oklab,var(--muted)50%,transparent)}}.bg-primary{background-color:var(--primary)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\\\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\\\/10{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.bg-red-500\\\\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\\\/20{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\\\\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/5{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.bg-white\\\\/8{background-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/8{background-color:color-mix(in oklab,var(--color-white)8%,transparent)}}.bg-white\\\\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/10{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.bg-white\\\\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/20{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.bg-white\\\\/60{background-color:#fff9}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/60{background-color:color-mix(in oklab,var(--color-white)60%,transparent)}}.bg-white\\\\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){.bg-white\\\\/90{background-color:color-mix(in oklab,var(--color-white)90%,transparent)}}.bg-yellow-500{background-color:var(--color-yellow-500)}.bg-zinc-100{background-color:var(--color-zinc-100)}.bg-zinc-700\\\\/50{background-color:#3f3f4680}@supports (color:color-mix(in lab, red, red)){.bg-zinc-700\\\\/50{background-color:color-mix(in oklab,var(--color-zinc-700)50%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-indigo-500{--tw-gradient-from:var(--color-indigo-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-purple-600{--tw-gradient-to:var(--color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.fill-foreground{fill:var(--foreground)}.stroke-\\\\[1\\\\.5px\\\\]{stroke-width:1.5px}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-1\\\\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.p-px{padding:1px}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\\\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\\\\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\\\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.pt-0\\\\.5{padding-top:calc(var(--spacing)*.5)}.pt-1\\\\.5{padding-top:calc(var(--spacing)*1.5)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-6{padding-left:calc(var(--spacing)*6)}.text-center{text-align:center}.text-left{text-align:left}.align-middle{vertical-align:middle}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\\\[10px\\\\]{font-size:10px}.text-\\\\[11px\\\\]{font-size:11px}.text-\\\\[13px\\\\]{font-size:13px}.text-\\\\[15px\\\\]{font-size:15px}.text-\\\\[17px\\\\]{font-size:17px}.text-\\\\[19px\\\\]{font-size:19px}.text-\\\\[21px\\\\]{font-size:21px}.text-\\\\[25px\\\\]{font-size:25px}.leading-\\\\[21px\\\\]{--tw-leading:21px;line-height:21px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-background{color:var(--background)}.text-blue-400{color:var(--color-blue-400)}.text-blue-400\\\\/60{color:#54a2ff99}@supports (color:color-mix(in lab, red, red)){.text-blue-400\\\\/60{color:color-mix(in oklab,var(--color-blue-400)60%,transparent)}}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-foreground{color:var(--foreground)}.text-green-400{color:var(--color-green-400)}.text-green-600{color:var(--color-green-600)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.text-white\\\\/30{color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/30{color:color-mix(in oklab,var(--color-white)30%,transparent)}}.text-white\\\\/40{color:#fff6}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/40{color:color-mix(in oklab,var(--color-white)40%,transparent)}}.text-white\\\\/50{color:#ffffff80}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/50{color:color-mix(in oklab,var(--color-white)50%,transparent)}}.text-white\\\\/60{color:#fff9}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/60{color:color-mix(in oklab,var(--color-white)60%,transparent)}}.text-white\\\\/70{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/70{color:color-mix(in oklab,var(--color-white)70%,transparent)}}.text-white\\\\/80{color:#fffc}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/80{color:color-mix(in oklab,var(--color-white)80%,transparent)}}.text-white\\\\/90{color:#ffffffe6}@supports (color:color-mix(in lab, red, red)){.text-white\\\\/90{color:color-mix(in oklab,var(--color-white)90%,transparent)}}.text-zinc-400{color:var(--color-zinc-400)}.text-zinc-700{color:var(--color-zinc-700)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,)var(--tw-slashed-zero,)var(--tw-numeric-figure,)var(--tw-numeric-spacing,)var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-100{opacity:1}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-black\\\\/10{--tw-shadow-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.shadow-black\\\\/10{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)10%,transparent)var(--tw-shadow-alpha),transparent)}}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\\\[color\\\\,box-shadow\\\\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\\\[grid-template-rows\\\\]{transition-property:grid-template-rows;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-100{--tw-duration:.1s;transition-duration:.1s}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.will-change-transform{will-change:transform}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\\\\:scale-100:is(:where(.group):hover *){--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.group-hover\\\\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\\\\:text-muted-foreground::placeholder{color:var(--muted-foreground)}.placeholder\\\\:text-white\\\\/40::placeholder{color:#fff6}@supports (color:color-mix(in lab, red, red)){.placeholder\\\\:text-white\\\\/40::placeholder{color:color-mix(in oklab,var(--color-white)40%,transparent)}}.first\\\\:mt-0:first-child{margin-top:calc(var(--spacing)*0)}.first\\\\:rounded-tl-lg:first-child{border-top-left-radius:var(--radius)}.first\\\\:border-t:first-child{border-top-style:var(--tw-border-style);border-top-width:1px}.last\\\\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}.last\\\\:rounded-tr-lg:last-child{border-top-right-radius:var(--radius)}.last\\\\:border-r:last-child{border-right-style:var(--tw-border-style);border-right-width:1px}.empty\\\\:hidden:empty{display:none}.focus-within\\\\:border-white\\\\/15:focus-within{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.focus-within\\\\:border-white\\\\/15:focus-within{border-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.focus-within\\\\:bg-white\\\\/10:focus-within{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.focus-within\\\\:bg-white\\\\/10:focus-within{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}@media (hover:hover){.hover\\\\:border-amber-500:hover{border-color:var(--color-amber-500)}.hover\\\\:border-red-500\\\\/50:hover{border-color:#fb2c3680}@supports (color:color-mix(in lab, red, red)){.hover\\\\:border-red-500\\\\/50:hover{border-color:color-mix(in oklab,var(--color-red-500)50%,transparent)}}.hover\\\\:border-white\\\\/20:hover{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\\\\:border-white\\\\/20:hover{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.hover\\\\:\\\\!bg-white:hover{background-color:var(--color-white)!important}.hover\\\\:bg-accent:hover,.hover\\\\:bg-accent\\\\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-accent\\\\/50:hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.hover\\\\:bg-amber-500\\\\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-amber-500\\\\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500)20%,transparent)}}.hover\\\\:bg-amber-500\\\\/30:hover{background-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-amber-500\\\\/30:hover{background-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.hover\\\\:bg-destructive\\\\/10:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/10:hover{background-color:color-mix(in oklab,var(--destructive)10%,transparent)}}.hover\\\\:bg-destructive\\\\/80:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/80:hover{background-color:color-mix(in oklab,var(--destructive)80%,transparent)}}.hover\\\\:bg-destructive\\\\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}}.hover\\\\:bg-muted-foreground\\\\/15:hover{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-muted-foreground\\\\/15:hover{background-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.hover\\\\:bg-primary\\\\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-primary\\\\/80:hover{background-color:color-mix(in oklab,var(--primary)80%,transparent)}}.hover\\\\:bg-primary\\\\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-primary\\\\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}}.hover\\\\:bg-red-500\\\\/10:hover{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-red-500\\\\/10:hover{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.hover\\\\:bg-red-500\\\\/20:hover{background-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-red-500\\\\/20:hover{background-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.hover\\\\:bg-red-500\\\\/30:hover{background-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-red-500\\\\/30:hover{background-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.hover\\\\:bg-secondary\\\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-secondary\\\\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}}.hover\\\\:bg-white:hover{background-color:var(--color-white)}.hover\\\\:bg-white\\\\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/5:hover{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.hover\\\\:bg-white\\\\/10:hover{background-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/10:hover{background-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.hover\\\\:bg-white\\\\/15:hover{background-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/15:hover{background-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.hover\\\\:bg-white\\\\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/20:hover{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.hover\\\\:bg-white\\\\/30:hover{background-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/30:hover{background-color:color-mix(in oklab,var(--color-white)30%,transparent)}}.hover\\\\:bg-white\\\\/95:hover{background-color:#fffffff2}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-white\\\\/95:hover{background-color:color-mix(in oklab,var(--color-white)95%,transparent)}}.hover\\\\:bg-zinc-50:hover{background-color:var(--color-zinc-50)}.hover\\\\:bg-zinc-200:hover{background-color:var(--color-zinc-200)}.hover\\\\:bg-zinc-700:hover{background-color:var(--color-zinc-700)}.hover\\\\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\\\\:text-destructive:hover{color:var(--destructive)}.hover\\\\:text-foreground:hover{color:var(--foreground)}.hover\\\\:text-primary\\\\/80:hover{color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-primary\\\\/80:hover{color:color-mix(in oklab,var(--primary)80%,transparent)}}.hover\\\\:text-red-200:hover{color:var(--color-red-200)}.hover\\\\:text-red-300:hover{color:var(--color-red-300)}.hover\\\\:text-red-400:hover{color:var(--color-red-400)}.hover\\\\:text-white:hover{color:var(--color-white)}.hover\\\\:text-white\\\\/50:hover{color:#ffffff80}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/50:hover{color:color-mix(in oklab,var(--color-white)50%,transparent)}}.hover\\\\:text-white\\\\/60:hover{color:#fff9}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/60:hover{color:color-mix(in oklab,var(--color-white)60%,transparent)}}.hover\\\\:text-white\\\\/70:hover{color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/70:hover{color:color-mix(in oklab,var(--color-white)70%,transparent)}}.hover\\\\:text-white\\\\/80:hover{color:#fffc}@supports (color:color-mix(in lab, red, red)){.hover\\\\:text-white\\\\/80:hover{color:color-mix(in oklab,var(--color-white)80%,transparent)}}.hover\\\\:text-zinc-600:hover{color:var(--color-zinc-600)}.hover\\\\:underline:hover{text-decoration-line:underline}.hover\\\\:opacity-75:hover{opacity:.75}.hover\\\\:opacity-100:hover{opacity:1}}.focus\\\\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\\\\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\\\\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\\\\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\\\\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus\\\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\\\:ring-\\\\[3px\\\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(3px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\\\:ring-blue-500:focus-visible{--tw-ring-color:var(--color-blue-500)}.focus-visible\\\\:ring-destructive\\\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-destructive\\\\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.focus-visible\\\\:ring-ring:focus-visible,.focus-visible\\\\:ring-ring\\\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-ring\\\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.focus-visible\\\\:ring-white\\\\/30:focus-visible{--tw-ring-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-white\\\\/30:focus-visible{--tw-ring-color:color-mix(in oklab,var(--color-white)30%,transparent)}}.focus-visible\\\\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\\\\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus-visible\\\\:ring-offset-transparent:focus-visible{--tw-ring-offset-color:transparent}.focus-visible\\\\:outline-1:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}.focus-visible\\\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\\\\:scale-\\\\[0\\\\.98\\\\]:active{scale:.98}.active\\\\:cursor-grabbing:active{cursor:grabbing}.active\\\\:bg-white\\\\/15:active{background-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.active\\\\:bg-white\\\\/15:active{background-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.active\\\\:bg-white\\\\/20:active{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.active\\\\:bg-white\\\\/20:active{background-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.disabled\\\\:pointer-events-none:disabled{pointer-events:none}.disabled\\\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\\\:opacity-40:disabled{opacity:.4}.disabled\\\\:opacity-50:disabled{opacity:.5}.has-\\\\[\\\\>svg\\\\]\\\\:px-2\\\\.5:has(>svg){padding-inline:calc(var(--spacing)*2.5)}.has-\\\\[\\\\>svg\\\\]\\\\:px-3:has(>svg){padding-inline:calc(var(--spacing)*3)}.has-\\\\[\\\\>svg\\\\]\\\\:px-4:has(>svg){padding-inline:calc(var(--spacing)*4)}.aria-invalid\\\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\\\:ring-destructive\\\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\\\\:ring-destructive\\\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.data-\\\\[orientation\\\\=horizontal\\\\]\\\\:h-px[data-orientation=horizontal]{height:1px}.data-\\\\[orientation\\\\=horizontal\\\\]\\\\:w-full[data-orientation=horizontal]{width:100%}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:h-full[data-orientation=vertical]{height:100%}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:w-px[data-orientation=vertical]{width:1px}.data-\\\\[state\\\\=open\\\\]\\\\:bg-accent[data-state=open]{background-color:var(--accent)}.data-\\\\[state\\\\=open\\\\]\\\\:text-muted-foreground[data-state=open]{color:var(--muted-foreground)}@media (min-width:40rem){.sm\\\\:flex{display:flex}.sm\\\\:h-3{height:calc(var(--spacing)*3)}.sm\\\\:h-3\\\\.5{height:calc(var(--spacing)*3.5)}.sm\\\\:h-4{height:calc(var(--spacing)*4)}.sm\\\\:h-7{height:calc(var(--spacing)*7)}.sm\\\\:max-h-24{max-height:calc(var(--spacing)*24)}.sm\\\\:max-h-32{max-height:calc(var(--spacing)*32)}.sm\\\\:max-h-48{max-height:calc(var(--spacing)*48)}.sm\\\\:min-h-7{min-height:calc(var(--spacing)*7)}.sm\\\\:w-3{width:calc(var(--spacing)*3)}.sm\\\\:w-3\\\\.5{width:calc(var(--spacing)*3.5)}.sm\\\\:w-4{width:calc(var(--spacing)*4)}.sm\\\\:w-7{width:calc(var(--spacing)*7)}.sm\\\\:max-w-3xl{max-width:var(--container-3xl)}.sm\\\\:max-w-16{max-width:calc(var(--spacing)*16)}.sm\\\\:max-w-24{max-width:calc(var(--spacing)*24)}.sm\\\\:max-w-lg{max-width:var(--container-lg)}.sm\\\\:max-w-md{max-width:var(--container-md)}.sm\\\\:min-w-7{min-width:calc(var(--spacing)*7)}.sm\\\\:flex-row{flex-direction:row}.sm\\\\:justify-end{justify-content:flex-end}.sm\\\\:gap-1{gap:calc(var(--spacing)*1)}.sm\\\\:gap-1\\\\.5{gap:calc(var(--spacing)*1.5)}.sm\\\\:p-1{padding:calc(var(--spacing)*1)}.sm\\\\:p-1\\\\.5{padding:calc(var(--spacing)*1.5)}.sm\\\\:px-2{padding-inline:calc(var(--spacing)*2)}.sm\\\\:py-1{padding-block:calc(var(--spacing)*1)}.sm\\\\:text-left{text-align:left}.sm\\\\:opacity-0{opacity:0}@media (hover:hover){.sm\\\\:group-hover\\\\:opacity-100:is(:where(.group):hover *){opacity:1}}}.dark\\\\:border-input:is(.dark *){border-color:var(--input)}.dark\\\\:border-muted-foreground\\\\/15:is(.dark *){border-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:border-muted-foreground\\\\/15:is(.dark *){border-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.dark\\\\:border-zinc-600:is(.dark *){border-color:var(--color-zinc-600)}.dark\\\\:border-zinc-700\\\\/80:is(.dark *){border-color:#3f3f46cc}@supports (color:color-mix(in lab, red, red)){.dark\\\\:border-zinc-700\\\\/80:is(.dark *){border-color:color-mix(in oklab,var(--color-zinc-700)80%,transparent)}}.dark\\\\:bg-destructive\\\\/60:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-destructive\\\\/60:is(.dark *){background-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.dark\\\\:bg-input\\\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-input\\\\/30:is(.dark *){background-color:color-mix(in oklab,var(--input)30%,transparent)}}.dark\\\\:bg-muted-foreground\\\\/20:is(.dark *){background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-muted-foreground\\\\/20:is(.dark *){background-color:color-mix(in oklab,var(--muted-foreground)20%,transparent)}}.dark\\\\:bg-zinc-700:is(.dark *){background-color:var(--color-zinc-700)}.dark\\\\:bg-zinc-800:is(.dark *){background-color:var(--color-zinc-800)}.dark\\\\:stroke-\\\\[2\\\\.5px\\\\]:is(.dark *){stroke-width:2.5px}.dark\\\\:text-green-400:is(.dark *){color:var(--color-green-400)}.dark\\\\:text-zinc-200:is(.dark *){color:var(--color-zinc-200)}.dark\\\\:text-zinc-400:is(.dark *){color:var(--color-zinc-400)}.dark\\\\:shadow-black\\\\/30:is(.dark *){--tw-shadow-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.dark\\\\:shadow-black\\\\/30:is(.dark *){--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)30%,transparent)var(--tw-shadow-alpha),transparent)}}@media (hover:hover){.dark\\\\:hover\\\\:bg-accent\\\\/50:is(.dark *):hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-accent\\\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.dark\\\\:hover\\\\:bg-input\\\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-input\\\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--input)50%,transparent)}}.dark\\\\:hover\\\\:bg-muted-foreground\\\\/30:is(.dark *):hover{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-muted-foreground\\\\/30:is(.dark *):hover{background-color:color-mix(in oklab,var(--muted-foreground)30%,transparent)}}.dark\\\\:hover\\\\:bg-zinc-600:is(.dark *):hover{background-color:var(--color-zinc-600)}.dark\\\\:hover\\\\:bg-zinc-700:is(.dark *):hover{background-color:var(--color-zinc-700)}.dark\\\\:hover\\\\:text-zinc-200:is(.dark *):hover{color:var(--color-zinc-200)}}.dark\\\\:focus-visible\\\\:ring-destructive\\\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:focus-visible\\\\:ring-destructive\\\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.dark\\\\:aria-invalid\\\\:ring-destructive\\\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:aria-invalid\\\\:ring-destructive\\\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.\\\\[\\\\&_svg\\\\]\\\\:pointer-events-none svg{pointer-events:none}.\\\\[\\\\&_svg\\\\]\\\\:shrink-0 svg{flex-shrink:0}.\\\\[\\\\&_svg\\\\]\\\\:text-background svg{color:var(--background)}.\\\\[\\\\&_svg\\\\]\\\\:text-black svg{color:var(--color-black)}@media (hover:hover){.hover\\\\:\\\\[\\\\&_svg\\\\]\\\\:text-destructive:hover svg{color:var(--destructive)}}.\\\\[\\\\&_svg\\\\:not\\\\(\\\\[class\\\\*\\\\=\\\\'size-\\\\'\\\\]\\\\)\\\\]\\\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\\\[\\\\&\\\\:last-child\\\\>td\\\\:first-child\\\\]\\\\:rounded-bl-lg:last-child>td:first-child{border-bottom-left-radius:var(--radius)}.\\\\[\\\\&\\\\:last-child\\\\>td\\\\:last-child\\\\]\\\\:rounded-br-lg:last-child>td:last-child{border-bottom-right-radius:var(--radius)}.only\\\\:\\\\[\\\\&\\\\>\\\\#attachment-tile\\\\]\\\\:size-24:only-child>#attachment-tile{width:calc(var(--spacing)*24);height:calc(var(--spacing)*24)}.\\\\[\\\\&\\\\>a\\\\]\\\\:text-xs>a{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\\\[\\\\&\\\\>a\\\\]\\\\:no-underline>a{text-decoration-line:none}.\\\\[\\\\&\\\\>button\\\\]\\\\:rounded-full>button{border-radius:3.40282e38px}.\\\\[\\\\&\\\\>button\\\\]\\\\:bg-foreground\\\\/60>button{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.\\\\[\\\\&\\\\>button\\\\]\\\\:bg-foreground\\\\/60>button{background-color:color-mix(in oklab,var(--foreground)60%,transparent)}}.\\\\[\\\\&\\\\>button\\\\]\\\\:p-1>button{padding:calc(var(--spacing)*1)}.\\\\[\\\\&\\\\>button\\\\]\\\\:opacity-100>button{opacity:1}.\\\\[\\\\&\\\\>button\\\\]\\\\:\\\\!ring-0>button{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)!important}@media (hover:hover){.\\\\[\\\\&\\\\>button\\\\]\\\\:hover\\\\:\\\\[\\\\&_svg\\\\]\\\\:text-destructive>button:hover svg{color:var(--destructive)}}.\\\\[\\\\&\\\\>li\\\\]\\\\:mt-0\\\\.5>li{margin-top:calc(var(--spacing)*.5)}.\\\\[\\\\&\\\\>li\\\\]\\\\:mt-1>li{margin-top:calc(var(--spacing)*1)}.\\\\[\\\\&\\\\>span\\\\]\\\\:text-xs>span{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\\\[\\\\&\\\\[align\\\\=center\\\\]\\\\]\\\\:text-center[align=center]{text-align:center}.\\\\[\\\\&\\\\[align\\\\=right\\\\]\\\\]\\\\:text-right[align=right]{text-align:right}}@keyframes shimmer{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes subtle-pulse{0%,to{opacity:1}50%{opacity:.85}}@keyframes smooth-slide-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes gradient-shift{0%,to{transform:translate(0%)translateY(0%)}25%{transform:translate(100%)translateY(100%)}50%{transform:translate(100%)translateY(0%)}75%{transform:translate(0%)translateY(100%)}}@keyframes float{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(-30px)translate(20px)}66%{transform:translateY(20px)translate(-20px)}}@keyframes float-delayed{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(30px)translate(-30px)}66%{transform:translateY(-20px)translate(20px)}}.tool-card-transition{transition:all .4s cubic-bezier(.34,1.56,.64,1)}.tool-card-smooth{transition:all .35s cubic-bezier(.4,0,.2,1)}.animate-fadeInUp{opacity:0;animation:.5s ease-out forwards fadeInUp}.animate-gradient-shift{background-size:200% 200%;animation:20s ease-in-out infinite gradient-shift}.animate-float-slow{animation:20s ease-in-out infinite float}.animate-float-delayed{animation:25s ease-in-out 5s infinite float-delayed}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@keyframes tool-border-rotate{0%{--tool-border-angle:0deg}to{--tool-border-angle:360deg}}@property --tool-border-angle{syntax:\\\"<angle>\\\";inherits:false;initial-value:0deg}.tool-border-calling{background:conic-gradient(from var(--tool-border-angle),transparent 0deg,transparent 60deg,#3b82f680 90deg,#60a5fab3 120deg,#93c5fd80 150deg,transparent 180deg,transparent 360deg);animation:1.5s linear infinite tool-border-rotate}.tool-border-success{background:#22c55e66;box-shadow:0 0 12px #22c55e4d,inset 0 0 8px #22c55e1a}.tool-border-error{background:#ef444466;box-shadow:0 0 12px #ef44444d,inset 0 0 8px #ef44441a}@keyframes pulse-success{0%,to{box-shadow:0 0 #22c55e66}50%{box-shadow:0 0 0 8px #22c55e00}}@keyframes shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.animate-pulse-success{animation:.6s ease-out pulse-success}.animate-shake{animation:.3s ease-out shake}@keyframes aui-pulse{50%{opacity:.5}}:where(.aui-md[data-status=running]):empty:after,:where(.aui-md[data-status=running])>:where(:not(ol):not(ul):not(pre)):last-child:after,:where(.aui-md[data-status=running])>pre:last-child code:after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child:not(:has(*>li))):after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child:not(:has(*>li))):after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child):after{--aui-content:\\\"●\\\";content:var(--aui-content);margin-left:.25rem;margin-right:.25rem;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;animation:2s cubic-bezier(.4,0,.6,1) infinite aui-pulse}.glass-pill{-webkit-backdrop-filter:blur(20px)saturate(150%);background:#0f172ad9;border:1px solid #ffffff0f;box-shadow:0 4px 16px #0003,inset 0 .5px #ffffff14}.glass-pill:before{content:\\\"\\\";border-radius:inherit;pointer-events:none;z-index:1;background:linear-gradient(#ffffff0a 0%,#0000 40%);position:absolute;inset:0}.glass-pill:after{display:none}.glass-pill-collapsed{-webkit-backdrop-filter:blur(20px)saturate(150%);background:#0f172ad9;border:1px solid #ffffff0f;box-shadow:0 2px 8px #0003,inset 0 .5px #ffffff14}.glass-pill-collapsed:before,.glass-pill-collapsed:after{display:none}.glass-pill-hovered{-webkit-backdrop-filter:blur(16px)saturate(140%);background:#0f172acc;border:1px solid #ffffff0f;box-shadow:0 2px 12px #0000002e}.glass-pill-hovered:before,.glass-pill-hovered:after{display:none}@keyframes glass-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.glass-shimmer{background:linear-gradient(90deg,#ffffff14 0%,#ffffff26 50%,#ffffff14 100%) 0 0/200% 100%;animation:4s ease-in-out infinite glass-shimmer}.scrollbar-thin{scrollbar-width:thin;scrollbar-color:#fff3 transparent}.scrollbar-thin::-webkit-scrollbar{width:4px;height:4px}.scrollbar-thin::-webkit-scrollbar-thumb{background-color:#fff3;border-radius:9999px}.scrollbar-thin::-webkit-scrollbar-track{background-color:#0000}.scroll-touch{-webkit-overflow-scrolling:touch;overscroll-behavior:contain}@media (hover:none){.scrollbar-thin{scrollbar-width:none}.scrollbar-thin::-webkit-scrollbar{display:none}}.scroll-fade-y{-webkit-mask-image:linear-gradient(#0000,#000 8px calc(100% - 8px),#0000);mask-image:linear-gradient(#0000,#000 8px calc(100% - 8px),#0000)}.pb-safe{padding-bottom:env(safe-area-inset-bottom,0px)}.mb-safe{margin-bottom:env(safe-area-inset-bottom,0px)}.bottom-safe{bottom:max(1rem,env(safe-area-inset-bottom,0px))}@supports (padding-bottom:env(safe-area-inset-bottom)){.pill-safe-bottom{padding-bottom:calc(env(safe-area-inset-bottom,0px) + .5rem)}}@property --tw-border-spacing-x{syntax:\\\"<length>\\\";inherits:false;initial-value:0}@property --tw-border-spacing-y{syntax:\\\"<length>\\\";inherits:false;initial-value:0}@property --tw-translate-x{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-translate-y{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-translate-z{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-scale-x{syntax:\\\"*\\\";inherits:false;initial-value:1}@property --tw-scale-y{syntax:\\\"*\\\";inherits:false;initial-value:1}@property --tw-scale-z{syntax:\\\"*\\\";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:\\\"*\\\";inherits:false}@property --tw-rotate-y{syntax:\\\"*\\\";inherits:false}@property --tw-rotate-z{syntax:\\\"*\\\";inherits:false}@property --tw-skew-x{syntax:\\\"*\\\";inherits:false}@property --tw-skew-y{syntax:\\\"*\\\";inherits:false}@property --tw-space-y-reverse{syntax:\\\"*\\\";inherits:false;initial-value:0}@property --tw-border-style{syntax:\\\"*\\\";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:\\\"*\\\";inherits:false}@property --tw-gradient-from{syntax:\\\"<color>\\\";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:\\\"<color>\\\";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:\\\"<color>\\\";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:\\\"*\\\";inherits:false}@property --tw-gradient-via-stops{syntax:\\\"*\\\";inherits:false}@property --tw-gradient-from-position{syntax:\\\"<length-percentage>\\\";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:\\\"<length-percentage>\\\";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:\\\"<length-percentage>\\\";inherits:false;initial-value:100%}@property --tw-leading{syntax:\\\"*\\\";inherits:false}@property --tw-font-weight{syntax:\\\"*\\\";inherits:false}@property --tw-tracking{syntax:\\\"*\\\";inherits:false}@property --tw-ordinal{syntax:\\\"*\\\";inherits:false}@property --tw-slashed-zero{syntax:\\\"*\\\";inherits:false}@property --tw-numeric-figure{syntax:\\\"*\\\";inherits:false}@property --tw-numeric-spacing{syntax:\\\"*\\\";inherits:false}@property --tw-numeric-fraction{syntax:\\\"*\\\";inherits:false}@property --tw-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\\\"*\\\";inherits:false}@property --tw-shadow-alpha{syntax:\\\"<percentage>\\\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\\\"*\\\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\\\"<percentage>\\\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\\\"*\\\";inherits:false}@property --tw-ring-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\\\"*\\\";inherits:false}@property --tw-inset-ring-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\\\"*\\\";inherits:false}@property --tw-ring-offset-width{syntax:\\\"<length>\\\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\\\"*\\\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\\\"*\\\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\\\"*\\\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\\\"*\\\";inherits:false}@property --tw-brightness{syntax:\\\"*\\\";inherits:false}@property --tw-contrast{syntax:\\\"*\\\";inherits:false}@property --tw-grayscale{syntax:\\\"*\\\";inherits:false}@property --tw-hue-rotate{syntax:\\\"*\\\";inherits:false}@property --tw-invert{syntax:\\\"*\\\";inherits:false}@property --tw-opacity{syntax:\\\"*\\\";inherits:false}@property --tw-saturate{syntax:\\\"*\\\";inherits:false}@property --tw-sepia{syntax:\\\"*\\\";inherits:false}@property --tw-drop-shadow{syntax:\\\"*\\\";inherits:false}@property --tw-drop-shadow-color{syntax:\\\"*\\\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\\\"<percentage>\\\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\\\"*\\\";inherits:false}@property --tw-duration{syntax:\\\"*\\\";inherits:false}@property --tw-ease{syntax:\\\"*\\\";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}\";\n\n/**\n * Inject the WebMCP styles into the document head.\n * This is called automatically when registering the web component.\n */\nexport function injectStyles(): void {\n\tif (typeof document === 'undefined') return\n\n\tconst styleId = 'webmcp-agent-styles'\n\tif (document.getElementById(styleId)) return\n\n\tconst style = document.createElement('style')\n\tstyle.id = styleId\n\tstyle.textContent = WEBMCP_STYLES\n\tdocument.head.appendChild(style)\n}\n","/**\n * WebMCP Agent\n *\n * An Intercom-like AI chat widget with MCP tool support and voice mode.\n * Drop it into your app and you're done - no configuration needed.\n *\n * @example Web Component (simplest)\n * ```html\n * <script src=\"https://cdn.webmcp.ai/agent.js\"></script>\n * <webmcp-agent app-id=\"your-app-id\"></webmcp-agent>\n * ```\n *\n * @example React Component\n * ```tsx\n * import { EmbeddedAgent } from '@mcp-b/embedded-agent'\n * import '@mcp-b/embedded-agent/styles'\n *\n * function App() {\n * return <EmbeddedAgent appId=\"your-app-id\" />\n * }\n * ```\n *\n * @example Development mode (use your own API keys)\n * ```tsx\n * <EmbeddedAgent\n * appId=\"your-app-id\"\n * devMode={{\n * anthropicApiKey: \"sk-ant-...\",\n * openaiApiKey: \"sk-...\" // Optional, for voice mode\n * }}\n * />\n * ```\n *\n */\n\nimport r2wc from '@r2wc/react-to-web-component'\n\nimport { AgentPill } from './components/pill'\nimport { AgentProvider } from './core/providers/AgentProvider'\nimport { injectStyles } from './generated/inline-styles'\nimport { WEBMCP_PRODUCTION_API_BASE } from './lib/constants'\n\nimport type { FC } from 'react'\n\n/**\n * Get the default API base URL.\n * Always uses production unless explicitly overridden with useLocalApi.\n */\nconst getDefaultApiBase = (useLocalApi?: boolean): string => {\n\tif (useLocalApi && typeof window !== 'undefined') {\n\t\treturn window.location.origin\n\t}\n\treturn WEBMCP_PRODUCTION_API_BASE\n}\n\n/**\n * Development mode configuration\n *\n * In dev mode, you provide your own API keys for testing.\n * Requests still go through WebMCP infrastructure (Cloudflare Workers),\n * but use your keys so there's no cost to us during development.\n */\nexport interface DevModeConfig {\n\t/** Your Anthropic API key for chat (required for dev mode) */\n\tanthropicApiKey: string\n\t/** Your OpenAI API key for voice mode (optional) */\n\topenaiApiKey?: string\n\t/** Use window.location.origin instead of production API (for internal development) */\n\tuseLocalApi?: boolean\n}\n\n/**\n * Props for the EmbeddedAgent component\n */\nexport interface EmbeddedAgentProps {\n\t/** Your WebMCP app ID - get one at webmcp.ai */\n\tappId: string\n\n\t/**\n\t * Development mode - use your own API keys for testing.\n\t * In production, leave this undefined to use your WebMCP plan.\n\t */\n\tdevMode?: DevModeConfig\n}\n\n/**\n * EmbeddedAgent - Drop-in AI chat widget\n *\n * A fully self-contained chat widget with:\n * - MCP tool support (connect to any MCP server)\n * - Voice mode (talk to your AI assistant)\n * - Action-first UI (shows what the AI is doing, not just typing)\n *\n * Just add your app ID and you're done. Everything else is handled.\n */\nexport const EmbeddedAgent: FC<EmbeddedAgentProps> = ({ appId, devMode }) => {\n\t// API base: always production unless useLocalApi is explicitly set\n\tconst apiBase = getDefaultApiBase(devMode?.useLocalApi)\n\n\t// Log initialization\n\tif (typeof window !== 'undefined') {\n\t\tconsole.debug('[WebMCP] Initialized', {\n\t\t\tappId,\n\t\t\tmode: devMode ? 'development' : 'production',\n\t\t\tapiBase,\n\t\t})\n\t}\n\n\t// Voice is enabled if we have an OpenAI key in dev mode, or in production (uses plan)\n\tconst voiceEnabled = !devMode || !!devMode.openaiApiKey\n\n\treturn (\n\t\t<AgentProvider\n\t\t\tapiBase={apiBase}\n\t\t\ttokenEndpoint={voiceEnabled ? `${apiBase}/api/realtime/session` : undefined}\n\t\t\tautoConnectLocal={true}\n\t\t>\n\t\t\t<AgentPill position=\"bottom-center\" showVoiceButton={voiceEnabled} />\n\t\t</AgentProvider>\n\t)\n}\n\n/**\n * Web Component wrapper\n *\n * Converts EmbeddedAgent to a <webmcp-agent> custom element.\n * Attributes map to props in kebab-case (app-id -> appId).\n */\nconst WebMCPAgentElement = r2wc(EmbeddedAgent as unknown as Parameters<typeof r2wc>[0], {\n\tprops: {\n\t\tappId: 'string',\n\t\t// Note: devMode is JSON-stringified when passed as attribute\n\t\t// <webmcp-agent dev-mode='{\"anthropicApiKey\": \"sk-...\"}'>\n\t\tdevMode: 'json',\n\t},\n})\n\n/**\n * Register the <webmcp-agent> custom element\n *\n * Called automatically when importing this module.\n * Styles are injected into the document head.\n */\nexport function registerWebMCPAgent(tagName = 'webmcp-agent'): void {\n\tif (typeof window === 'undefined') return\n\n\tinjectStyles()\n\n\tif (!customElements.get(tagName)) {\n\t\tcustomElements.define(tagName, WebMCPAgentElement)\n\t}\n}\n\n// Auto-register on import\nregisterWebMCPAgent()\n"],"mappings":"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"}