@mcp-b/char 0.0.6 → 0.1.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.
Files changed (39) hide show
  1. package/README.md +76 -362
  2. package/dist/custom-elements.json +2180 -0
  3. package/dist/display-mode-policy.d.ts +82 -0
  4. package/dist/display-mode-policy.d.ts.map +1 -0
  5. package/dist/display-mode-policy.js +87 -0
  6. package/dist/display-mode-policy.js.map +1 -0
  7. package/dist/index.d.ts +707 -326
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2374 -15521
  10. package/dist/index.js.map +1 -1
  11. package/dist/shell-component.d.ts +379 -0
  12. package/dist/shell-component.d.ts.map +1 -0
  13. package/dist/shell-component.js +2508 -0
  14. package/dist/shell-component.js.map +1 -0
  15. package/dist/tsdoc-metadata.json +11 -0
  16. package/dist/utils.d.ts +161 -0
  17. package/dist/utils.d.ts.map +1 -0
  18. package/dist/utils.js +393 -0
  19. package/dist/utils.js.map +1 -0
  20. package/dist/web-component-standalone.iife.js +1259 -2358
  21. package/dist/web-component-standalone.iife.js.map +1 -1
  22. package/dist/web-component.d.ts +381 -180
  23. package/dist/web-component.d.ts.map +1 -1
  24. package/dist/web-component.js +1142 -15740
  25. package/dist/web-component.js.map +1 -1
  26. package/package.json +23 -115
  27. package/THIRD_PARTY_NOTICES.md +0 -52
  28. package/dist/VoiceHandoffPanel-CIFIJSDs.js +0 -244
  29. package/dist/VoiceHandoffPanel-CIFIJSDs.js.map +0 -1
  30. package/dist/button-BLnLZvxR.js +0 -105
  31. package/dist/button-BLnLZvxR.js.map +0 -1
  32. package/dist/realtimekit.d.ts +0 -15
  33. package/dist/realtimekit.d.ts.map +0 -1
  34. package/dist/realtimekit.js +0 -89
  35. package/dist/realtimekit.js.map +0 -1
  36. package/dist/styles/globals.css +0 -2
  37. package/dist/styles.d.ts +0 -2
  38. package/dist/web-component-standalone.css +0 -37
  39. package/dist/web-component-standalone.css.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["DevModeConfig","anthropicApiKey","openaiApiKey","useLocalApi","DevModeResolution","devMode","isEmpty","normalizeApiKey","value","trimmed","trim","undefined","resolveDevMode","normalized","hasAnyValue","c","_c","createContext","useContext","ReactNode","PortalContainerContext","HTMLElement","hasWarnedAboutMissingContext","usePortalContainer","context","window","process","env","NODE_ENV","console","error","PortalContainerProvider","t0","$","container","children","t1","c","_c","React","TooltipPrimitive","cn","usePortalContainer","TooltipProvider","t0","$","props","t1","delayDuration","undefined","t2","Tooltip","TooltipTrigger","TooltipContent","children","className","sideOffset","container","t3","Symbol","for","t4","t5","c","_c","React","DialogPrimitive","XIcon","cn","usePortalContainer","Dialog","t0","$","props","t1","DialogTrigger","DialogPortal","container","DialogClose","DialogOverlay","className","t2","DialogContent","children","showCloseButton","undefined","Symbol","for","t3","t4","t5","DialogHeader","DialogFooter","DialogTitle","DialogDescription","c","_c","React","AvatarPrimitive","cn","Avatar","t0","$","className","props","t1","t2","AvatarImage","AvatarFallback","c","_c","forwardRef","ComponentPropsWithRef","Slottable","Tooltip","TooltipContent","TooltipTrigger","Button","cn","TooltipIconButtonProps","tooltip","side","TooltipIconButton","HTMLButtonElement","t0","ref","$","children","className","rest","t1","undefined","t2","t3","t4","t5","t6","t7","displayName","c","_c","useEffect","useState","FC","PropsWithChildren","XIcon","PlusIcon","FileText","AttachmentPrimitive","ComposerPrimitive","MessagePrimitive","useAssistantState","useAssistantApi","useShallow","Tooltip","TooltipContent","TooltipTrigger","Dialog","DialogTitle","DialogContent","DialogTrigger","Avatar","AvatarImage","AvatarFallback","TooltipIconButton","cn","useFileSrc","file","$","src","setSrc","undefined","t0","t1","objectUrl","URL","createObjectURL","revokeObjectURL","useAttachmentSrc","src_0","_temp2","AttachmentPreviewProps","AttachmentPreview","isLoaded","setIsLoaded","t2","Symbol","for","t3","AttachmentPreviewDialog","children","t4","AttachmentThumb","isImage","_temp3","AttachmentUI","api","isComposer","attachment","source","_temp4","typeLabel","_temp5","t5","t6","t7","t8","t9","t10","AttachmentRemove","UserMessageAttachments","Attachment","ComposerAttachments","ComposerAddAttachment","_temp","type","content","filter","image","attachment_0","_exhaustiveCheck","Error","c","_c","CodeHeaderProps","MarkdownTextPrimitive","unstable_memoizeMarkdownComponents","memoizeMarkdownComponents","useIsMarkdownCodeBlock","remarkGfm","FC","memo","useState","CheckIcon","CopyIcon","TooltipIconButton","cn","MarkdownTextImpl","$","t0","Symbol","for","defaultComponents","MarkdownText","CodeHeader","language","code","isCopied","copyToClipboard","useCopyToClipboard","t1","onCopy","t2","t3","t4","t5","t6","undefined","copiedDuration","setIsCopied","value","navigator","clipboard","writeText","then","setTimeout","h1","className","props","h2","h3","h4","h5","h6","p","a","blockquote","ul","ol","hr","table","th","td","tr","sup","pre","Code","isCodeBlock","c","_c","CollapsiblePrimitive","Collapsible","t0","$","props","t1","CollapsibleTrigger","CollapsibleContent","c","_c","BrainIcon","ChevronDownIcon","memo","useCallback","useRef","useState","FC","PropsWithChildren","useScrollLock","useAssistantState","ReasoningMessagePartComponent","ReasoningGroupComponent","MarkdownText","Collapsible","CollapsibleContent","CollapsibleTrigger","cn","ANIMATION_DURATION","ReasoningRoot","className","t0","$","children","collapsibleRef","isOpen","setIsOpen","lockScroll","t1","open","handleOpenChange","t2","t3","Symbol","for","t4","React","CSSProperties","displayName","GradientFade","ReasoningTrigger","active","t5","t6","t7","ReasoningContent","ariaBusy","ReasoningText","ReasoningImpl","ReasoningGroupImpl","startIndex","endIndex","message","status","type","lastIndex","parts","length","lastType","isReasoningStreaming","Reasoning","ReasoningGroup","cn","useEffect","useMemo","useRef","HTMLAttributes","WaveformMode","BAR_WIDTH","BAR_HEIGHT","BAR_GAP","BAR_RADIUS","FADE_WIDTH","SENSITIVITY","HISTORY_SIZE","UPDATE_RATE","LiveWaveformProps","HTMLDivElement","active","processing","level","height","mode","clampLevel","value","Number","isNaN","Math","max","min","LiveWaveform","className","props","canvasRef","HTMLCanvasElement","frameRef","lastTickRef","smoothLevelRef","historyRef","paramsRef","current","inlineStyle","canvas","ctx","getContext","container","parentElement","cachedColor","getComputedStyle","color","resize","dpr","window","devicePixelRatio","rect","getBoundingClientRect","width","floor","style","setTransform","draw","timestamp","currentActive","currentProcessing","currentLevel","currentMode","requestAnimationFrame","clientWidth","rawHeight","clientHeight","displayHeight","clearRect","baseLevel","targetLevel","smoothing","animatedLevel","sin","fillStyle","barStep","barCount","centerY","next","history","push","length","shift","paddedHistory","Array","fill","slice","i","h","x","beginPath","roundRect","oscillation","distance","abs","shape","reactive","gradient","createLinearGradient","addColorStop","save","globalCompositeOperation","fillRect","restore","observer","ResizeObserver","observe","cancelAnimationFrame","disconnect","c","_c","React","SelectPrimitive","CheckIcon","ChevronDownIcon","ChevronUpIcon","cn","usePortalContainer","Select","t0","$","props","t1","SelectGroup","SelectValue","SelectTrigger","children","className","size","undefined","t2","t3","Symbol","for","t4","SelectContent","position","align","container","t5","t6","t7","t8","t9","t10","t11","SelectLabel","SelectItem","SelectSeparator","SelectScrollUpButton","SelectScrollDownButton","Button","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","cn","Mic","MicOff","RefreshCw","useCallback","useEffect","useMemo","useState","FC","AudioDevice","deviceId","label","groupId","UseAudioDevicesReturn","devices","loading","error","hasPermission","loadDevices","Promise","cleanDeviceLabel","index","trimmed","replace","trim","useAudioDevices","setDevices","setLoading","setError","setHasPermission","navigator","mediaDevices","stream","getUserMedia","audio","getTracks","forEach","track","stop","all","enumerateDevices","mics","filter","device","kind","map","err","Error","message","catch","console","handleDeviceChange","addEventListener","removeEventListener","MicSelectorProps","value","onValueChange","muted","onMutedChange","disabled","className","MicSelector","t0","$","_c","t1","undefined","t2","length","t3","t4","find","d","selectedLabel","t5","t6","t7","t8","t9","t10","_temp","t11","t12","t13","t14","t15","t16","t17","t18","_temp2","t19","t20","t21","t22","t23","t24","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","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","Prompt","Resource","ResourceTemplate","Tool","MCPSource","MCPSourceConfig","ToolWithSource","Transport","ReactNode","SOURCE_LOCAL","SOURCE_REMOTE","SourceState","Omit","client","transport","tools","resources","resourceTemplates","prompts","InflightToolCall","toolName","sourceId","abortController","AbortController","MCPToolsContextValue","sources","Map","addSource","id","config","Promise","removeSource","getSource","isConnected","callTool","name","args","Record","callToolOnSource","getPrompt","refreshTools","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","message","get","close","undefined","abortPromise","_","reject","signal","aborted","reason","addEventListener","once","result","race","arguments","content","type","const","text","isError","find","values","hasPrompt","some","p","debug","length","publicSources","timer","setTimeout","clearTimeout","inflightCalls","clear","catch","value","useMCPTools","context","useOptionalMCPTools","useCallback","useMCPTools","GetPromptResult","Prompt","UsePromptsResult","prompts","hasPrompts","getPrompt","name","args","Record","Promise","usePrompts","$","_c","mcpGetPrompt","length","t0","t1","cn","Skeleton","t0","$","_c","className","props","t1","t2","ErrorBoundary","FallbackProps","useState","ErrorInfo","ReactNode","Button","cn","AlertCircle","RefreshCw","MessageSquarePlus","ChatErrorFallbackProps","onStartNewThread","Promise","getErrorMessage","error","Error","message","ChatErrorFallback","t0","$","_c","resetErrorBoundary","isCreatingThread","setIsCreatingThread","errorMessage","t1","includes","isKnownChatError","t2","t3","err","console","handleStartNewThread","Symbol","for","t4","t5","t6","t7","t8","t9","t10","t11","t12","t13","t14","t15","ChatErrorBoundaryProps","children","onReset","onError","info","ChatErrorBoundary","error_0","componentStack","normalizedError","DEFAULT_MAX_TOKEN_SIZE_BYTES","validateTokenSize","token","maxSizeBytes","valid","errorCode","errorMessage","sizeBytes","length","sizeMB","toFixed","maxMB","IDP_TYPE","OKTA","AZURE","AUTH0","GOOGLE","CUSTOM_OIDC","WORKOS","FIREBASE","ONELOGIN","LOGTO","IDP_TYPES","Object","values","IDP_DISPLAY_NAMES","IDP_TYPES_REQUIRING_DOMAIN","IDP_TYPES_REQUIRING_ISSUER","requiresDomain","idpType","includes","requiresIssuer","getIdpDisplayName","IDP_ISSUER_PATTERNS","domain","clientId","projectId","subdomain","tenant","getIdpIssuerUrl","explicitIssuer","pattern","jose","ALLOWED_ALGORITHMS","validateTokenSize","extractAzureTenantId","getOIDCDiscoveryUrl","fetchOIDCDiscovery","getSecureJWKS","clearJWKSCacheEntry","mapJoseError","DEFAULT_CLOCK_SKEW_SECONDS","DEFAULT_MAX_TOKEN_AGE_SECONDS","verifyUserIdentity","options","authToken","idpConfig","maxTokenAgeSeconds","retryOnKeyNotFound","type","success","errorCode","errorMessage","sizeResult","valid","discoveryUrl","error","Error","message","oidcConfig","jwksResult","jwks_uri","payload","result","jwtVerify","getKey","algorithms","issuer","audience","clientId","undefined","clockTolerance","maxTokenAge","errors","JWKSNoMatchingKey","retryJwksResult","retryError","mapped","expectedTenantId","tid","audArray","Array","isArray","aud","length","azp","sub","userId","email","z","IDP_TYPES","IDP_TYPE","IDP_DISPLAY_NAMES","IDP_TYPES_REQUIRING_DOMAIN","IdpTypeSchema","enum","nullable","domainSchema","string","min","refine","val","includes","message","endsWith","optional","issuerSchema","url","URL","protocol","clientIdSchema","trim","length","BaseIdpConfigSchema","object","type","clientId","domain","issuer","IdpConfigSchema","superRefine","config","ctx","displayName","addIssue","code","ZodIssueCode","custom","path","CUSTOM_OIDC","IDP_TYPE","MAX_IDP_DOMAIN_LENGTH","IDP_DOMAIN_PATTERNS","OKTA","AUTH0","WORKOS","FIREBASE","ONELOGIN","LOGTO","validateOktaDomain","domain","length","valid","error","pattern","test","validateAuth0Domain","AZURE_UUID_PATTERN","AZURE_DOMAIN_PATTERN","validateAzureTenant","tenantIdOrDomain","validateCustomOidcIssuer","issuer","url","URL","protocol","validateNoWildcard","startsWith","includes","validateWorkOsClientId","clientId","validateFirebaseProjectId","projectId","validateOneLoginSubdomain","subdomain","validateLogtoTenant","tenant","validateIdpDomain","idpType","AZURE","GOOGLE","CUSTOM_OIDC","validateIdpConfigSecurity","config","idp_type","allowed_domains","wildcardResult","domainResult","idp_domain","idp_issuer","idp_client_id","TOKEN_ERROR_CODES","TOKEN_REQUIRED","TOKEN_EXPIRED","INVALID_TOKEN","INVALID_SIGNATURE","INVALID_ISSUER","INVALID_AUDIENCE","INVALID_ALGORITHM","INVALID_AZP","INVALID_TOKEN_AGE","TOKEN_TOO_LARGE","KEY_ERROR_CODES","KEY_NOT_FOUND","JWKS_FETCH_FAILED","JWKS_RATE_LIMITED","CONFIG_ERROR_CODES","IDP_NOT_CONFIGURED","SSRF_BLOCKED","ALLOWLIST_REQUIRED","PROVIDER_ERROR_CODES","AZURE_TID_MISMATCH","APP_ERROR_CODES","ORG_NOT_FOUND","ORIGIN_NOT_ALLOWED","DATABASE_ERROR","LOCALHOST_REQUIRED","API_KEY_REQUIRED","FEATURE_NOT_IMPLEMENTED","INTERNAL_ERROR","MISSING_CLIENT_ID","MISSING_ORG_CONTEXT","CLIENT_ID_NOT_ALLOWED","MISSING_USER_ID","NETWORK_ERROR","TOKEN_EXCHANGE_ERROR","AUTH_ERROR_CODE","ERROR_HTTP_STATUS","getHttpStatus","errorCode","isAuthError","isRetryable","retryableCodes","includes","isRecoverable","unrecoverableCodes","isAuthErrorCode","code","Object","values","assertNever","value","message","Error","AUTH_ERROR_CODE","getHttpStatus","isRecoverable","assertNever","getErrorMetadata","code","context","TOKEN_REQUIRED","title","message","docsLink","TOKEN_EXPIRED","INVALID_TOKEN","INVALID_SIGNATURE","INVALID_ISSUER","callToAction","steps","dashboardLink","INVALID_AUDIENCE","INVALID_ALGORITHM","INVALID_AZP","INVALID_TOKEN_AGE","TOKEN_TOO_LARGE","KEY_NOT_FOUND","JWKS_FETCH_FAILED","JWKS_RATE_LIMITED","IDP_NOT_CONFIGURED","SSRF_BLOCKED","AZURE_TID_MISMATCH","ORG_NOT_FOUND","ORIGIN_NOT_ALLOWED","currentDomain","examples","DATABASE_ERROR","LOCALHOST_REQUIRED","API_KEY_REQUIRED","FEATURE_NOT_IMPLEMENTED","INTERNAL_ERROR","MISSING_CLIENT_ID","MISSING_ORG_CONTEXT","ALLOWLIST_REQUIRED","CLIENT_ID_NOT_ALLOWED","MISSING_USER_ID","NETWORK_ERROR","TOKEN_EXCHANGE_ERROR","buildAuthError","options","errorCode","metadata","resolvedMessage","resolvedCallToAction","errorTitle","recoverable","debugInfo","httpStatus","createAuthErrorResponse","errorResponse","Response","JSON","stringify","error","status","headers","isAuthErrorCode","APP_ERROR_CODES","ErrorContext","InitContextResult","AuthError","AuthErrorCode","mapErrorCode","backendCode","INTERNAL_ERROR","convertInitErrorToAuthError","result","success","Error","code","errorCode","title","errorTitle","message","callToAction","dashboardLink","docsLink","context","recoverable","debugInfo","AuthErrorException","constructor","authError","name","captureStackTrace","throwInitError","useLayoutEffect","useRef","stableStringifyImpl","isToolUIPart","UIMessage","useLatest","value","$","_c","ref","t0","t1","current","CallToolResult","HubToSiteMessage","PolicyEventMessage","SyncedToolSchema","ToolSourcesUpdateMessage","stableStringify","generateShortTabId","window","random","Math","floor","toString","padStart","EMBEDDED_AGENT_TAB_ID","getEmbeddedAgentTabId","areSyncedToolSchemasEquivalent","a","b","length","byName","Map","schema","set","name","next","prev","get","description","inputSchema","annotations","sources","safeParseHubToSiteMessage","data","parsed","JSON","parse","msg","Partial","type","callId","toolName","args","Record","safeParseToolSourcesMessage","Array","isArray","safeParsePolicyEventMessage","event","formatToolResult","result","textContent","content","find","c","text","stringify","sliceMessagesUntil","id","messages","T","parentId","index","findIndex","m","slice","shallowEqualRecords","aKeys","Object","keys","bKeys","key","prototype","hasOwnProperty","call","useShallowStableObject","getPendingToolCallIds","lastMessage","role","parts","filter","part","Extract","toolCallId","state","output","undefined","map","useCallback","useEffect","useState","ToolConnectionMetadata","getEmbeddedAgentTabId","UseToolSourceMetadataOptions","enabled","UseToolSourceMetadataResult","metadata","useToolSourceMetadata","options","tabId","getMetadata","window","undefined","iconUrl","link","document","querySelector","HTMLLinkElement","href","getAttribute","URL","location","toString","url","origin","title","trim","setMetadata","updateMetadata","addEventListener","titleObserver","MutationObserver","titleElement","observe","childList","headObserver","head","subtree","attributes","attributeFilter","removeEventListener","disconnect","useEffect","useMemo","useRef","SyncedToolSchema","ToolConnectionMetadata","ToolWithSource","ThreadManagerAgent","ThreadManagerState","useAgent","stableStringify","UseToolSourceRegistrationOptions","manager","ReturnType","tools","metadata","useToolSourceRegistration","options","toolsRef","current","localToolSchemasKey","tabId","schemas","map","t","name","description","inputSchema","annotations","sort","a","b","localeCompare","lastRegisteredKeyRef","console","debug","readyState","hasMetadata","toolCount","length","keyChanged","WebSocket","OPEN","registerTools","warn","localTools","toolSchemas","toolNames","stub","error","ExternalStoreThreadListAdapter","useAgent","useCallback","useEffect","useMemo","useRef","useState","CreateThreadParams","InitContextResult","PolicyEvent","PolicyPluginStatus","SiteToHubMessage","ThreadManagerAgent","ThreadManagerState","ThreadSummary","ThreadUpdateParams","ThreadWithDeleted","ToolSourceInfo","ToolWithSource","CallToolResult","AuthError","throwInitError","getEmbeddedAgentTabId","safeParseHubToSiteMessage","safeParsePolicyEventMessage","safeParseToolSourcesMessage","stableStringify","useLatest","useToolSourceMetadata","useToolSourceRegistration","ResolvedAuth","TicketAuth","ANONYMOUS_SESSION_KEY","getOrCreateAnonymousId","window","crypto","randomUUID","sessionId","localStorage","getItem","setItem","error","console","warn","Error","message","String","UseCloudflareThreadAdapterOptions","host","resolvedAuth","mcpTools","executeMCPTool","toolName","args","Record","Promise","UseCloudflareThreadAdapterResult","currentThreadId","setCurrentThreadId","threadId","threadListAdapter","isInitialized","isConnected","isReady","endUserId","organizationId","manager","ReturnType","toolSources","policyPluginStatus","policyEvents","clearPolicyEvents","authError","sortThreadsByRecency","lastMessageAt","createdAt","list","T","sort","a","b","aTime","bTime","isRegularThread","thread","status","isArchivedThread","useCloudflareThreadAdapter","options","isAnonymous","mode","ticketAuth","anthropicApiKey","effectiveUserId","orgId","userId","setIsInitialized","initialSyncComplete","setInitialSyncComplete","setEndUserId","setOrganizationId","setAuthError","threads","setThreads","lastSelectedThreadId","setLastSelectedThreadId","initPromiseRef","initAttemptedRef","autoCreateAttemptedRef","isMountedRef","current","agent","name","query","anonymous","undefined","onStateUpdate","state","source","trim","code","title","debugInfo","JSON","stringify","recoverable","tabId","setToolSources","setPolicyEvents","setPolicyPluginStatus","enabled","handleMessage","event","MessageEvent","toolSourcesMessage","data","prev","sources","policyEventMessage","slice","addEventListener","removeEventListener","readyState","WebSocket","OPEN","stub","getPolicyPluginStatus","then","catch","metadata","tools","msg","type","result","response","callId","send","content","text","isError","prevTicketRef","ticket","prevAnonymousKeyRef","ticketChanged","keyChanged","debug","ensureInitialized","origin","location","initContextAnonymous","initContextWithTicket","initResult","success","activeThreads","nonDeleted","filter","t","archivedThreads","some","id","isLoading","length","managerRef","ensureInitializedRef","organizationIdRef","activeThreadsRef","currentThreadIdRef","setLastSelectedThread","createThread","params","info","onRename","newTitle","updateThread","onArchive","archiveThread","nextActive","onUnarchive","restoreThread","onDelete","deleteThread","onSwitchToNewThread","onSwitchToThread","z","ThreadStatusSchema","enum","ThreadSummarySchema","object","id","string","status","title","optional","remoteId","externalId","organizationId","messageCount","number","totalTokens","lastMessageAt","nullable","createdAt","ThreadWithDeletedSchema","union","omit","extend","literal","ThreadMetadataSchema","threadId","userId","threadManagerName","CreateThreadParamsSchema","CreateThreadResultSchema","ThreadUpdateParamsSchema","totalTokensDelta","ThreadManagerContextSchema","endUserId","z","ThreadWithDeletedSchema","ThreadManagerStateSchema","object","threads","array","endUserId","string","nullable","organizationId","externalId","isAnonymous","boolean","optional","anthropicApiKey","lastSelectedThreadId","z","ToolSourceSelectorSchema","object","sourceId","string","tabId","ToolSourceSchema","origin","optional","url","title","iconUrl","connectedAt","number","lastSeenAt","ToolSourceInfoSchema","extend","toolCount","ToolConnectionMetadataSchema","ThreadToolSelectionSchema","selectedSources","array","ToolSourcesUpdateMessageSchema","type","literal","sources","z","ToolApprovalModeSchema","enum","ToolApprovalSettingsSchema","object","mode","z","ThreadMetadataSchema","ThreadToolSelectionSchema","ToolApprovalModeSchema","VoiceSessionStateSchema","object","isActive","boolean","isMuted","sessionId","string","min","routingMode","enum","default","handoffStatus","realtimeKitMeetingId","optional","realtimeKitCustomerParticipantId","realtimeKitSupportParticipantId","ThreadAgentStateSchema","threadMetadata","nullable","toolSelection","approvalMode","voiceSession","isAnonymous","anthropicApiKey","z","ToolSourceSchema","ToolAnnotationsSchema","object","title","string","optional","readOnlyHint","boolean","destructiveHint","idempotentHint","openWorldHint","catchall","any","SyncedToolSchemaSchema","name","description","inputSchema","record","annotations","sources","array","TOOL_SOURCE_SELECTOR","z","PolicyDecisionStatusSchema","enum","PolicyViolationSchema","object","policy_id","string","status","details","optional","PolicyPluginStatusSchema","enabled","boolean","name","PolicyEventSchema","toolName","callId","message","violations","array","latencyMs","number","timestamp","source","tabId","nullable","origin","url","title","PolicyEventMessageSchema","type","literal","event","z","PolicyDecisionStatusSchema","PolicyViolationSchema","ToolCallPolicyMetadataSchema","object","pluginName","string","status","message","violations","array","latencyMs","number","optional","evaluatedAt","callId","ToolCallMetadataSchema","startedAt","duration","sourceId","isError","boolean","wasAborted","policy","z","HubToSiteMessageSchema","discriminatedUnion","object","type","literal","callId","string","toolName","args","record","unknown","optional","SiteToHubMessageSchema","result","content","array","isError","boolean","passthrough","z","AUTH_ERROR_CODE","authErrorCodeValues","Object","values","AuthErrorCodeSchema","enum","ErrorCallToActionSchema","object","steps","array","string","examples","optional","ErrorContextSchema","issuer","configuredIssuer","currentDomain","allowedDomains","expectedIssuer","actualIssuer","missingField","catchall","any","InitContextResultSchema","success","boolean","endUserId","organizationId","isAnonymous","hasOrgContext","message","errorCode","errorTitle","callToAction","dashboardLink","docsLink","context","recoverable","debugInfo","z","RealtimeKitJoinResultSchema","object","meetingId","string","participantId","authToken","expiresAt","optional","z","TodoStatusSchema","enum","TodoSchema","object","text","string","status","UpdateTodosInputSchema","new","array","inProgress","number","done","clearPreviouslyDone","boolean","insertAt","optional","UpdateTodosResultSchema","todos","AskForPlanApprovalInputSchema","explainer","AskForPlanApprovalResultSchema","approved","z","MCPClientStateSchema","enum","MCPConnectionStateSchema","TabSourceConfigSchema","object","type","literal","targetOrigin","string","optional","channelId","HttpSourceConfigSchema","url","authToken","timeout","number","autoReconnect","boolean","transportType","customHeaders","record","MCPSourceConfigSchema","discriminatedUnion","ToolAnnotationsFullSchema","title","readOnlyHint","destructiveHint","idempotentHint","openWorldHint","passthrough","ToolWithSourceSchema","name","description","inputSchema","unknown","annotations","_sourceId","MCPSourceSchema","id","config","state","error","nullable","tools","array","resources","resourceTemplates","prompts","isToolDestructive","annotations","readOnlyHint","destructiveHint","unstable_createMessageConverter","useExternalMessageConverter","ReasoningMessagePart","ToolCallMessagePart","TextMessagePart","SourceMessagePart","getToolName","isToolUIPart","ToolCallMetadata","UIMessage","MessagePart","NonNullable","JSONValue","key","JSONObject","stripClosingDelimiters","json","replace","getRawInput","part","rawInput","length","ConvertedPart","convertParts","message","metadata","Metadata","parts","filter","p","type","toolCallLastIndex","Map","i","set","toolCallId","messageMetadata","custom","toolStatuses","Record","payload","messageToolStatuses","converterMetadata","toolArtifacts","result","push","text","get","toolName","args","argsText","toolResult","isError","state","input","output","error","errorText","JSON","stringify","serverStatus","localStatus","toolStatus","artifact","needsApproval","undefined","statusPayload","interruptPayload","const","interrupt","status","reason","sourceType","id","sourceId","url","title","console","warn","CloudflareMessageConverter","createdAt","Date","role","fileParts","Extract","attachments","map","idx","toString","mediaType","startsWith","name","filename","content","image","data","mimeType","contentType","msgWithMeta","annotations","unstable_annotations","unstable_data","Array","isArray","default","useCallback","useEffect","useMemo","useRef","useState","useExternalStoreRuntime","AppendMessage","AssistantRuntime","ExternalStoreThreadListAdapter","ThreadMessage","useAgentChat","isToolDestructive","ToolCallMetadata","ThreadAgentState","ThreadManagerAgent","ThreadManagerState","ThreadToolSelection","ToolApprovalMode","ToolSourceInfo","ToolWithSource","ThreadAgentAgent","SerializableValue","CallToolResult","useAgent","UIMessage","CloudflareMessageConverter","formatToolResult","getEmbeddedAgentTabId","getPendingToolCallIds","sliceMessagesUntil","useLatest","DISCONNECTED_THREAD_ID","UseThreadRuntimeOptions","threadId","host","authToken","manager","ReturnType","mcpTools","executeMCPTool","toolName","args","Record","Promise","toolSources","threadListAdapter","AddToolOutputOptions","toolCallId","output","ExecuteToolOptions","VoiceSyncCallbacks","appendUserMessage","text","appendAssistantMessage","appendToolCall","result","isError","UseThreadRuntimeResult","runtime","reset","isReady","hasPendingApprovals","toolExecution","executeTool","options","getToolMetadata","description","annotations","addToolOutput","toolApproval","mode","setMode","isDestructive","toolSelection","sources","selection","setSelection","currentSourceId","voiceSync","voiceSession","threadAgent","extractToolCallMetadata","_meta","rawMeta","charMeta","char","toolInvocation","metadata","Partial","sourceId","startedAt","duration","undefined","wasAborted","policy","useThreadRuntime","agentState","setAgentState","setToolSelectionState","toolCallArtifacts","setToolCallArtifacts","tabId","match","find","source","agent","name","startClosed","onStateUpdate","state","threadAgentRef","current","readyState","WebSocket","CLOSED","close","approvalMode","setApprovalMode","console","warn","OPEN","stub","catch","error","mcpToolsRef","approvalModeRef","pendingClientToolCallsRef","Set","setToolSelection","tool","t","Error","invokeTool","prev","chatAddToolOutputRef","autoContinue","chat","autoContinueAfterToolResult","resume","onToolCall","toolcall","toolCall","tools","add","input","resultText","delete","size","message","String","prepareSendMessagesRequest","body","messages","clientTools","requestTabId","Boolean","length","isRunning","status","useThreadMessages","toolArtifacts","onNew","isVoiceMessage","custom","firstContent","content","type","voiceUIMessage","id","Date","now","Math","random","toString","slice","role","parts","setMessages","clear","sendMessage","onEdit","previousMessages","newMessages","parentId","onReload","regenerate","onCancel","stop","onAddToolResult","isLast","store","adapters","threadList","clearHistory","runVoiceSync","actionLabel","context","operation","appendVoiceUserMessage","appendVoiceMessage","appendVoiceAssistantMessage","appendVoiceToolCall","createContext","useContext","ToolApprovalMode","ToolWithSource","ToolApprovalContextValue","mode","setMode","isDestructive","annotations","ToolApprovalContext","useToolApproval","context","Error","useOptionalToolApproval","createContext","useContext","CallToolResult","ToolWithSource","FC","ReactNode","AddToolOutputOptions","ExecuteToolOptions","ToolExecutionContextValue","executeTool","toolName","args","Record","options","Promise","getToolMetadata","description","annotations","addToolOutput","hasPendingApprovals","ToolExecutionContext","ToolExecutionProviderProps","value","children","ToolExecutionProvider","t0","$","_c","t1","useToolExecution","context","Error","useOptionalToolExecution","createContext","useContext","ThreadToolSelection","ToolSourceInfo","FC","ReactNode","ToolSelectionContextValue","sources","selection","setSelection","Promise","currentSourceId","ToolSelectionContext","ToolSelectionProviderProps","value","children","ToolSelectionProvider","t0","$","_c","t1","useToolSelection","context","Error","useOptionalToolSelection","createContext","Suspense","useCallback","useContext","useEffect","useMemo","useRef","ReactNode","FC","Skeleton","AssistantRuntimeProvider","PolicyEvent","ThreadAgentAgent","ThreadAgentState","ThreadManagerAgent","ThreadManagerState","ToolWithSource","CallToolResult","useAgent","ChatErrorBoundary","useCloudflareThreadAdapter","useThreadRuntime","VoiceSyncCallbacks","AuthErrorException","ResolvedAuth","ToolApprovalContext","ToolExecutionProvider","ToolSelectionProvider","CloudflareThreadRuntimeProviderProps","children","host","resolvedAuth","mcpTools","executeMCPTool","toolName","args","Record","Promise","ThreadListItem","id","title","status","CloudflareThreadContextValue","isInitialized","isReady","isLoading","endUserId","organizationId","currentThreadId","setCurrentThreadId","threadId","reset","startNew","archiveThread","threads","archivedThreads","authError","AuthError","PolicyPluginContextValue","enabled","name","events","clearEvents","CloudflareThreadContext","PolicyPluginContext","VoiceSyncContext","VoiceSessionContext","undefined","ThreadAgentConnection","ReturnType","ThreadAgentContext","useOptionalVoiceSync","useVoiceSync","context","Error","useVoiceSession","useOptionalVoiceSession","useThreadAgent","useOptionalThreadAgent","useCloudflareThread","usePolicyPlugin","useOptionalPolicyPlugin","ThreadRuntimeSkeleton","$","_c","t0","Symbol","for","t1","t2","t3","t4","ThreadRuntimeBridgeProps","manager","threadListAdapter","toolSources","onResetChange","onStartNewThread","ThreadRuntimeBridge","authToken","mode","ticketAuth","ticket","runtime","resetThread","toolExecution","toolApproval","toolSelection","hasPendingApprovals","voiceSync","voiceSession","threadAgent","executeTool","getToolMetadata","addToolOutput","toolExecutionValue","resetThreadRef","current","stableReset","onResetChangeRef","error","info","console","message","componentStack","CloudflareThreadRuntimeProvider","policyPluginStatus","policyEvents","clearPolicyEvents","resetRef","handleResetChange","newReset","onSwitchToNewThreadRef","onSwitchToNewThread","onArchiveRef","onArchive","contextValue","policyPluginValue","normalizeToolName","name","normalizeToolName","humanizeToolName","name","progressive","normalizedName","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","FORM_CANCELLED_MESSAGE","formatToolDenialWithReason","reason","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","messageState","hasPendingPart","some","partRuntime","getMessagePartByToolCallId","addToolResult","error","Error","message","resolveAllPendingToolCallsByName","pendingCalls","resolved","call","resolveAllPendingToolCalls","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","REALTIME_EVENT","SESSION_STATE","SESSION_CONNECTING","SESSION_CONNECTED","SESSION_CLOSED","AUDIO_LEVEL","USER_TRANSCRIPT_DONE","ASSISTANT_TRANSCRIPT","ASSISTANT_TRANSCRIPT_DONE","TEXT","TEXT_DONE","TOOL_CALL_STARTED","TOOL_CALL_COMPLETED","SPEECH_STARTED","SPEECH_STOPPED","AUDIO_STARTED","AUDIO_STOPPED","ERROR","const","RealtimeEvent","REALTIME_MESSAGE","RESPONSE_CREATED","RESPONSE_DONE","RESPONSE_CREATE","RESPONSE_FUNCTION_CALL_ARGUMENTS_DONE","RESPONSE_FUNCTION_CALL_ARGUMENTS_DELTA","RESPONSE_OUTPUT_ITEM_ADDED","RESPONSE_OUTPUT_ITEM_DONE","RESPONSE_CONTENT_PART_ADDED","RESPONSE_CONTENT_PART_DONE","RESPONSE_OUTPUT_AUDIO_DELTA","RESPONSE_OUTPUT_AUDIO_DONE","RESPONSE_AUDIO_DONE","RESPONSE_AUDIO_TRANSCRIPT_DELTA","RESPONSE_AUDIO_TRANSCRIPT_DONE","RESPONSE_TEXT_DELTA","RESPONSE_TEXT_DONE","INPUT_AUDIO_BUFFER_SPEECH_STARTED","INPUT_AUDIO_BUFFER_SPEECH_STOPPED","INPUT_AUDIO_BUFFER_COMMITTED","OUTPUT_AUDIO_BUFFER_STARTED","OUTPUT_AUDIO_BUFFER_STOPPED","OUTPUT_AUDIO_BUFFER_CLEARED","CONVERSATION_ITEM_CREATED","CONVERSATION_ITEM_TRUNCATED","CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED","CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_DELTA","CONVERSATION_ITEM_CREATE","SESSION_UPDATE","SESSION_CREATED","SESSION_UPDATED","RATE_LIMITS_UPDATED","RealtimeMessageType","AUDIO_EVENT_BY_MESSAGE","AudioLifecycleMessageType","TRANSCRIPT_EVENT_BY_MESSAGE","TranscriptMessageType","TurnDetectionConfig","type","threshold","prefix_padding_ms","silence_duration_ms","create_response","interrupt_response","AudioTranscriptionConfig","model","language","NoiseReductionConfig","AudioInputConfig","format","noise_reduction","transcription","turn_detection","AudioOutputConfig","voice","AudioConfig","input","output","GASessionConfig","instructions","tools","OpenAITool","audio","RealtimeConfig","apiUrl","tokenEndpoint","inputDeviceId","RealtimeSession","pc","RTCPeerConnection","dataChannel","RTCDataChannel","audioElement","HTMLAudioElement","localStream","MediaStream","remoteStream","cleanup","name","description","parameters","properties","Record","required","SessionConfig","modalities","tool_choice","input_audio_transcription","FunctionCall","arguments","call_id","status","ConversationItem","role","content","RealtimeMessage","key","isRealtimeMessage","data","ToolExecutionResult","success","error","EventCallback","IEventEmitter","on","event","callback","off","emit","AudioLevelData","micLevel","micFrequency","speakerLevel","speakerFrequency","TranscriptData","text","isDone","ToolCallData","toolName","VoiceModeState","isActive","isConnecting","isMuted","isUserSpeaking","isAssistantSpeaking","isError","connectionState","audioLevel","transcript","toolCall","SessionStateEventData","state","durationSeconds","UserTranscriptEventData","AssistantTranscriptEventData","delta","ToolCallStartedEventData","ToolCallCompletedEventData","args","result","NestedErrorObject","code","message","param","event_id","ErrorEventData","isSessionStateEventData","d","includes","isUserTranscriptEventData","isAssistantTranscriptEventData","undefined","isToolCallStartedEventData","isToolCallCompletedEventData","isErrorEventData","hasError","extractErrorMessage","nestedError","isAudioLevelData","Array","isArray","RESPONSE_REQUEST_DELAY_MS","AUDIO_EVENT_BY_MESSAGE","REALTIME_EVENT","REALTIME_MESSAGE","TRANSCRIPT_EVENT_BY_MESSAGE","AudioLifecycleMessageType","TranscriptMessageType","EventEmitter","ToolManager","isRealtimeMessage","FunctionCall","RealtimeMessage","ResponseOutputItem","type","status","name","call_id","arguments","isExecutableFunctionCall","item","undefined","console","warn","MessageHandler","isProcessingResponse","pendingFunctionCalls","Set","processedFunctionCalls","responseRequestTimer","ReturnType","setTimeout","hasRequestedResponse","constructor","toolManager","eventEmitter","handleMessage","data","dataChannel","RTCDataChannel","Promise","msg","parsed","JSON","parse","error","log","RESPONSE_CREATED","handleResponseCreated","RESPONSE_DONE","handleResponseDone","RESPONSE_FUNCTION_CALL_ARGUMENTS_DONE","handleFunctionCallArguments","RESPONSE_FUNCTION_CALL_ARGUMENTS_DELTA","RESPONSE_OUTPUT_ITEM_DONE","handleResponseOutputItemDone","INPUT_AUDIO_BUFFER_SPEECH_STARTED","INPUT_AUDIO_BUFFER_SPEECH_STOPPED","handleSpeechEvents","RESPONSE_OUTPUT_AUDIO_DELTA","RESPONSE_OUTPUT_AUDIO_DONE","OUTPUT_AUDIO_BUFFER_STARTED","OUTPUT_AUDIO_BUFFER_STOPPED","RESPONSE_AUDIO_DONE","handleAudioEvents","RESPONSE_AUDIO_TRANSCRIPT_DELTA","RESPONSE_AUDIO_TRANSCRIPT_DONE","RESPONSE_TEXT_DELTA","RESPONSE_TEXT_DONE","handleTranscriptEvents","CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED","handleUserTranscript","ERROR","handleError","SESSION_CREATED","SESSION_UPDATED","handleSessionEvents","CONVERSATION_ITEM_CREATED","CONVERSATION_ITEM_TRUNCATED","INPUT_AUDIO_BUFFER_COMMITTED","OUTPUT_AUDIO_BUFFER_CLEARED","RESPONSE_OUTPUT_ITEM_ADDED","RESPONSE_CONTENT_PART_ADDED","RESPONSE_CONTENT_PART_DONE","CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_DELTA","RATE_LIMITS_UPDATED","_msg","outputItems","extractResponseOutput","response","hasFunctionCalls","some","length","functionCalls","filter","map","functionCall","executeFunctionCallIfNeeded","size","requestResponseIfNeeded","outputItem","r","Record","Array","isArray","output","eventType","SPEECH_STARTED","SPEECH_STOPPED","emit","Object","hasOwn","has","add","executeFunctionCall","delta","transcript","USER_TRANSCRIPT_DONE","text","session","tools","toolNames","slice","tool","toolCount","hasInputTranscription","input_audio_transcription","clearTimeout","argsString","callId","argsLength","parsedArgs","parseError","argsSample","TOOL_CALL_STARTED","result","executeToolCall","success","readyState","TOOL_CALL_COMPLETED","args","resultString","stringify","CONVERSATION_ITEM_CREATE","send","sendToolError","String","delete","errorResponse","RESPONSE_CREATE","reset","clear","jsonrepair","FunctionCall","OpenAITool","ToolExecutionResult","RegisteredTool","name","description","inputSchema","Record","ToolExecutor","args","Promise","ToolManager","tools","executor","lastSentToolSignature","setTools","console","log","length","getToolSignature","slice","setExecutor","resetSession","map","t","sort","join","hasToolsChanged","currentSignature","changed","currentSignatureLength","lastSentSignatureLength","currentFirst50","lastSentFirst50","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","data","String","toolList","count","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","inputDeviceId","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","deviceConstraint","exact","undefined","navigator","mediaDevices","audio","deviceId","echoCancellation","noiseSuppression","autoGainControl","baseUrl","RTCSessionDescriptionInit","endpoint","Authorization","status","answerSdp","type","const","AUDIO_FREQUENCY_BINS","AUDIO_VISUALIZATION_INTERVAL_MS","debugLog","REALTIME_DEFAULT_VOICE","AudioAnalyzer","EventEmitter","REALTIME_EVENT","REALTIME_MESSAGE","MessageHandler","ToolManager","WebRTCManager","RegisteredTool","ToolExecutor","EventCallback","RealtimeConfig","RealtimeSession","EMPTY_FREQUENCY_TEMPLATE","Object","freeze","Array","fill","createZeroFrequencyArray","OpenAIRealtimeService","session","webrtcManager","toolManager","messageHandler","eventEmitter","muted","lastState","localAnalyzer","remoteAnalyzer","visualizationInterval","ReturnType","setInterval","sessionStartTime","onToolsChangedCallback","pendingConfig","inputDeviceId","constructor","tokenEndpoint","setTools","tools","console","log","length","slice","map","t","name","join","isSessionActive","updateSessionTools","setToolExecutor","executor","setExecutor","onToolsChanged","callback","startSession","config","Promise","stopSession","Date","now","emitSessionState","createSession","setupDataChannel","dataChannel","setupPeerConnectionMonitoring","pc","localStream","initializeLocalAnalyzer","remoteStream","initializeRemoteAnalyzerSafely","originalOntrack","ontrack","e","call","streams","warn","error","handleSessionError","durationSeconds","Math","floor","clearInterval","destroy","cleanup","reset","resetSession","sendUserMessage","text","Error","message","type","CONVERSATION_ITEM_CREATE","item","role","content","send","JSON","stringify","RESPONSE_CREATE","readyState","getLocalStream","MediaStream","getRemoteStream","toggleMute","audioElement","isMuted","setInputDevice","deviceId","stream","navigator","mediaDevices","getUserMedia","audio","exact","echoCancellation","noiseSuppression","autoGainControl","nextTrack","getAudioTracks","getTracks","forEach","track","stop","sender","getSenders","find","s","kind","replaceTrack","oldStream","getInputDeviceId","pauseAudio","pause","resumeAudio","play","catch","on","event","off","getSessionStatus","state","isActive","RTCDataChannel","addEventListener","configureSession","MessageEvent","handleMessage","data","emit","ERROR","SESSION_CLOSED","RTCPeerConnection","connectionState","iceConnectionState","initializeRemoteAnalyzer","formatToolsForOpenAI","markToolsSent","sessionConfig","modalities","instructions","getSessionInstructions","voice","tool_choice","turn_detection","threshold","prefix_padding_ms","silence_duration_ms","input_audio_transcription","model","sessionUpdate","SESSION_UPDATE","changesSummary","getChangesSummary","total","added","removed","String","clonedStream","clone","initialize","startAudioVisualization","logCounter","micLevel","getAudioLevel","micFrequency","getFrequencyData","speakerLevel","speakerFrequency","mic","toFixed","speaker","AUDIO_LEVEL","extra","Record","payload","SESSION_STATE","SESSION_CONNECTING","SESSION_CONNECTED","useCallback","useEffect","useMemo","useRef","useState","TOOL_CALL_DISPLAY_DURATION_MS","TOOL_CALL_ERROR_DISPLAY_DURATION_MS","REALTIME_EVENT","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","onToolComplete","toolName","args","Record","result","isError","UseVoiceModeReturn","startSession","config","Promise","stopSession","toggleMute","muted","sendMessage","pauseAudio","resumeAudio","setInputDevice","deviceId","useVoiceMode","options","$","_c","isActive","setIsActive","isConnecting","setIsConnecting","isMuted","setIsMuted","isUserSpeaking","setIsUserSpeaking","isAssistantSpeaking","setIsAssistantSpeaking","setIsError","connectionState","setConnectionState","audioLevel","setAudioLevel","transcript","setTranscript","toolCall","setToolCall","setError","inputDeviceId","setInputDeviceId","serviceRef","onConnectRef","onDisconnectRef","onErrorRef","onUserTranscriptRef","onAssistantTranscriptRef","onToolCompleteRef","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","name","handleToolCallCompleted","data_5","normalizedArgs","normalizedResult","JSON","stringify","success","setTimeout","undefined","handleError","data_6","errorMsg","handleUserSpeechStarted","handleUserSpeechStopped","handleAssistantAudioStarted","handleAssistantAudioStopped","on","SESSION_STATE","AUDIO_LEVEL","USER_TRANSCRIPT_DONE","ASSISTANT_TRANSCRIPT","ASSISTANT_TRANSCRIPT_DONE","TOOL_CALL_STARTED","TOOL_CALL_COMPLETED","SPEECH_STARTED","SPEECH_STOPPED","AUDIO_STARTED","AUDIO_STOPPED","ERROR","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","service_8","t16","createContext","useContext","useMemo","useVoiceMode","ReactNode","UseVoiceModeReturn","RegisteredTool","ToolExecutor","VoiceModeContextValue","isSupported","VoiceModeContext","VoiceModeProviderProps","children","tokenEndpoint","tools","toolExecutor","onConnect","onDisconnect","durationSeconds","onError","error","onUserTranscript","text","onAssistantTranscript","onToolComplete","toolName","args","Record","result","isError","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","useThread","useThreadRuntime","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","VOICE_TOOL_RESULT_MESSAGES","TOOL_DENIED_MESSAGE","getPendingToolCallsByName","resolveAllPendingToolCalls","resolveAllPendingToolCallsByName","resolvePendingToolCall","useThreadAgent","useOptionalMCPTools","useOptionalToolApproval","useOptionalVoiceModeContext","VoiceModeProvider","useOptionalVoiceToolApproval","VoiceToolApprovalProvider","isToolDestructive","ToolCallMetadata","ToolWithSource","FC","MutableRefObject","ReactNode","RefObject","RegisteredTool","ToolExecutor","VoiceToolCallData","toolCallId","toolName","args","Record","result","isError","artifact","AddToolCallToThread","data","VoiceMessageMetadata","source","voiceSessionId","timestamp","VoiceThreadContextValue","isActive","isConnecting","isMuted","isUserSpeaking","isAssistantSpeaking","isSupported","error","sessionId","start","Promise","stop","toggleMute","muted","sendMessage","text","pauseAudio","resumeAudio","setInputDevice","deviceId","inputDeviceId","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","onUserTranscript","onAssistantTranscript","onToolComplete","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","threadMessages","_temp","threadAgent","t1","Symbol","for","required","t2","allVoiceTools","t3","Map","pendingVoiceResolutions","t4","readyState","WebSocket","OPEN","Error","stub","startHumanHandoff","callTool","tools","find","t_0","t","needsApproval","mode","annotations","callId","approved","requestApproval","resultMessage","handled","resolvedNow","queue","get","push","set","textContent","_temp2","toolExecutor","t5","size","queue_0","entries","freshQueue","filter","t6","length","delete","pendingCalls","queueIndex","call","result_0","messageId","t7","t8","t9","VoiceThreadBridge","map","VoiceThreadContextProvider","bb0","undefined","startSession","stopSession","contextValue","useVoiceThread","context","useOptionalVoiceThread","useIsVoiceActive","messages","c","Button","useVoiceThread","useVoiceToolApproval","cn","humanizeToolName","Check","X","useEffect","useMemo","useRef","FC","VoiceToolApprovalPanelProps","variant","VoiceToolApprovalPanel","t0","$","_c","t1","undefined","voiceApproval","voiceThread","wasWaitingRef","isWaitingForApproval","isWaiting","pendingApproval","timeoutRemaining","approve","deny","t2","t3","current","pauseAudio","resumeAudio","t4","t5","window","handleKeyDown","event","target","HTMLElement","isTypingTarget","tagName","isContentEditable","key","preventDefault","addEventListener","removeEventListener","t6","bb0","t8","JSON","stringify","args","t7","error","console","argsPreview","t9","Symbol","for","t10","t11","toolName","t12","t13","t14","t15","t16","t17","t18","t19","useEffect","useState","useDelayedState","value","delay","$","_c","delayedValue","setDelayedValue","t0","t1","timer","setTimeout","clearTimeout","createContext","useCallback","useContext","useMemo","FC","ReactNode","ToolWithSource","ToolExclusionFilter","toolName","tool","ToolExclusionContextValue","shouldExclude","filterTools","tools","ToolExclusionContext","ToolExclusionProviderProps","children","exclude","excludeNames","excludePrefixes","ToolExclusionProvider","t0","$","_c","t1","name","includes","some","prefix","startsWith","t2","filter","tool_0","t3","value","t4","useToolExclusion","context","Error","useOptionalToolExclusion","useAssistantTool","memo","useMemo","useMCPTools","useOptionalToolExclusion","CallToolResult","ToolWithSource","FC","formatToolResult","result","textContent","content","map","c","type","text","JSON","stringify","join","Camera","FileText","MousePointer","Navigation","PenLine","Search","Trash2","Wrench","normalizeToolName","LucideIcon","getToolIcon","toolName","name","toLowerCase","includes","c","_c","AlertCircle","AlertTriangle","Check","ChevronDownIcon","ChevronUpIcon","Loader2","X","useCallback","useMemo","useState","React","ToolResponse","useDelayedState","useMCPTools","formatToolResult","useToolExecution","cn","formatArgs","humanizeToolName","TOOL_DENIED_MESSAGE","normalizeToolName","getToolIcon","ToolCallMessagePartComponent","ToolCallMetadata","StatusVariant","STATUS_BORDER","Record","running","success","error","cancelled","warning","STATUS_ACCENT","STATUS_ICON_RING","extractProgress","value","obj","maybeProgress","progress","percentage","pct","Number","isFinite","Math","max","min","getErrorCodeDescription","code","ParsedError","summary","details","validationErrors","ValidationError","path","message","expected","received","options","parseErrorMessage","errorMessage","mcpErrorMatch","match","errorCode","parseInt","fullMessage","arrayStartIdx","indexOf","depth","arrayEndIdx","i","length","jsonStr","substring","parsed","JSON","parse","Array","isArray","cleanedMessage","replace","includes","checkForError","result","startsWith","isError","extractErrorDetails","status","type","reason","errorStr","stringify","StatusIcon","FC","className","t0","$","t1","Symbol","for","iconMap","Icon","t2","t3","t4","t5","t6","t7","ProgressBar","round","width","ValidationErrorDisplay","errors","getErrorCodeChip","_temp","err","idx","fieldPath","join","trim","slice","map","_temp2","ApprovedResult","approved","isApprovedResult","isDeniedResult","hasStatusError","parseToolCallMetadata","artifact","metadata","Partial","sourceId","startedAt","duration","PolicySummary","policy","NonNullable","toneClass","pluginName","violations","RunningToolDisplay","toolName","partialResult","t8","t9","t10","undefined","t11","ApprovalDialog","toolDescription","inputArgs","onApprove","onDeny","isExecuting","isHovered","setIsHovered","ToolIcon","Object","keys","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","t24","t25","CompletedToolDisplay","argsText","isExpanded","setIsExpanded","ErrorToolDisplay","parsedError","errorInfo","DeniedToolDisplay","UnifiedToolFallback","toolCallId","args","addResult","callTool","tools","toolExecution","setIsExecuting","parsedArgs","e","console","warn","normalizedToolName","toolMetadata","getToolMetadata","localTool","find","t","name","description","requiresApproval","executeTool","handleApprove","toolResult","resultText","addToolOutput","output","Error","String","handleDeny","statusType","isPendingApproval","showApprovalDialog","hasErrorResult","displayResult","opt","ComposerAddAttachment","ComposerAttachments","UserMessageAttachments","MarkdownText","Reasoning","ReasoningGroup","TooltipIconButton","Button","LiveWaveform","MicSelector","usePrompts","useCloudflareThread","usePolicyPlugin","useThreadAgent","useVoiceSession","useToolApproval","useToolSelection","useVoiceThread","useVoiceToolApproval","cn","ActionBarPrimitive","AssistantIf","ComposerPrimitive","ErrorPrimitive","MessagePrimitive","ThreadPrimitive","RealtimeKitJoinResult","ThreadToolSelection","ToolSourceInfo","VoiceSessionState","ArrowDownIcon","ArrowUpIcon","CheckIcon","CopyIcon","History","PhoneCall","Plus","ShieldAlert","Shield","ShieldOff","SquareIcon","X","Suspense","lazy","useCallback","useEffect","useMemo","useState","FC","VoiceToolApprovalPanel","UnifiedToolFallback","ThreadProps","onThreadsClick","onNewThread","onClose","HandoffStatus","AI_ONLY_HANDOFF_STATUS","glassmorphicButtonClass","VoiceHandoffPanel","ThinkingIndicator","$","_c","t0","Symbol","for","_temp2","Thread","voiceSession","threadAgent","stop","stopVoice","isActive","isVoiceActive","handoffStatus","isHandoffActive","handoffJoin","setHandoffJoin","handoffError","setHandoffError","isRequestingHandoff","setIsRequestingHandoff","requestHandoffToken","readyState","WebSocket","OPEN","result","stub","startHumanHandoff","error","Error","message","endHandoff","endHumanHandoff","e","currentTarget","dispatchEvent","CustomEvent","bubbles","composed","dispatchError","console","callbackError","debug","thread","isEmpty","UserMessage","AssistantMessage","ThreadScrollToBottom","ThreadWelcome","ThreadSuggestions","prompts","hasPrompts","slice","map","_temp3","t1","ComposerProps","Composer","isConnecting","isVoiceConnecting","start","startVoice","voiceApproval","currentThreadId","isVoiceMode","isVoiceApprovalPending","pendingApproval","t2","t3","t4","t5","getSourceLabel","source","title","trim","fallback","url","origin","URL","hostname","getSourceKey","sourceId","getSelectionKey","selection","buildSelection","current","selectedSources","selectedSet","Set","key","nextSelector","tabId","next","has","filter","item","ComposerToolSources","toolSelection","sources","currentSourceId","setSelection","selectedKeys","nextSelection","catch","_temp4","handleToggle","length","source_0","isSelected","label","isLocal","iconUrl","toolCount","ComposerApprovalButton","mode","setMode","isAskMode","ComposerPolicyButton","enabled","name","events","clearEvents","isOpen","setIsOpen","latestEvent","hasWarning","status","hasFailure","_temp5","toolName","t6","_temp6","t7","ComposerVoiceContent","isMuted","isUserSpeaking","isAssistantSpeaking","audioLevel","inputDeviceId","toggleMute","setInputDevice","deviceError","setDeviceError","voiceWaveLevel","Math","max","micLevel","speakerLevel","isVoiceWaveActive","deviceId","handleVoiceDeviceChange","ComposerVoiceControls","muted","onMutedChange","onStop","onSetInputDevice","Promise","ComposerHandoffButton","onStartVoice","isError","voiceError","isStarting","setIsStarting","_temp7","finally","handleClick","ComposerAction","_temp8","_temp9","t8","MessageError","Text","tools","Fallback","AssistantActionBar","_temp0","_temp1","_temp10","_temp","type","messages","at","parts","some","prompt","index","animationDelay","description","prev","event","idx","callId","Date","timestamp","toLocaleTimeString","hour","minute","isRunning","thread_0","isCopied","message_0","text","c","_c","ThreadListPrimitive","Archive","Plus","cn","FC","useCloudflareThread","AgentThreadListProps","className","onSelectThread","AgentThreadList","t0","$","threads","isLoading","currentThreadId","setCurrentThreadId","archiveThread","t1","t2","Symbol","for","t3","length","map","thread","id","title","catch","_temp","t4","ThreadListNew","ThreadListSkeleton","Array","from","_temp2","ThreadListItemProps","isActive","onSelect","onArchive","ThreadListItem","t5","e","stopPropagation","t6","t7","t8","t9","error","console","_","idx","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","c","_c","useThread","useMemo","TextPart","type","text","useLatestSummary","$","messages","_temp","t0","bb0","length","lastAssistantMessage","reverse","find","_temp2","textParts","content","filter","_temp3","at","m","role","thread","createContext","useContext","useMemo","FC","ReactNode","ThreadControlContextValue","reset","Promise","startNew","ThreadControlContext","ThreadControlProviderProps","children","ThreadControlProvider","t0","$","_c","t1","t2","value","t3","useThreadControl","context","Error","useOptionalThreadControl","useThread","useMemo","useActions","useLatestSummary","useMCPTools","useVoiceThread","useThreadControl","CallToolResult","GetPromptResult","Prompt","ToolWithSource","Action","AgentVoice","isActive","isConnecting","isError","isMuted","isUserSpeaking","isAssistantSpeaking","isSupported","error","sessionId","audioLevel","micLevel","speakerLevel","transcript","type","text","isDone","start","Promise","stop","toggleMute","muted","sendMessage","setInputDevice","deviceId","inputDeviceId","AgentThread","reset","startNew","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","thread","isVoiceActive","useAgent","$","_c","threadMessages","_temp","_temp2","t0","find","_temp3","t1","filter","_temp4","slice","t2","completed","_temp5","at","voiceThread","mcpContext","length","t3","t4","t5","callTool","threadControl","t6","thread_1","t7","t8","t9","a_1","a","a_0","thread_0","useAssistantApi","useAssistantState","useCallback","useMemo","AgentThreadStatus","AgentThreadListItem","id","title","status","remoteId","externalId","AgentThreadsState","isLoading","currentThreadId","threadIds","archivedThreadIds","itemsById","Readonly","Record","switchToThread","threadId","switchToNewThread","rename","archive","useAgentThreads","$","_c","api","_temp","_temp2","_temp3","_temp4","threadItems","_temp5","t0","entries","map","_temp6","Object","fromEntries","t1","threads","t2","t3","threadId_0","item","t4","threadId_1","t5","normalized","const","threads_3","threads_2","threads_1","threads_0","mainThreadId","X","React","Button","TooltipIconButton","cn","AuthError","glassmorphicButtonClass","ErrorScreenProps","error","dashboardBaseUrl","docsBaseUrl","onRetry","onContact","onClose","showDebug","className","ErrorScreen","t0","$","_c","t1","t2","t3","undefined","isDebugExpanded","setIsDebugExpanded","useState","dashboardUrl","dashboardLink","docsUrl","docsLink","startsWith","t4","t5","e","currentTarget","dispatchEvent","CustomEvent","bubbles","composed","t6","dispatchError","console","t7","callbackError","debug","Symbol","for","t8","title","t9","code","t10","message","t11","t12","context","Object","keys","length","currentDomain","missingField","expectedIssuer","actualIssuer","t13","callToAction","steps","map","_temp","t14","examples","_temp2","t15","debugInfo","e_0","open","t16","t17","t18","recoverable","t19","t20","t21","t22","t23","t24","t25","example","index_0","index","step","React","APP_ERROR_CODES","ErrorScreen","AuthError","AuthErrorBoundaryProps","children","ReactNode","dashboardBaseUrl","docsBaseUrl","fallback","ComponentType","error","reset","onError","Error","errorInfo","ErrorInfo","onRetryAuth","onClose","showDebug","AuthErrorBoundaryState","hasError","retryFailed","retryErrorMessage","AuthErrorBoundary","Component","constructor","props","state","getDerivedStateFromError","Partial","authError","isAuthError","code","INTERNAL_ERROR","title","message","recoverable","debugInfo","componentDidCatch","console","handlerError","handleReset","retryError","setState","handleContact","window","open","render","FallbackComponent","displayError","name","makeAssistantToolUI","ArrowRight","Check","DoneArgs","summary","actions","nextSteps","DoneToolUI","toolName","render","args","hasActions","length","hasNextSteps","map","action","i","step","c","_c","React","ChevronDownIcon","ChevronLeftIcon","ChevronRightIcon","DayPicker","getDefaultClassNames","DayButton","cn","Button","buttonVariants","Calendar","className","classNames","showOutsideDays","captionLayout","buttonVariant","formatters","components","props","ComponentProps","defaultClassNames","String","raw","formatMonthDropdown","date","toLocaleString","month","root","months","nav","button_previous","variant","button_next","month_caption","dropdowns","dropdown_root","dropdown","caption_label","table","weekdays","weekday","week","week_number_header","week_number","day","showWeekNumber","range_start","range_middle","range_end","today","outside","disabled","hidden","Root","rootRef","Chevron","orientation","CalendarDayButton","WeekNumber","children","t0","$","modifiers","ref","useRef","t1","t2","focused","current","focus","useEffect","T0","t3","t4","t5","toLocaleDateString","t6","selected","t7","t8","t9","t10","t11","React","PopoverPrimitive","cn","usePortalContainer","Popover","t0","$","_c","props","t1","PopoverTrigger","PopoverContent","className","t2","align","sideOffset","undefined","container","t3","t4","t5","PopoverAnchor","PopoverHeader","PopoverTitle","PopoverDescription","c","_c","useCallback","format","parseISO","CalendarIcon","WidgetProps","cn","Button","Calendar","Popover","PopoverContent","PopoverTrigger","DateWidget","t0","$","id","value","onChange","disabled","readonly","placeholder","rawErrors","t1","t2","undefined","T0","T1","T2","dateValue","handleSelect","t3","t4","t5","t6","t7","t8","t9","length","t10","date","hasError","t11","t12","Symbol","for","t13","t14","c","_c","useCallback","useMemo","ClockIcon","WidgetProps","cn","Button","Popover","PopoverContent","PopoverTrigger","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","TimeWidget","t0","$","id","value","onChange","disabled","readonly","placeholder","rawErrors","t1","t2","undefined","t3","bb0","t4","Symbol","for","split","parts","t5","t6","t7","hours","minutes","newHour","mins","handleHourChange","newMinute","hrs","handleMinuteChange","hasError","length","Array","from","_temp","hourOptions","_temp2","minuteOptions","t8","h","parseInt","m","ampm","displayHour","formatDisplayTime","t9","t10","t11","t12","t13","t14","t15","t16","t17","t18","t19","map","_temp3","t20","t21","t22","t23","t24","t25","_temp4","t26","t27","t28","minute","hour","__0","i_0","i","toString","padStart","_","c","_c","useCallback","useMemo","format","parseISO","CalendarIcon","ClockIcon","WidgetProps","cn","Button","Calendar","Popover","PopoverContent","PopoverTrigger","Select","SelectContent","SelectItem","SelectTrigger","SelectValue","DateTimeWidget","t0","$","id","value","onChange","disabled","readonly","placeholder","rawErrors","t1","t2","undefined","t3","bb0","t4","Symbol","for","dateValue","hours","minutes","t5","t6","parsed","getHours","toString","padStart","getMinutes","t7","date","h","m","hrs","parseInt","mins","newDate","Date","setHours","updateDateTime","date_0","handleDateSelect","newHour","handleHourChange","newMinute","handleMinuteChange","hasError","length","t8","Array","from","_temp","hourOptions","t9","_temp2","minuteOptions","t10","h_0","m_0","ampm","displayHour","formatDisplayDateTime","t11","t12","t13","t14","t15","t16","t17","t18","t19","t20","t21","t22","t23","map","_temp3","t24","t25","t26","t27","t28","_temp4","t29","t30","t31","t32","minute","hour","__0","i_0","i","_","c","_c","Ajv","makeAssistantToolUI","withTheme","Theme","ShadcnTheme","validator","AlertCircle","AlertTriangle","Check","ChevronDownIcon","ChevronUpIcon","FileText","X","useEffect","useRef","useState","JSONSchema7","Button","Collapsible","CollapsibleContent","CollapsibleTrigger","useToolExecution","FORM_CANCELLED_MESSAGE","DateWidget","TimeWidget","DateTimeWidget","Form","ajv","normalizeSchema","schema","obj","Record","type","toLowerCase","properties","Object","fromEntries","entries","map","key","value","items","Array","isArray","additionalProperties","keyword","const","not","validateSchema","isValid","errors","errorMessages","err","path","instancePath","message","join","SchemaErrorDisplay","t0","$","title","error","isOpen","setIsOpen","t1","Symbol","for","t2","t3","t4","t5","t6","t7","FormArgs","description","submitLabel","FormResult","parseFormData","data","keys","hasNonNumericKeys","some","isNaN","Number","parsed","JSON","parse","console","warn","substring","Error","String","formatValue","undefined","stringify","FormResultDisplay","T0","T1","t8","parsedData","t9","t10","t11","_temp","t12","t13","FormToolUI","toolName","render","args","result","status","addResult","toolCallId","toolExecution","errorSentRef","schemaError","setSchemaError","formDataRef","hasValidationError","setHasValidationError","isWaiting","normalizedSchema","current","validationError","addToolOutput","output","handleSubmit","formData","outputValue","handleForceSubmit","handleCancel","norender","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","controlledOpen","isControlled","undefined","internalOpen","setInternalOpen","setUserModeState","setPositionState","setHasUnread","setIsVoiceActiveState","setIsFullScreen","onOpenChangeRef","onModeChangeRef","current","next","pos","prev","value","useAgentUI","context","Error","useOptionalAgentUI","usePillMode","useHasUnread","useThread","useThreadRuntime","useMemo","ThreadAssistantMessage","PendingToolCallInfo","usePendingToolCalls","$","_c","messages","_temp","result","msg","role","assistantMsg","status","type","part","content","undefined","push","messageId","id","toolCallId","toolName","args","Record","t","useAssistantApi","useAssistantState","useThread","useThreadRuntime","useWebMCP","useCallback","useRef","z","useOptionalAgentUI","useOptionalMCPTools","useOptionalToolApproval","useOptionalToolSelection","useOptionalVoiceThread","usePendingToolCalls","resolvePendingToolCall","ToolApprovalMode","ToolSourceSelector","PillMode","DEBUG_TOOL_PREFIX","DEBUG_STATE_SCHEMA","const","DEBUG_UI_SCHEMA","action","enum","describe","mode","optional","text","string","DEBUG_TOOLS_SCHEMA","toolCallId","reason","sourceIds","array","DEBUG_SESSION_SCHEMA","threadId","DEBUG_STATE_DESCRIPTION","DEBUG_UI_DESCRIPTION","DEBUG_TOOLS_DESCRIPTION","DEBUG_SESSION_DESCRIPTION","UseWebMCPDebugToolsOptions","additionalState","cloudflareThread","isInitialized","isReady","currentThreadId","endUserId","organizationId","managerState","readyState","readyStateLabel","TOOL_DENIED_MESSAGE","useWebMCPDebugTools","options","agentUI","mcpTools","toolApproval","toolSelection","voiceThread","pendingToolCalls","threadRuntime","assistantApi","threadMessages","t","messages","isRunning","threadsLoading","threads","isLoading","mainThreadId","threadIds","stateRef","current","handleDebugState","state","ui","userMode","isFullScreen","hasUnread","position","error","map","msg","contentPreview","part","content","type","slice","toolCalls","filter","tc","toolCallPart","toolName","result","name","status","undefined","id","role","selectedSourceIds","selection","selectedSources","s","sourceId","thread","isEmpty","length","messageCount","pendingApprovals","messageId","args","currentAction","voice","isActive","isConnecting","isMuted","isSupported","transcript","tools","approvalMode","localTools","description","_sourceId","mcpSources","Array","from","sources","entries","source","toolCount","remoteSources","tabId","title","url","isSelected","includes","currentSourceId","connection","managerReadyState","managerReadyStateLabel","inputSchema","handler","handleDebugUi","success","setUserMode","expand","collapse","toggleFullScreen","resetPosition","x","y","markRead","composer","setText","send","message","e","Error","reset","handleDebugTools","target","find","callTool","resultString","JSON","stringify","errorMsg","denyMessage","denied","setMode","setSelection","currentSelected","newSelected","allSources","handleDebugSession","switchToNewThread","switchToThread","start","stop","toggleMute","isDebugTool","startsWith","useEffect","useRef","useState","ReactNode","TicketAuth","TicketExchangeResponse","AuthErrorJsonPayload","ErrorCallToAction","buildAuthError","AuthErrorException","AuthError","AuthErrorCode","ResolvedAuth","mode","ticketAuth","anthropicApiKey","TicketExchangeGateProps","children","auth","apiBase","authToken","clientId","TicketExchangeResult","success","code","title","message","callToAction","dashboardLink","docsLink","recoverable","exchangeTokenForTicket","Promise","response","fetch","method","headers","Authorization","body","JSON","stringify","client_id","ok","data","json","err","error","parseError","console","status","statusText","Error","String","contentType","get","ticket","userId","orgId","errorMessage","errorName","name","isNetworkError","TypeError","includes","DOMException","type","AuthLoadingSpinner","$","_c","t0","Symbol","for","TicketExchangeGate","providedTicket","exchangedTicket","setExchangedTicket","setError","setIsExchanging","exchangePromiseRef","isMountedRef","t1","t2","current","prevAuthTokenRef","prevProvidedTicketRef","t3","authTokenChanged","providedTicketChanged","t4","t5","t6","t7","then","result","catch","errorType","constructor","stack","undefined","debugInfo","finally","t8","err_0","errorCode","errorTitle","ToolWithSource","React","useCallback","useEffect","useState","FC","ReactNode","WEBMCP_PRODUCTION_API_BASE","resolveDevMode","AuthErrorBoundary","DoneToolUI","FormToolUI","MCPToolsProvider","useMCPTools","ToolExclusionProvider","ToolExclusionFilter","VoiceThreadBridge","AgentUIProvider","PillMode","CloudflareThreadRuntimeProvider","useCloudflareThread","useOptionalVoiceSync","ThreadControlProvider","useWebMCPDebugTools","TicketExchangeGate","ResolvedAuth","AgentProviderConfig","apiBase","authToken","clientId","ticketAuth","ticket","userId","orgId","anthropicApiKey","devMode","openaiApiKey","useLocalApi","host","agent","tokenEndpoint","autoConnectLocal","open","defaultOpen","defaultMode","onToolsChange","tools","onVoiceError","error","onVoiceConnect","onVoiceDisconnect","duration","onOpenChange","onModeChange","mode","excludeTools","excludeToolNames","excludeToolPrefixes","enableDebugTools","dashboardBaseUrl","docsBaseUrl","onAuthError","Error","errorInfo","ErrorInfo","showErrorDebug","onClose","AgentProviderProps","children","AgentRuntimeProps","resolvedAuth","DebugToolsRegistrar","$","_c","cloudflareThread","refreshTools","t0","currentThreadId","endUserId","isInitialized","isReady","organizationId","additionalState","t1","t2","timer","setTimeout","clearTimeout","StatefulRuntimeBridgeProps","StatefulRuntimeBridge","reset","startNew","voiceSync","appendUserMessage","appendAssistantMessage","t3","appendToolCall","t4","t5","Symbol","for","t6","t7","t8","UnifiedRuntime","mcpTools","callTool","AgentRuntime","AgentProvider","anthropicApiKeyProp","undefined","resolvedDevMode","isEmpty","hasExclusions","retryKey","setRetryKey","_temp","handleRetry","resolvedApiBase","url","URL","resolvedHost","resolvedTokenEndpoint","t9","t10","t11","content","t12","t13","t14","k","c","_c","useCallback","useEffect","useRef","useState","FC","ArrowLeft","Plus","X","Thread","TooltipIconButton","AgentThreadList","useAgent","useAgentThreads","AgentProvider","AgentProviderConfig","cn","Screen","AgentThreadProps","className","onClose","AgentThread","t0","$","providerConfig","t1","t2","AgentThreadInnerProps","AgentThreadInner","isLoading","threadIds","switchToNewThread","agent","screen","setScreen","Symbol","for","showThreadList","showThreadView","t3","thread","startNew","catch","_temp","startNewThread","t4","handleSelectThread","didAutoCreateThreadRef","t5","t6","length","current","t7","error","console","t8","glassmorphicButtonClass","t9","c","_c","useCallback","useEffect","useRef","useState","createPortal","FC","ReactNode","PortalContainerProvider","ShadowRootError","message","details","ShadowRootProps","children","styles","className","mode","ShadowRoot","t0","$","t1","undefined","hostRef","portalContainer","setPortalContainer","error","setError","detectTheme","_temp","t2","t3","Symbol","for","host","current","syncTheme","isDark","classList","toggle","observer","MutationObserver","observe","document","documentElement","attributes","attributeFilter","mediaQuery","window","matchMedia","addEventListener","disconnect","removeEventListener","t4","t5","host_0","shadow","shadowRoot","attachShadow","t6","e","console","Error","styleElement","querySelector","createElement","setAttribute","insertBefore","firstChild","textContent","container","appendChild","t7","display","alignItems","justifyContent","padding","backgroundColor","border","borderRadius","color","fontSize","textAlign","fontWeight","marginBottom","t8","t9","opacity","t10","marginTop","t11","t12","HTMLElement","html","contains","matches","WEBMCP_SHADOW_STYLES","getShadowStyles","FC","resolveDevMode","DevModeConfig","TicketAuth","AgentThread","ShadowRoot","WEBMCP_SHADOW_STYLES","WEBMCP_PRODUCTION_API_BASE","MCPToolsProvider","useMCPTools","MCPToolsContextValue","MCPToolsProviderProps","CharProps","authToken","clientId","ticketAuth","open","className","onClose","devMode","enableDebugTools","getDefaultApiBase","useLocalApi","window","location","origin","Char","t0","$","_c","t1","undefined","apiBase","resolvedDevMode","t2","Symbol","for","bb0","t3","isEmpty","authMode","t4","console","debug","hasAuthToken","hasClientId","hasTicketAuth","mode","voiceEnabled","openaiApiKey","anthropicApiKey","t5"],"sources":["../src/utils/dev-mode.ts","../src/providers/PortalContainerProvider.tsx","../src/components/ui/tooltip.tsx","../src/components/ui/dialog.tsx","../src/components/ui/avatar.tsx","../src/components/assistant-ui/tooltip-icon-button.tsx","../src/components/assistant-ui/attachment.tsx","../src/components/assistant-ui/markdown-text.tsx","../src/components/ui/collapsible.tsx","../src/components/assistant-ui/reasoning.tsx","../src/components/ui/live-waveform.tsx","../src/components/ui/select.tsx","../src/components/ui/mic-selector.tsx","../src/utils/constants.ts","../src/utils/mcp-transport.ts","../src/providers/MCPToolsProvider.tsx","../src/hooks/usePrompts.ts","../src/components/ui/skeleton.tsx","../src/components/errors/ChatErrorBoundary.tsx","../../auth/dist/oidc/validators/token-size.js","../../auth/dist/idp/constants.js","../../auth/dist/oidc/jwt-verifier.js","../../auth/dist/idp/schemas.js","../../auth/dist/idp/domain-validation.js","../../auth/dist/errors/codes.js","../../auth/dist/errors/builder.js","../src/utils/convert-init-error.ts","../src/hooks/thread-runtime-utils.ts","../src/hooks/useToolSourceMetadata.tsx","../src/hooks/useToolSourceRegistration.tsx","../src/hooks/useCloudflareThreadAdapter.tsx","../../shared-types/dist/schemas/thread.js","../../shared-types/dist/schemas/thread-manager-state.js","../../shared-types/dist/schemas/tool-source.js","../../shared-types/dist/schemas/tool-approval.js","../../shared-types/dist/schemas/thread-agent-state.js","../../shared-types/dist/schemas/tool-sync.js","../../shared-types/dist/schemas/policy-plugin.js","../../shared-types/dist/schemas/tool-call-metadata.js","../../shared-types/dist/schemas/rpc-messages.js","../../shared-types/dist/schemas/init-context.js","../../shared-types/dist/schemas/realtimekit.js","../../shared-types/dist/schemas/planning.js","../../shared-types/dist/schemas/mcp-client.js","../../shared-types/dist/utils/tool-destructive.js","../src/utils/converter.ts","../src/hooks/useThreadRuntime.tsx","../src/providers/ToolApprovalContext.tsx","../src/providers/ToolExecutionProvider.tsx","../src/providers/ToolSelectionProvider.tsx","../src/providers/CloudflareThreadRuntimeProvider.tsx","../src/utils/tool-names.ts","../src/utils/format.ts","../src/utils/thread-utils.ts","../src/services/realtime/audio-analyzer.ts","../src/services/realtime/event-emitter.ts","../src/services/realtime/events.ts","../src/services/realtime/types.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/hooks/useVoiceMode.ts","../src/providers/VoiceModeProvider.tsx","../src/providers/VoiceToolApprovalProvider.tsx","../src/providers/VoiceThreadBridge.tsx","../src/components/voice/VoiceToolApprovalPanel.tsx","../src/hooks/useDelayedState.ts","../src/providers/ToolExclusionProvider.tsx","../src/providers/MCPToolRegistry.tsx","../src/utils/tool-icons.ts","../src/components/shared/UnifiedToolFallback.tsx","../src/components/assistant-ui/thread.tsx","../src/components/agent/AgentThreadList.tsx","../src/hooks/useActions.ts","../src/hooks/useLatestSummary.ts","../src/providers/ThreadControlProvider.tsx","../src/hooks/useAgent.ts","../src/hooks/useAgentThreads.ts","../src/components/errors/ErrorScreen.tsx","../src/components/errors/AuthErrorBoundary.tsx","../src/tools/DoneToolUI.tsx","../src/components/ui/calendar.tsx","../src/components/ui/popover.tsx","../src/tools/widgets/DateWidget.tsx","../src/tools/widgets/TimeWidget.tsx","../src/tools/widgets/DateTimeWidget.tsx","../src/tools/FormToolUI.tsx","../src/providers/AgentUIProvider.tsx","../src/hooks/usePendingToolCalls.ts","../src/hooks/use-webmcp-debug-tools.ts","../src/providers/TicketExchangeGate.tsx","../src/providers/AgentProvider.tsx","../src/public/AgentThread.tsx","../src/components/agent/ShadowRoot.tsx","../src/generated/inline-styles.ts","../src/index.tsx"],"sourcesContent":["export interface DevModeConfig {\n\t/**\n\t * Your Anthropic API key for chat.\n\t * Required for anonymous mode (no authToken).\n\t */\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\nexport interface DevModeResolution {\n\tdevMode?: DevModeConfig\n\tisEmpty: boolean\n}\n\nfunction normalizeApiKey(value?: string): string | undefined {\n\tconst trimmed = value?.trim()\n\treturn trimmed ? trimmed : undefined\n}\n\nexport function resolveDevMode(devMode?: DevModeConfig): DevModeResolution {\n\tif (!devMode) {\n\t\treturn { devMode: undefined, isEmpty: false }\n\t}\n\n\tconst normalized = {\n\t\tanthropicApiKey: normalizeApiKey(devMode.anthropicApiKey),\n\t\topenaiApiKey: normalizeApiKey(devMode.openaiApiKey),\n\t\tuseLocalApi: devMode.useLocalApi === true ? true : undefined,\n\t} satisfies DevModeConfig\n\n\tconst hasAnyValue =\n\t\t!!normalized.anthropicApiKey || !!normalized.openaiApiKey || !!normalized.useLocalApi\n\n\treturn {\n\t\tdevMode: hasAnyValue ? normalized : undefined,\n\t\tisEmpty: !hasAnyValue,\n\t}\n}\n","'use client'\n\nimport { createContext, useContext, type ReactNode } from 'react'\n\nconst PortalContainerContext = createContext<HTMLElement | null>(null)\n\n// Track if we've already warned about missing context (warn once per session)\nlet hasWarnedAboutMissingContext = false\n\n/**\n * Hook to get the Shadow DOM container for Radix portals.\n * When inside a Shadow DOM, this returns the container element\n * so portals render inside the shadow root instead of document.body.\n */\nexport function usePortalContainer() {\n const context = useContext(PortalContainerContext)\n\n if (!context && typeof window !== 'undefined') {\n // In development, throw an error to catch configuration issues early\n if (process.env.NODE_ENV === 'development' && !hasWarnedAboutMissingContext) {\n hasWarnedAboutMissingContext = true\n console.error(\n '[Char] PortalContainerProvider not found. Radix components will render outside ' +\n 'the Shadow DOM, breaking CSS encapsulation. Wrap your component tree in PortalContainerProvider.'\n )\n }\n\n // In production, log once and continue with fallback\n if (process.env.NODE_ENV !== 'development' && !hasWarnedAboutMissingContext) {\n hasWarnedAboutMissingContext = true\n console.error(\n '[Char] PortalContainerProvider not found. CSS encapsulation may be broken.'\n )\n }\n }\n\n return context\n}\n\n/**\n * Provider that supplies the Shadow DOM container to all Radix components.\n * This ensures portals (Popover, Select, Dialog, etc.) render inside\n * the Shadow DOM where styles are applied.\n */\nexport function PortalContainerProvider({\n container,\n children\n}: {\n container: HTMLElement | null\n children: ReactNode\n}) {\n return (\n <PortalContainerContext.Provider value={container}>\n {children}\n </PortalContainerContext.Provider>\n )\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\n\nimport { cn } from \"@/utils/cn\";\nimport { usePortalContainer } from \"@/providers/PortalContainerProvider\";\n\nfunction TooltipProvider({\n delayDuration = 0,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n );\n}\n\nfunction Tooltip({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n );\n}\n\nfunction TooltipTrigger({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />;\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 0,\n children,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content>) {\n const container = usePortalContainer()\n\n return (\n <TooltipPrimitive.Portal container={container}>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n \"fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in text-balance rounded-md bg-foreground px-3 py-1.5 text-background text-xs data-[state=closed]:animate-out\",\n className,\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { usePortalContainer } from \"@/providers/PortalContainerProvider\";\n\nfunction Dialog({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nfunction DialogTrigger({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nfunction DialogPortal({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Portal>) {\n const container = usePortalContainer()\n\n return (\n <DialogPrimitive.Portal\n data-slot=\"dialog-portal\"\n container={container}\n {...props}\n />\n );\n}\n\nfunction DialogClose({\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Close>) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Content> & {\n showCloseButton?: boolean;\n}) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg outline-none duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg\",\n className,\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0\"\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"font-semibold text-lg leading-none\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\";\n\nimport { cn } from \"@/utils/cn\";\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n );\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"flex size-full items-center justify-center rounded-full bg-muted\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Avatar, AvatarImage, AvatarFallback };\n","\"use client\";\n\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithRef } from \"react\";\nimport { Slottable } from \"@radix-ui/react-slot\";\n\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/utils/cn\";\n\nexport type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {\n tooltip: string;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n};\n\nexport const TooltipIconButton = forwardRef<\n HTMLButtonElement,\n TooltipIconButtonProps\n>(({ children, tooltip, side = \"bottom\", className, ...rest }, ref) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n {...rest}\n className={cn(\"aui-button-icon size-6 p-1\", className)}\n ref={ref}\n >\n <Slottable>{children}</Slottable>\n <span className=\"aui-sr-only sr-only\">{tooltip}</span>\n </Button>\n </TooltipTrigger>\n <TooltipContent side={side}>{tooltip}</TooltipContent>\n </Tooltip>\n );\n});\n\nTooltipIconButton.displayName = \"TooltipIconButton\";\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { FC, PropsWithChildren } from \"react\";\nimport { XIcon, PlusIcon, FileText } from \"lucide-react\";\nimport {\n AttachmentPrimitive,\n ComposerPrimitive,\n MessagePrimitive,\n useAssistantState,\n useAssistantApi,\n} from \"@assistant-ui/react\";\nimport { useShallow } from \"zustand/shallow\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogTrigger,\n} from \"@/components/ui/dialog\";\nimport { Avatar, AvatarImage, AvatarFallback } from \"@/components/ui/avatar\";\nimport { TooltipIconButton } from \"@/components/assistant-ui/tooltip-icon-button\";\nimport { cn } from \"@/utils/cn\";\n\nconst useFileSrc = (file: File | undefined) => {\n const [src, setSrc] = useState<string | undefined>(undefined);\n\n useEffect(() => {\n if (!file) {\n setSrc(undefined);\n return;\n }\n\n const objectUrl = URL.createObjectURL(file);\n setSrc(objectUrl);\n\n return () => {\n URL.revokeObjectURL(objectUrl);\n };\n }, [file]);\n\n return src;\n};\n\nconst useAttachmentSrc = () => {\n const { file, src } = useAssistantState(\n useShallow(({ attachment }): { file?: File; src?: string } => {\n if (attachment.type !== \"image\") return {};\n if (attachment.file) return { file: attachment.file };\n const src = attachment.content?.filter((c) => c.type === \"image\")[0]\n ?.image;\n if (!src) return {};\n return { src };\n }),\n );\n\n return useFileSrc(file) ?? src;\n};\n\ntype AttachmentPreviewProps = {\n src: string;\n};\n\nconst AttachmentPreview: FC<AttachmentPreviewProps> = ({ src }) => {\n const [isLoaded, setIsLoaded] = useState(false);\n return (\n <img\n src={src}\n alt=\"Image Preview\"\n className={\n isLoaded\n ? \"aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain\"\n : \"aui-attachment-preview-image-loading hidden\"\n }\n onLoad={() => setIsLoaded(true)}\n />\n );\n};\n\nconst AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {\n const src = useAttachmentSrc();\n\n if (!src) return children;\n\n return (\n <Dialog>\n <DialogTrigger\n className=\"aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50\"\n asChild\n >\n {children}\n </DialogTrigger>\n <DialogContent className=\"aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive\">\n <DialogTitle className=\"aui-sr-only sr-only\">\n Image Attachment Preview\n </DialogTitle>\n <div className=\"aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background\">\n <AttachmentPreview src={src} />\n </div>\n </DialogContent>\n </Dialog>\n );\n};\n\nconst AttachmentThumb: FC = () => {\n const isImage = useAssistantState(\n ({ attachment }) => attachment.type === \"image\",\n );\n const src = useAttachmentSrc();\n\n return (\n <Avatar className=\"aui-attachment-tile-avatar h-full w-full rounded-none\">\n <AvatarImage\n src={src}\n alt=\"Attachment preview\"\n className=\"aui-attachment-tile-image object-cover\"\n />\n <AvatarFallback delayMs={isImage ? 200 : 0}>\n <FileText className=\"aui-attachment-tile-fallback-icon size-8 text-muted-foreground\" />\n </AvatarFallback>\n </Avatar>\n );\n};\n\nconst AttachmentUI: FC = () => {\n const api = useAssistantApi();\n const isComposer = api.attachment.source === \"composer\";\n\n const isImage = useAssistantState(\n ({ attachment }) => attachment.type === \"image\",\n );\n const typeLabel = useAssistantState(({ attachment }) => {\n const type = attachment.type;\n switch (type) {\n case \"image\":\n return \"Image\";\n case \"document\":\n return \"Document\";\n case \"file\":\n return \"File\";\n default:\n const _exhaustiveCheck: never = type;\n throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);\n }\n });\n\n return (\n <Tooltip>\n <AttachmentPrimitive.Root\n className={cn(\n \"aui-attachment-root relative\",\n isImage &&\n \"aui-attachment-root-composer only:[&>#attachment-tile]:size-24\",\n )}\n >\n <AttachmentPreviewDialog>\n <TooltipTrigger asChild>\n <div\n className={cn(\n \"aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75\",\n isComposer &&\n \"aui-attachment-tile-composer border-foreground/20\",\n )}\n role=\"button\"\n id=\"attachment-tile\"\n aria-label={`${typeLabel} attachment`}\n >\n <AttachmentThumb />\n </div>\n </TooltipTrigger>\n </AttachmentPreviewDialog>\n {isComposer && <AttachmentRemove />}\n </AttachmentPrimitive.Root>\n <TooltipContent side=\"top\">\n <AttachmentPrimitive.Name />\n </TooltipContent>\n </Tooltip>\n );\n};\n\nconst AttachmentRemove: FC = () => {\n return (\n <AttachmentPrimitive.Remove asChild>\n <TooltipIconButton\n tooltip=\"Remove file\"\n className=\"aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white text-muted-foreground opacity-100 shadow-sm hover:bg-white! [&_svg]:text-black hover:[&_svg]:text-destructive\"\n side=\"top\"\n >\n <XIcon className=\"aui-attachment-remove-icon size-3 dark:stroke-[2.5px]\" />\n </TooltipIconButton>\n </AttachmentPrimitive.Remove>\n );\n};\n\nexport const UserMessageAttachments: FC = () => {\n return (\n <div className=\"aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2\">\n <MessagePrimitive.Attachments components={{ Attachment: AttachmentUI }} />\n </div>\n );\n};\n\nexport const ComposerAttachments: FC = () => {\n return (\n <div className=\"aui-composer-attachments mb-2 flex w-full flex-row items-center gap-2 overflow-x-auto px-1.5 pt-0.5 pb-1 empty:hidden\">\n <ComposerPrimitive.Attachments\n components={{ Attachment: AttachmentUI }}\n />\n </div>\n );\n};\n\nexport const ComposerAddAttachment: FC = () => {\n return (\n <ComposerPrimitive.AddAttachment asChild>\n <TooltipIconButton\n tooltip=\"Add Attachment\"\n side=\"bottom\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"aui-composer-add-attachment size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30\"\n aria-label=\"Add Attachment\"\n >\n <PlusIcon className=\"aui-attachment-add-icon size-5 stroke-[1.5px]\" />\n </TooltipIconButton>\n </ComposerPrimitive.AddAttachment>\n );\n};\n","\"use client\";\n\nimport \"@assistant-ui/react-markdown/styles/dot.css\";\n\nimport {\n type CodeHeaderProps,\n MarkdownTextPrimitive,\n unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,\n useIsMarkdownCodeBlock,\n} from \"@assistant-ui/react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport { type FC, memo, useState } from \"react\";\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\n\nimport { TooltipIconButton } from \"@/components/assistant-ui/tooltip-icon-button\";\nimport { cn } from \"@/utils/cn\";\n\nconst MarkdownTextImpl = () => {\n return (\n <MarkdownTextPrimitive\n remarkPlugins={[remarkGfm]}\n className=\"aui-md\"\n components={defaultComponents}\n />\n );\n};\n\nexport const MarkdownText = memo(MarkdownTextImpl);\n\nconst CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {\n const { isCopied, copyToClipboard } = useCopyToClipboard();\n const onCopy = () => {\n if (!code || isCopied) return;\n copyToClipboard(code);\n };\n\n return (\n <div className=\"aui-code-header-root mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-code-header-bg px-4 py-2 font-semibold text-foreground text-sm\">\n <span className=\"aui-code-header-language lowercase [&>span]:text-xs\">\n {language}\n </span>\n <TooltipIconButton tooltip=\"Copy\" onClick={onCopy}>\n {!isCopied && <CopyIcon className=\"size-4\" />}\n {isCopied && <CheckIcon className=\"size-4\" />}\n </TooltipIconButton>\n </div>\n );\n};\n\nconst useCopyToClipboard = ({\n copiedDuration = 3000,\n}: {\n copiedDuration?: number;\n} = {}) => {\n const [isCopied, setIsCopied] = useState<boolean>(false);\n\n const copyToClipboard = (value: string) => {\n if (!value) return;\n\n navigator.clipboard.writeText(value).then(() => {\n setIsCopied(true);\n setTimeout(() => setIsCopied(false), copiedDuration);\n });\n };\n\n return { isCopied, copyToClipboard };\n};\n\nconst defaultComponents = memoizeMarkdownComponents({\n h1: ({ className, ...props }) => (\n <h1\n className={cn(\n \"aui-md-h1 mb-6 scroll-m-20 font-extrabold text-2xl tracking-tight last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n h2: ({ className, ...props }) => (\n <h2\n className={cn(\n \"aui-md-h2 mt-6 mb-3 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n h3: ({ className, ...props }) => (\n <h3\n className={cn(\n \"aui-md-h3 mt-5 mb-3 scroll-m-20 font-semibold text-lg tracking-tight first:mt-0 last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n h4: ({ className, ...props }) => (\n <h4\n className={cn(\n \"aui-md-h4 mt-4 mb-2 scroll-m-20 font-semibold text-base tracking-tight first:mt-0 last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n h5: ({ className, ...props }) => (\n <h5\n className={cn(\n \"aui-md-h5 my-3 font-semibold text-sm first:mt-0 last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n h6: ({ className, ...props }) => (\n <h6\n className={cn(\n \"aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n p: ({ className, ...props }) => (\n <p\n className={cn(\n \"aui-md-p mt-5 mb-5 leading-7 first:mt-0 last:mb-0\",\n className,\n )}\n {...props}\n />\n ),\n a: ({ className, ...props }) => (\n <a\n className={cn(\n \"aui-md-a font-medium text-primary underline underline-offset-4\",\n className,\n )}\n {...props}\n />\n ),\n blockquote: ({ className, ...props }) => (\n <blockquote\n className={cn(\"aui-md-blockquote border-l-2 pl-6 italic\", className)}\n {...props}\n />\n ),\n ul: ({ className, ...props }) => (\n <ul\n className={cn(\"aui-md-ul my-5 ml-6 list-disc [&>li]:mt-2\", className)}\n {...props}\n />\n ),\n ol: ({ className, ...props }) => (\n <ol\n className={cn(\"aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2\", className)}\n {...props}\n />\n ),\n hr: ({ className, ...props }) => (\n <hr className={cn(\"aui-md-hr my-5 border-b\", className)} {...props} />\n ),\n table: ({ className, ...props }) => (\n <table\n className={cn(\n \"aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto\",\n className,\n )}\n {...props}\n />\n ),\n th: ({ className, ...props }) => (\n <th\n className={cn(\n \"aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [[align=center]]:text-center [[align=right]]:text-right\",\n className,\n )}\n {...props}\n />\n ),\n td: ({ className, ...props }) => (\n <td\n className={cn(\n \"aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right\",\n className,\n )}\n {...props}\n />\n ),\n tr: ({ className, ...props }) => (\n <tr\n className={cn(\n \"aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg\",\n className,\n )}\n {...props}\n />\n ),\n sup: ({ className, ...props }) => (\n <sup\n className={cn(\"aui-md-sup [&>a]:text-xs [&>a]:no-underline\", className)}\n {...props}\n />\n ),\n pre: ({ className, ...props }) => (\n <pre\n className={cn(\n \"aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-code-bg p-4 text-code-text\",\n className,\n )}\n {...props}\n />\n ),\n code: function Code({ className, ...props }) {\n const isCodeBlock = useIsMarkdownCodeBlock();\n return (\n <code\n className={cn(\n !isCodeBlock &&\n \"aui-md-inline-code rounded border bg-muted font-semibold\",\n className,\n )}\n {...props}\n />\n );\n },\n CodeHeader,\n});\n","\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\nfunction Collapsible({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />;\n}\n\nfunction CollapsibleTrigger({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {\n return (\n <CollapsiblePrimitive.CollapsibleTrigger\n data-slot=\"collapsible-trigger\"\n {...props}\n />\n );\n}\n\nfunction CollapsibleContent({\n ...props\n}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {\n return (\n <CollapsiblePrimitive.CollapsibleContent\n data-slot=\"collapsible-content\"\n {...props}\n />\n );\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent };\n","\"use client\";\n\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport {\n memo,\n useCallback,\n useRef,\n useState,\n type FC,\n type PropsWithChildren,\n} from \"react\";\n\nimport {\n useScrollLock,\n useAssistantState,\n type ReasoningMessagePartComponent,\n type ReasoningGroupComponent,\n} from \"@assistant-ui/react\";\n\nimport { MarkdownText } from \"@/components/assistant-ui/markdown-text\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/utils/cn\";\n\nconst ANIMATION_DURATION = 200;\n\n/**\n * Root collapsible container that manages open/closed state and scroll lock.\n * Provides animation timing via CSS variable and prevents scroll jumps on collapse.\n */\nconst ReasoningRoot: FC<\n PropsWithChildren<{\n className?: string;\n }>\n> = ({ className, children }) => {\n const collapsibleRef = useRef<HTMLDivElement>(null);\n const [isOpen, setIsOpen] = useState(false);\n const lockScroll = useScrollLock(collapsibleRef, ANIMATION_DURATION);\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) {\n lockScroll();\n }\n setIsOpen(open);\n },\n [lockScroll],\n );\n\n return (\n <Collapsible\n ref={collapsibleRef}\n open={isOpen}\n onOpenChange={handleOpenChange}\n className={cn(\"aui-reasoning-root mb-4 w-full\", className)}\n style={\n {\n \"--animation-duration\": `${ANIMATION_DURATION}ms`,\n } as React.CSSProperties\n }\n >\n {children}\n </Collapsible>\n );\n};\n\nReasoningRoot.displayName = \"ReasoningRoot\";\n\n/**\n * Gradient overlay that softens the bottom edge during expand/collapse animations.\n * Animation: Fades out with delay when opening and fades back in when closing.\n */\nconst GradientFade: FC<{ className?: string }> = ({ className }) => (\n <div\n className={cn(\n \"aui-reasoning-fade pointer-events-none absolute inset-x-0 bottom-0 z-10 h-16\",\n \"bg-[linear-gradient(to_top,var(--color-background),transparent)]\",\n \"fade-in-0 animate-in\",\n \"group-data-[state=open]/collapsible-content:animate-out\",\n \"group-data-[state=open]/collapsible-content:fade-out-0\",\n \"group-data-[state=open]/collapsible-content:delay-[calc(var(--animation-duration)*0.75)]\", // calc for timing the delay\n \"group-data-[state=open]/collapsible-content:fill-mode-forwards\",\n \"duration-(--animation-duration)\",\n \"group-data-[state=open]/collapsible-content:duration-(--animation-duration)\",\n className,\n )}\n />\n);\n\n/**\n * Trigger button for the Reasoning collapsible.\n * Composed of icons, label, and text shimmer animation when reasoning is being streamed.\n */\nconst ReasoningTrigger: FC<{ active: boolean; className?: string }> = ({\n active,\n className,\n}) => (\n <CollapsibleTrigger\n className={cn(\n \"aui-reasoning-trigger group/trigger -mb-2 flex max-w-[75%] items-center gap-2 py-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className,\n )}\n >\n <BrainIcon className=\"aui-reasoning-trigger-icon size-4 shrink-0\" />\n <span className=\"aui-reasoning-trigger-label-wrapper relative inline-block leading-none\">\n <span>Reasoning</span>\n {active ? (\n <span\n aria-hidden\n className=\"aui-reasoning-trigger-shimmer shimmer pointer-events-none absolute inset-0 motion-reduce:animate-none\"\n >\n Reasoning\n </span>\n ) : null}\n </span>\n <ChevronDownIcon\n className={cn(\n \"aui-reasoning-trigger-chevron mt-0.5 size-4 shrink-0\",\n \"transition-transform duration-(--animation-duration) ease-out\",\n \"group-data-[state=closed]/trigger:-rotate-90\",\n \"group-data-[state=open]/trigger:rotate-0\",\n )}\n />\n </CollapsibleTrigger>\n);\n\n/**\n * Collapsible content wrapper that handles height expand/collapse animation.\n * Animation: Height animates up (collapse) and down (expand).\n * Also provides group context for child animations via data-state attributes.\n */\nconst ReasoningContent: FC<\n PropsWithChildren<{\n className?: string;\n \"aria-busy\"?: boolean;\n }>\n> = ({ className, children, \"aria-busy\": ariaBusy }) => (\n <CollapsibleContent\n className={cn(\n \"aui-reasoning-content relative overflow-hidden text-muted-foreground text-sm outline-none\",\n \"group/collapsible-content ease-out\",\n \"data-[state=closed]:animate-collapsible-up\",\n \"data-[state=open]:animate-collapsible-down\",\n \"data-[state=closed]:fill-mode-forwards\",\n \"data-[state=closed]:pointer-events-none\",\n \"data-[state=open]:duration-(--animation-duration)\",\n \"data-[state=closed]:duration-(--animation-duration)\",\n className,\n )}\n aria-busy={ariaBusy}\n >\n {children}\n <GradientFade />\n </CollapsibleContent>\n);\n\nReasoningContent.displayName = \"ReasoningContent\";\n\n/**\n * Text content wrapper that animates the reasoning text visibility.\n * Animation: Slides in from top + fades in when opening, reverses when closing.\n * Reacts to parent ReasoningContent's data-state via Radix group selectors.\n */\nconst ReasoningText: FC<\n PropsWithChildren<{\n className?: string;\n }>\n> = ({ className, children }) => (\n <div\n className={cn(\n \"aui-reasoning-text relative z-0 space-y-4 pt-4 pl-6 leading-relaxed\",\n \"transform-gpu transition-[transform,opacity]\",\n \"group-data-[state=open]/collapsible-content:animate-in\",\n \"group-data-[state=closed]/collapsible-content:animate-out\",\n \"group-data-[state=open]/collapsible-content:fade-in-0\",\n \"group-data-[state=closed]/collapsible-content:fade-out-0\",\n \"group-data-[state=open]/collapsible-content:slide-in-from-top-4\",\n \"group-data-[state=closed]/collapsible-content:slide-out-to-top-4\",\n \"group-data-[state=open]/collapsible-content:duration-(--animation-duration)\",\n \"group-data-[state=closed]/collapsible-content:duration-(--animation-duration)\",\n \"[&_p]:-mb-2\",\n className,\n )}\n >\n {children}\n </div>\n);\n\nReasoningText.displayName = \"ReasoningText\";\n\n/**\n * Renders a single reasoning part's text with markdown support.\n * Consecutive reasoning parts are automatically grouped by ReasoningGroup.\n *\n * Pass Reasoning to MessagePrimitive.Parts in thread.tsx\n *\n * @example:\n * ```tsx\n * <MessagePrimitive.Parts\n * components={{\n * Reasoning: Reasoning,\n * ReasoningGroup: ReasoningGroup,\n * }}\n * />\n * ```\n */\nconst ReasoningImpl: ReasoningMessagePartComponent = () => <MarkdownText />;\n\n/**\n * Collapsible wrapper that groups consecutive reasoning parts together.\n * Includes scroll lock to prevent page jumps during collapse animation.\n *\n * Pass ReasoningGroup to MessagePrimitive.Parts in thread.tsx\n *\n * @example:\n * ```tsx\n * <MessagePrimitive.Parts\n * components={{\n * Reasoning: Reasoning,\n * ReasoningGroup: ReasoningGroup,\n * }}\n * />\n * ```\n */\nconst ReasoningGroupImpl: ReasoningGroupComponent = ({\n children,\n startIndex,\n endIndex,\n}) => {\n /**\n * Detects if reasoning is currently streaming within this group's range.\n */\n const isReasoningStreaming = useAssistantState(({ message }) => {\n if (message.status?.type !== \"running\") return false;\n const lastIndex = message.parts.length - 1;\n if (lastIndex < 0) return false;\n const lastType = message.parts[lastIndex]?.type;\n if (lastType !== \"reasoning\") return false;\n return lastIndex >= startIndex && lastIndex <= endIndex;\n });\n\n return (\n <ReasoningRoot>\n <ReasoningTrigger active={isReasoningStreaming} />\n\n <ReasoningContent aria-busy={isReasoningStreaming}>\n <ReasoningText>{children}</ReasoningText>\n </ReasoningContent>\n </ReasoningRoot>\n );\n};\n\nexport const Reasoning = memo(ReasoningImpl);\nReasoning.displayName = \"Reasoning\";\n\nexport const ReasoningGroup = memo(ReasoningGroupImpl);\nReasoningGroup.displayName = \"ReasoningGroup\";\n","import { cn } from '@/utils/cn'\nimport { useEffect, useMemo, useRef, type HTMLAttributes } from 'react'\n\ntype WaveformMode = 'scrolling' | 'static'\n\nconst BAR_WIDTH = 3\nconst BAR_HEIGHT = 4\nconst BAR_GAP = 2\nconst BAR_RADIUS = 1.5\nconst FADE_WIDTH = 24\nconst SENSITIVITY = 1\nconst HISTORY_SIZE = 60\nconst UPDATE_RATE = 30\n\nexport interface LiveWaveformProps extends HTMLAttributes<HTMLDivElement> {\n\tactive?: boolean\n\tprocessing?: boolean\n\tlevel?: number\n\theight?: string | number\n\tmode?: WaveformMode\n}\n\nfunction clampLevel(value: number): number {\n\tif (Number.isNaN(value)) return 0\n\treturn Math.max(0, Math.min(1, value))\n}\n\nexport function LiveWaveform({\n\tactive = false,\n\tprocessing = false,\n\tlevel = 0,\n\theight = 56,\n\tmode = 'static',\n\tclassName,\n\t...props\n}: LiveWaveformProps) {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null)\n\tconst frameRef = useRef<number | null>(null)\n\tconst lastTickRef = useRef(0)\n\tconst smoothLevelRef = useRef(0)\n\tconst historyRef = useRef<number[]>([])\n\tconst paramsRef = useRef({ active, processing, level, mode })\n\n\t// Keep a stable animation loop and read latest render params from refs.\n\tparamsRef.current = { active, processing, level, mode }\n\n\tconst inlineStyle = useMemo(\n\t\t() => ({ height: typeof height === 'number' ? `${height}px` : height }),\n\t\t[height]\n\t)\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current\n\t\tif (!canvas) return\n\t\tconst ctx = canvas.getContext('2d')\n\t\tif (!ctx) return\n\n\t\tconst container = canvas.parentElement\n\t\tif (!container) return\n\n\t\tlastTickRef.current = 0\n\n\t\tlet cachedColor = getComputedStyle(container).color\n\n\t\tconst resize = () => {\n\t\t\tconst dpr = window.devicePixelRatio || 1\n\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\tcanvas.width = Math.max(1, Math.floor(rect.width * dpr))\n\t\t\tcanvas.height = Math.max(1, Math.floor(rect.height * dpr))\n\t\t\tcanvas.style.width = `${rect.width}px`\n\t\t\tcanvas.style.height = `${rect.height}px`\n\t\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0)\n\t\t\tcachedColor = getComputedStyle(container).color\n\t\t}\n\n\t\tconst draw = (timestamp: number) => {\n\t\t\tconst {\n\t\t\t\tactive: currentActive,\n\t\t\t\tprocessing: currentProcessing,\n\t\t\t\tlevel: currentLevel,\n\t\t\t\tmode: currentMode,\n\t\t\t} = paramsRef.current\n\n\t\t\tif (timestamp - lastTickRef.current < UPDATE_RATE) {\n\t\t\t\tframeRef.current = window.requestAnimationFrame(draw)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlastTickRef.current = timestamp\n\n\t\t\tconst width = container.clientWidth\n\t\t\tconst rawHeight = container.clientHeight\n\t\t\tconst displayHeight = Math.max(1, rawHeight)\n\n\t\t\tctx.clearRect(0, 0, width, displayHeight)\n\n\t\t\tconst baseLevel = clampLevel(currentLevel * SENSITIVITY)\n\t\t\tconst targetLevel = currentActive ? baseLevel : 0\n\t\t\tconst smoothing = 0.2\n\t\t\tsmoothLevelRef.current += (targetLevel - smoothLevelRef.current) * smoothing\n\n\t\t\tlet animatedLevel = smoothLevelRef.current\n\t\t\tif (!currentActive && currentProcessing) {\n\t\t\t\tanimatedLevel = 0.3 + 0.15 * Math.sin(timestamp / 180)\n\t\t\t}\n\n\t\t\tctx.fillStyle = cachedColor\n\n\t\t\tconst barStep = BAR_WIDTH + BAR_GAP\n\t\t\tconst barCount = Math.max(1, Math.floor(width / barStep))\n\t\t\tconst centerY = displayHeight / 2\n\n\t\t\tif (currentMode === 'scrolling') {\n\t\t\t\tconst next = currentActive || currentProcessing ? animatedLevel : 0.08\n\t\t\t\tconst history = historyRef.current\n\t\t\t\thistory.push(next)\n\t\t\t\tif (history.length > HISTORY_SIZE) history.shift()\n\n\t\t\t\tconst paddedHistory =\n\t\t\t\t\thistory.length < barCount\n\t\t\t\t\t\t? [...new Array(barCount - history.length).fill(0), ...history]\n\t\t\t\t\t\t: history.slice(-barCount)\n\n\t\t\t\tfor (let i = 0; i < barCount; i++) {\n\t\t\t\t\tconst value = paddedHistory[i] ?? 0\n\t\t\t\t\tconst h = Math.max(BAR_HEIGHT, value * (displayHeight - 4))\n\t\t\t\t\tconst x = i * barStep\n\t\t\t\t\tctx.beginPath()\n\t\t\t\t\tctx.roundRect(x, centerY - h / 2, BAR_WIDTH, h, BAR_RADIUS)\n\t\t\t\t\tctx.fill()\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst oscillation = 0.12 * Math.sin(timestamp / 160)\n\t\t\t\tfor (let i = 0; i < barCount; i++) {\n\t\t\t\t\tconst distance = Math.abs(i - barCount / 2) / (barCount / 2)\n\t\t\t\t\tconst shape = 1 - Math.min(1, distance)\n\t\t\t\t\tconst reactive = currentActive || currentProcessing ? animatedLevel + oscillation : 0.08\n\t\t\t\t\tconst h = Math.max(BAR_HEIGHT, reactive * shape * (displayHeight - 4))\n\t\t\t\t\tconst x = i * barStep\n\t\t\t\t\tctx.beginPath()\n\t\t\t\t\tctx.roundRect(x, centerY - h / 2, BAR_WIDTH, h, BAR_RADIUS)\n\t\t\t\t\tctx.fill()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fade edges for smooth visual blending\n\t\t\tconst gradient = ctx.createLinearGradient(0, 0, width, 0)\n\t\t\tgradient.addColorStop(0, 'rgba(255,255,255,1)')\n\t\t\tgradient.addColorStop(Math.min(0.5, FADE_WIDTH / Math.max(1, width)), 'rgba(255,255,255,0)')\n\t\t\tgradient.addColorStop(\n\t\t\t\tMath.max(0.5, 1 - FADE_WIDTH / Math.max(1, width)),\n\t\t\t\t'rgba(255,255,255,0)'\n\t\t\t)\n\t\t\tgradient.addColorStop(1, 'rgba(255,255,255,1)')\n\t\t\tctx.save()\n\t\t\tctx.globalCompositeOperation = 'destination-out'\n\t\t\tctx.fillStyle = gradient\n\t\t\tctx.fillRect(0, 0, width, displayHeight)\n\t\t\tctx.restore()\n\n\t\t\tframeRef.current = window.requestAnimationFrame(draw)\n\t\t}\n\n\t\tresize()\n\t\tconst observer = new ResizeObserver(resize)\n\t\tobserver.observe(container)\n\t\tframeRef.current = window.requestAnimationFrame(draw)\n\n\t\treturn () => {\n\t\t\tif (frameRef.current) {\n\t\t\t\twindow.cancelAnimationFrame(frameRef.current)\n\t\t\t}\n\t\t\tobserver.disconnect()\n\t\t}\n\t}, [])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('relative w-full overflow-hidden rounded-md', className)}\n\t\t\tstyle={inlineStyle}\n\t\t\t{...props}\n\t\t>\n\t\t\t<canvas ref={canvasRef} className=\"h-full w-full\" />\n\t\t</div>\n\t)\n}\n\nexport default LiveWaveform\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { usePortalContainer } from \"@/providers/PortalContainerProvider\";\n\nfunction Select({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nfunction SelectValue({\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({\n className,\n size = \"default\",\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"default\";\n}) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n data-size={size}\n className={cn(\n \"flex w-fit items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[size=default]:h-9 data-[size=sm]:h-8 data-[placeholder]:text-muted-foreground *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:hover:bg-input/50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"size-4 opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"item-aligned\",\n align = \"center\",\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n const container = usePortalContainer()\n\n return (\n <SelectPrimitive.Portal container={container}>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n className={cn(\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=open]:animate-in\",\n position === \"popper\" &&\n \"data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1\",\n className,\n )}\n position={position}\n align={align}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"p-1\",\n position === \"popper\" &&\n \"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1\",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n data-slot=\"select-label\"\n className={cn(\"px-2 py-1.5 text-muted-foreground text-xs\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n \"relative flex w-full cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n className,\n )}\n {...props}\n >\n <span\n data-slot=\"select-item-indicator\"\n className=\"absolute right-2 flex size-3.5 items-center justify-center\"\n >\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n data-slot=\"select-separator\"\n className={cn(\"pointer-events-none -mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n data-slot=\"select-scroll-up-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className,\n )}\n {...props}\n >\n <ChevronUpIcon className=\"size-4\" />\n </SelectPrimitive.ScrollUpButton>\n );\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n data-slot=\"select-scroll-down-button\"\n className={cn(\n \"flex cursor-default items-center justify-center py-1\",\n className,\n )}\n {...props}\n >\n <ChevronDownIcon className=\"size-4\" />\n </SelectPrimitive.ScrollDownButton>\n );\n}\n\nexport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","import { Button } from '@/components/ui/button'\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from '@/components/ui/select'\nimport { cn } from '@/utils/cn'\nimport { Mic, MicOff, RefreshCw } from 'lucide-react'\nimport { useCallback, useEffect, useMemo, useState, type FC } from 'react'\n\nexport interface AudioDevice {\n\tdeviceId: string\n\tlabel: string\n\tgroupId: string\n}\n\nexport interface UseAudioDevicesReturn {\n\tdevices: AudioDevice[]\n\tloading: boolean\n\terror: string | null\n\thasPermission: boolean\n\tloadDevices: () => Promise<void>\n}\n\nfunction cleanDeviceLabel(label: string, index: number): string {\n\tconst trimmed = label.replace(/\\s*\\(.*?\\)\\s*/g, '').trim()\n\treturn trimmed || `Microphone ${index + 1}`\n}\n\nexport function useAudioDevices(): UseAudioDevicesReturn {\n\tconst [devices, setDevices] = useState<AudioDevice[]>([])\n\tconst [loading, setLoading] = useState(false)\n\tconst [error, setError] = useState<string | null>(null)\n\tconst [hasPermission, setHasPermission] = useState(false)\n\n\tconst loadDevices = useCallback(async () => {\n\t\tif (typeof navigator === 'undefined' || !navigator.mediaDevices) {\n\t\t\tsetError('Audio device APIs are not available in this browser')\n\t\t\treturn\n\t\t}\n\n\t\tsetLoading(true)\n\t\tsetError(null)\n\t\ttry {\n\t\t\tconst stream = await navigator.mediaDevices.getUserMedia({ audio: true })\n\t\t\tstream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t\tsetHasPermission(true)\n\n\t\t\tconst all = await navigator.mediaDevices.enumerateDevices()\n\t\t\tconst mics = all\n\t\t\t\t.filter((device) => device.kind === 'audioinput')\n\t\t\t\t.map((device, index) => ({\n\t\t\t\t\tdeviceId: device.deviceId,\n\t\t\t\t\tlabel: cleanDeviceLabel(device.label, index),\n\t\t\t\t\tgroupId: device.groupId,\n\t\t\t\t}))\n\t\t\tsetDevices(mics)\n\t\t} catch (err) {\n\t\t\tsetError(err instanceof Error ? err.message : 'Failed to load microphones')\n\t\t} finally {\n\t\t\tsetLoading(false)\n\t\t}\n\t}, [])\n\n\tuseEffect(() => {\n\t\tloadDevices().catch(console.error)\n\t}, [loadDevices])\n\n\tuseEffect(() => {\n\t\tif (typeof navigator === 'undefined' || !navigator.mediaDevices) return\n\t\tconst handleDeviceChange = () => {\n\t\t\tloadDevices().catch(console.error)\n\t\t}\n\t\tnavigator.mediaDevices.addEventListener('devicechange', handleDeviceChange)\n\t\treturn () => navigator.mediaDevices.removeEventListener('devicechange', handleDeviceChange)\n\t}, [loadDevices])\n\n\treturn {\n\t\tdevices,\n\t\tloading,\n\t\terror,\n\t\thasPermission,\n\t\tloadDevices,\n\t}\n}\n\ninterface MicSelectorProps {\n\tvalue?: string\n\tonValueChange: (deviceId: string) => void\n\tmuted: boolean\n\tonMutedChange: (muted: boolean) => void\n\tdisabled?: boolean\n\tclassName?: string\n}\n\nexport const MicSelector: FC<MicSelectorProps> = ({\n\tvalue,\n\tonValueChange,\n\tmuted,\n\tonMutedChange,\n\tdisabled = false,\n\tclassName,\n}) => {\n\tconst { devices, loading, error, hasPermission, loadDevices } = useAudioDevices()\n\n\tuseEffect(() => {\n\t\tif (value) return\n\t\tif (devices.length === 0) return\n\t\tonValueChange(devices[0].deviceId)\n\t}, [devices, value, onValueChange])\n\n\tconst selectedLabel = useMemo(\n\t\t() => devices.find((d) => d.deviceId === value)?.label,\n\t\t[devices, value]\n\t)\n\n\treturn (\n\t\t<div className={cn('flex w-full items-center gap-2', className)}>\n\t\t\t<Select\n\t\t\t\tvalue={value ?? ''}\n\t\t\t\tonValueChange={onValueChange}\n\t\t\t\tdisabled={disabled || loading || devices.length === 0}\n\t\t\t>\n\t\t\t\t<SelectTrigger className=\"h-8 min-w-0 flex-1 text-xs\">\n\t\t\t\t\t<SelectValue placeholder={loading ? 'Loading microphones...' : 'Select microphone'}>\n\t\t\t\t\t\t{selectedLabel}\n\t\t\t\t\t</SelectValue>\n\t\t\t\t</SelectTrigger>\n\t\t\t\t<SelectContent align=\"start\">\n\t\t\t\t\t{devices.map((device) => (\n\t\t\t\t\t\t<SelectItem key={device.deviceId} value={device.deviceId}>\n\t\t\t\t\t\t\t{device.label}\n\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t))}\n\t\t\t\t</SelectContent>\n\t\t\t</Select>\n\n\t\t\t<Button\n\t\t\t\ttype=\"button\"\n\t\t\t\tsize=\"icon\"\n\t\t\t\tvariant=\"ghost\"\n\t\t\t\tclassName=\"h-8 w-8 shrink-0\"\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonClick={() => onMutedChange(!muted)}\n\t\t\t\taria-label={muted ? 'Unmute microphone preview' : 'Mute microphone preview'}\n\t\t\t>\n\t\t\t\t{muted ? <MicOff className=\"h-4 w-4\" /> : <Mic className=\"h-4 w-4\" />}\n\t\t\t</Button>\n\n\t\t\t<Button\n\t\t\t\ttype=\"button\"\n\t\t\t\tsize=\"icon\"\n\t\t\t\tvariant=\"ghost\"\n\t\t\t\tclassName=\"h-8 w-8 shrink-0\"\n\t\t\t\tdisabled={disabled || loading}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tloadDevices().catch(() => undefined)\n\t\t\t\t}}\n\t\t\t\taria-label=\"Refresh microphones\"\n\t\t\t>\n\t\t\t\t<RefreshCw className={cn('h-4 w-4', loading && 'animate-spin')} />\n\t\t\t</Button>\n\n\t\t\t{error ? (\n\t\t\t\t<p className=\"text-xs text-destructive\" role=\"alert\">{error}</p>\n\t\t\t) : hasPermission ? (\n\t\t\t\t<span className=\"sr-only\">Microphone permission granted</span>\n\t\t\t) : null}\n\t\t</div>\n\t)\n}\n\nexport default MicSelector\n","/**\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://app.usechar.ai'\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","/**\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/shared-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 '../utils/constants'\nimport { createMCPTransport } from '../utils/mcp-transport'\n\nimport type {\n\tCallToolResult,\n\tGetPromptResult,\n\tPrompt,\n\tResource,\n\tResourceTemplate,\n\tTool,\n} from '@modelcontextprotocol/sdk/types.js'\nimport type {\n\tMCPSource,\n\tMCPSourceConfig,\n\tToolWithSource,\n} from '@mcp-b/shared-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, 'tools' | 'resources' | 'resourceTemplates' | 'prompts'> {\n\tclient: Client | null\n\ttransport: Transport | null\n\ttools: Tool[]\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\t/**\n\t * Refresh tools from all connected sources.\n\t * Call this after dynamically registering tools via useWebMCP inside the provider tree.\n\t */\n\trefreshTools: () => Promise<void>\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.message\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\t\tconst callTool = useCallback(\n\t\t\tasync (name: string, args: Record<string, unknown>): Promise<CallToolResult> => {\n\t\t\t\tconst tool = toolsList.find((t) => t.name === name)\n\t\t\t\tif (!tool) {\n\t\t\t\t\tthrow new Error(`Tool '${name}' not found`)\n\t\t\t\t}\n\n\t\t\t\treturn callToolOnSource(tool._sourceId, tool.name, args)\n\t\t\t},\n\t\t\t[toolsList, callToolOnSource]\n\t\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 * Refresh tools from all connected sources.\n\t * Call this after dynamically registering tools via useWebMCP inside the provider tree.\n\t * This is needed because tools registered after the initial connection may not\n\t * trigger a ToolListChangedNotification that the client receives.\n\t */\n\tconst refreshTools = useCallback(async () => {\n\t\tconsole.debug('[MCPToolsProvider] Refreshing tools from all sources')\n\t\tfor (const source of sourcesRef.current.values()) {\n\t\t\tif (source.client && source.state === 'connected') {\n\t\t\t\ttry {\n\t\t\t\t\tconst { tools } = await source.client.listTools()\n\t\t\t\t\tsource.tools = tools\n\t\t\t\t\tconsole.debug(`[MCPToolsProvider:${source.id}] Refreshed ${tools.length} tools`)\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`[MCPToolsProvider:${source.id}] Failed to refresh tools:`, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trebuildTools()\n\t}, [rebuildTools])\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\trefreshTools,\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\trefreshTools,\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 * usePrompts Hook\n *\n * Easy access to MCP prompts from any component.\n * Provides prompts list and getPrompt function from MCPToolsProvider context.\n */\nimport { useCallback } from 'react'\n\nimport { useMCPTools } from '../providers/MCPToolsProvider'\n\nimport type { GetPromptResult, Prompt } from '@modelcontextprotocol/sdk/types.js'\n\nexport interface UsePromptsResult {\n\t/** Available prompts from all MCP sources */\n\tprompts: Prompt[]\n\t/** Whether prompts are available (MCPToolsProvider is present and has prompts) */\n\thasPrompts: boolean\n\t/** Get expanded prompt content by name */\n\tgetPrompt: (name: string, args?: Record<string, string>) => Promise<GetPromptResult>\n}\n\n/**\n * Hook to access MCP prompts.\n *\n * @example Basic usage\n * ```tsx\n * function MyComponent() {\n * const { prompts, hasPrompts, getPrompt } = usePrompts()\n *\n * const handleClick = async (prompt: Prompt) => {\n * const result = await getPrompt(prompt.name)\n * console.log(result.messages)\n * }\n *\n * if (!hasPrompts) return null\n *\n * return (\n * <div>\n * {prompts.map(p => (\n * <button key={p.name} onClick={() => handleClick(p)}>\n * {p.name}\n * </button>\n * ))}\n * </div>\n * )\n * }\n * ```\n */\nexport function usePrompts(): UsePromptsResult {\n\tconst { prompts, getPrompt: mcpGetPrompt } = useMCPTools()\n\n\tconst hasPrompts = prompts.length > 0\n\n\tconst getPrompt = useCallback(\n\t\tasync (name: string, args?: Record<string, string>): Promise<GetPromptResult> => {\n\t\t\treturn mcpGetPrompt(name, args)\n\t\t},\n\t\t[mcpGetPrompt]\n\t)\n\n\treturn {\n\t\tprompts,\n\t\thasPrompts,\n\t\tgetPrompt,\n\t}\n}\n","import { cn } from \"@/utils/cn\";\n\nfunction Skeleton({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"animate-pulse rounded-md bg-accent\", className)}\n {...props}\n />\n );\n}\n\nexport { Skeleton };\n","/**\n * ChatErrorBoundary Component\n *\n * Error boundary specifically for assistant-ui/react runtime errors.\n * Uses react-error-boundary as recommended by assistant-ui docs.\n *\n * This boundary catches transient errors like:\n * - \"Duplicate key toolCallId-X in tapResources\"\n * - State corruption in the chat runtime\n * - ResourceFiber errors\n *\n * It provides a less alarming UI than AuthErrorBoundary and offers\n * recovery actions (retry, start new thread) appropriate for chat errors.\n *\n * @see https://github.com/assistant-ui/assistant-ui/blob/main/apps/docs/content/docs/runtimes/data-stream.mdx#error-boundaries\n */\n\nimport { ErrorBoundary, type FallbackProps } from 'react-error-boundary'\nimport { useState, type ErrorInfo, type ReactNode } from 'react'\n\nimport { Button } from '@/components/ui/button'\nimport { cn } from '@/utils/cn'\nimport { AlertCircle, RefreshCw, MessageSquarePlus } from 'lucide-react'\n\n/**\n * Props for the ChatErrorFallback component.\n */\nexport interface ChatErrorFallbackProps extends FallbackProps {\n\t/** Callback to start a new thread (optional, can be async) */\n\tonStartNewThread?: () => void | Promise<void>\n}\n\n/**\n * Extracts an error message from an unknown error value.\n */\nfunction getErrorMessage(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message\n\t}\n\tif (typeof error === 'string') {\n\t\treturn error\n\t}\n\tif (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {\n\t\treturn error.message\n\t}\n\treturn 'An unexpected error occurred'\n}\n\n/**\n * Fallback UI displayed when assistant-ui throws an error.\n * Designed to be inline within the chat area (not fullscreen).\n */\nexport function ChatErrorFallback({\n\terror,\n\tresetErrorBoundary,\n\tonStartNewThread,\n}: ChatErrorFallbackProps) {\n\tconst [isCreatingThread, setIsCreatingThread] = useState(false)\n\n\t// Extract a user-friendly message\n\tconst errorMessage = getErrorMessage(error)\n\n\t// Check if this is a known assistant-ui error\n\tconst isKnownChatError =\n\t\terrorMessage.includes('tapResources') ||\n\t\terrorMessage.includes('Duplicate key') ||\n\t\terrorMessage.includes('toolCallId') ||\n\t\terrorMessage.includes('ResourceFiber')\n\n\t// Handle starting a new thread: create thread, then reset boundary to show it\n\tconst handleStartNewThread = async () => {\n\t\tif (!onStartNewThread || isCreatingThread) return\n\n\t\tsetIsCreatingThread(true)\n\t\ttry {\n\t\t\t// Create the new thread (this updates currentThreadId via state broadcast)\n\t\t\tawait onStartNewThread()\n\t\t\t// Reset the error boundary to remount children with the new thread\n\t\t\tresetErrorBoundary()\n\t\t} catch (err) {\n\t\t\tconsole.error('[ChatErrorFallback] Failed to create new thread:', err)\n\t\t\tsetIsCreatingThread(false)\n\t\t}\n\t}\n\n\treturn (\n\t\t<div\n\t\t\trole=\"alert\"\n\t\t\tclassName={cn(\n\t\t\t\t'flex flex-col items-center justify-center h-full w-full p-6',\n\t\t\t\t'min-h-40'\n\t\t\t)}\n\t\t>\n\t\t\t<div className=\"w-full max-w-sm bg-background border border-border rounded-lg shadow-md overflow-hidden\">\n\t\t\t\t{/* Header */}\n\t\t\t\t<div className=\"px-4 py-3 border-b border-border bg-muted/30\">\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<AlertCircle className=\"h-4 w-4 text-muted-foreground\" />\n\t\t\t\t\t\t<h2 className=\"text-sm font-medium text-foreground\">\n\t\t\t\t\t\t\t{isKnownChatError ? 'Chat temporarily unavailable' : 'Something went wrong'}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Body */}\n\t\t\t\t<div className=\"px-4 py-3 space-y-3\">\n\t\t\t\t\t<p className=\"text-xs text-muted-foreground leading-relaxed\">\n\t\t\t\t\t\t{isKnownChatError\n\t\t\t\t\t\t\t? 'The chat encountered a temporary issue. This usually resolves by retrying or starting a new conversation.'\n\t\t\t\t\t\t\t: errorMessage}\n\t\t\t\t\t</p>\n\n\t\t\t\t\t{/* Technical details (collapsed by default) */}\n\t\t\t\t\t{!isKnownChatError && (\n\t\t\t\t\t\t<details className=\"text-xs\">\n\t\t\t\t\t\t\t<summary className=\"cursor-pointer text-muted-foreground/70 hover:text-muted-foreground\">\n\t\t\t\t\t\t\t\tTechnical details\n\t\t\t\t\t\t\t</summary>\n\t\t\t\t\t\t\t<pre className=\"mt-2 p-2 bg-muted/50 rounded text-xs font-mono overflow-x-auto whitespace-pre-wrap break-all\">\n\t\t\t\t\t\t\t\t{errorMessage}\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t</details>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Actions */}\n\t\t\t\t<div className=\"px-4 py-3 border-t border-border bg-muted/20 flex gap-2\">\n\t\t\t\t\t<Button\n\t\t\t\t\t\tvariant=\"default\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tonClick={resetErrorBoundary}\n\t\t\t\t\t\tclassName=\"flex-1\"\n\t\t\t\t\t\tdisabled={isCreatingThread}\n\t\t\t\t\t>\n\t\t\t\t\t\t<RefreshCw className=\"h-3 w-3 mr-1.5\" />\n\t\t\t\t\t\tTry again\n\t\t\t\t\t</Button>\n\n\t\t\t\t\t{onStartNewThread && (\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tonClick={handleStartNewThread}\n\t\t\t\t\t\t\tclassName=\"flex-1\"\n\t\t\t\t\t\t\tdisabled={isCreatingThread}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{isCreatingThread ? (\n\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t<RefreshCw className=\"h-3 w-3 mr-1.5 animate-spin\" />\n\t\t\t\t\t\t\t\t\tCreating...\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<>\n\t\t\t\t\t\t\t\t\t<MessageSquarePlus className=\"h-3 w-3 mr-1.5\" />\n\t\t\t\t\t\t\t\t\tNew conversation\n\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/**\n * Props for ChatErrorBoundary.\n */\nexport interface ChatErrorBoundaryProps {\n\t/** Child components to protect */\n\tchildren: ReactNode\n\t/** Callback when error boundary resets (used to clean up state) */\n\tonReset?: () => void\n\t/** Callback to start a new thread (can be async) */\n\tonStartNewThread?: () => void | Promise<void>\n\t/** Callback when an error is caught (for logging/analytics) */\n\tonError?: (error: Error, info: ErrorInfo) => void\n}\n\n/**\n * Error boundary for assistant-ui runtime errors.\n *\n * Wraps AssistantRuntimeProvider to catch errors like:\n * - \"Duplicate key toolCallId-X in tapResources\"\n * - State corruption in the chat runtime\n *\n * Provides appropriate recovery actions (retry, new thread) with a\n * non-alarming inline error UI.\n *\n * @example\n * ```tsx\n * <ChatErrorBoundary\n * onReset={handleReset}\n * onStartNewThread={handleStartNew}\n * onError={(error, info) => logError(error, info)}\n * >\n * <AssistantRuntimeProvider runtime={runtime}>\n * {children}\n * </AssistantRuntimeProvider>\n * </ChatErrorBoundary>\n * ```\n */\nexport function ChatErrorBoundary({\n\tchildren,\n\tonReset,\n\tonStartNewThread,\n\tonError,\n}: ChatErrorBoundaryProps) {\n\treturn (\n\t\t<ErrorBoundary\n\t\t\tFallbackComponent={({ error, resetErrorBoundary }) => (\n\t\t\t\t<ChatErrorFallback\n\t\t\t\t\terror={error}\n\t\t\t\t\tresetErrorBoundary={resetErrorBoundary}\n\t\t\t\t\tonStartNewThread={onStartNewThread}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\tonReset={onReset}\n\t\t\tonError={(error, info) => {\n\t\t\t\t// Log to console for debugging\n\t\t\t\tconsole.error('[ChatErrorBoundary] Caught error:', error)\n\t\t\t\tconsole.error('[ChatErrorBoundary] Component stack:', info.componentStack)\n\n\t\t\t\t// Call user-provided error handler (normalize error to Error instance)\n\t\t\t\tif (onError) {\n\t\t\t\t\tconst normalizedError = error instanceof Error ? error : new Error(getErrorMessage(error))\n\t\t\t\t\tonError(normalizedError, info)\n\t\t\t\t}\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</ErrorBoundary>\n\t)\n}\n","/**\n * Token Size Validator\n *\n * Validates JWT token size before parsing to prevent DoS attacks.\n *\n * Security:\n * - Rejects oversized tokens before JSON parsing\n * - Prevents resource exhaustion from maliciously large tokens\n * - Default limit: 16KB (sufficient for normal OIDC tokens)\n */\n/**\n * Default maximum token size in bytes (16KB).\n * Normal OIDC tokens are typically 1-4KB.\n */\nexport const DEFAULT_MAX_TOKEN_SIZE_BYTES = 16 * 1024; // 16KB\n/**\n * Validate token size before parsing.\n *\n * Call this BEFORE any other token operations to reject oversized tokens early.\n *\n * @param token - The JWT token string\n * @param maxSizeBytes - Maximum allowed size in bytes (default: 16KB)\n * @returns Validation result\n */\nexport function validateTokenSize(token, maxSizeBytes = DEFAULT_MAX_TOKEN_SIZE_BYTES) {\n // Check if token is a string\n if (typeof token !== 'string') {\n return {\n valid: false,\n errorCode: 'INVALID_TOKEN',\n errorMessage: 'Token must be a string'\n };\n }\n // Check token size\n // Note: We use string length as a proxy for byte length\n // For JWT tokens (ASCII), this is accurate\n // For non-ASCII characters, the actual byte length would be higher,\n // which makes this check even more conservative\n const sizeBytes = token.length;\n if (sizeBytes === 0) {\n return {\n valid: false,\n errorCode: 'TOKEN_REQUIRED',\n errorMessage: 'Token is empty'\n };\n }\n if (sizeBytes > maxSizeBytes) {\n const sizeMB = (sizeBytes / (1024 * 1024)).toFixed(2);\n const maxMB = (maxSizeBytes / 1024).toFixed(0);\n return {\n valid: false,\n errorCode: 'TOKEN_TOO_LARGE',\n errorMessage: `Token size (${sizeMB}MB) exceeds maximum allowed (${maxMB}KB). ` +\n 'Rejecting to prevent resource exhaustion.'\n };\n }\n return { valid: true, sizeBytes };\n}\n//# sourceMappingURL=token-size.js.map","/**\n * IDP Constants\n *\n * Constants for supported identity providers.\n *\n * @see ./IDP_PROVIDER_MATRIX.md for the complete provider reference including\n * field labels, placeholders, discovery URLs, and edge cases.\n */\n/**\n * Supported IDP types.\n */\nexport const IDP_TYPE = {\n OKTA: 'okta',\n AZURE: 'azure',\n AUTH0: 'auth0',\n GOOGLE: 'google',\n CUSTOM_OIDC: 'custom_oidc',\n WORKOS: 'workos',\n FIREBASE: 'firebase',\n ONELOGIN: 'onelogin',\n LOGTO: 'logto'\n};\n/**\n * All IDP type values as an array.\n * Useful for Zod enums and iteration.\n */\nexport const IDP_TYPES = Object.values(IDP_TYPE);\n/**\n * Display names for IDP types.\n * Uses `as const satisfies` to ensure all IDP types have display names.\n */\nexport const IDP_DISPLAY_NAMES = {\n [IDP_TYPE.OKTA]: 'Okta',\n [IDP_TYPE.AZURE]: 'Azure AD',\n [IDP_TYPE.AUTH0]: 'Auth0',\n [IDP_TYPE.GOOGLE]: 'Google Workspace',\n [IDP_TYPE.CUSTOM_OIDC]: 'Custom OIDC Provider',\n [IDP_TYPE.WORKOS]: 'WorkOS',\n [IDP_TYPE.FIREBASE]: 'Firebase Auth',\n [IDP_TYPE.ONELOGIN]: 'OneLogin',\n [IDP_TYPE.LOGTO]: 'Logto'\n};\n/**\n * IDP types that require domain configuration.\n */\nexport const IDP_TYPES_REQUIRING_DOMAIN = [\n IDP_TYPE.OKTA,\n IDP_TYPE.AZURE,\n IDP_TYPE.AUTH0,\n // WorkOS does NOT require domain - it uses runtime clientId to construct issuer URL\n IDP_TYPE.FIREBASE,\n IDP_TYPE.ONELOGIN,\n IDP_TYPE.LOGTO\n];\n/**\n * IDP types that require issuer configuration.\n */\nexport const IDP_TYPES_REQUIRING_ISSUER = [IDP_TYPE.CUSTOM_OIDC];\n/**\n * Check if an IDP type requires domain configuration.\n */\nexport function requiresDomain(idpType) {\n return IDP_TYPES_REQUIRING_DOMAIN.includes(idpType);\n}\n/**\n * Check if an IDP type requires issuer configuration.\n */\nexport function requiresIssuer(idpType) {\n return IDP_TYPES_REQUIRING_ISSUER.includes(idpType);\n}\n/**\n * Get the display name for an IDP type.\n */\nexport function getIdpDisplayName(idpType) {\n return IDP_DISPLAY_NAMES[idpType] ?? idpType;\n}\n/**\n * Known issuer URL patterns for each IDP type.\n * Used to construct expected issuer URLs from IDP type and domain.\n */\nexport const IDP_ISSUER_PATTERNS = {\n /**\n * Okta issuer: https://{domain}\n * Example: https://acme.okta.com\n */\n [IDP_TYPE.OKTA]: (domain) => `https://${domain}`,\n /**\n * Azure AD issuer: https://login.microsoftonline.com/{tenant}/v2.0\n * Example: https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0\n */\n [IDP_TYPE.AZURE]: (domain) => `https://login.microsoftonline.com/${domain}/v2.0`,\n /**\n * Auth0 issuer: https://{domain}/\n * Example: https://acme.auth0.com/\n * Note: Auth0 issuers have a trailing slash\n */\n [IDP_TYPE.AUTH0]: (domain) => `https://${domain}/`,\n /**\n * Google issuer: Fixed URL (no domain needed)\n */\n [IDP_TYPE.GOOGLE]: () => 'https://accounts.google.com',\n /**\n * Custom OIDC: Requires explicit issuer URL (no pattern)\n */\n [IDP_TYPE.CUSTOM_OIDC]: null,\n /**\n * WorkOS issuer: https://api.workos.com/user_management/{clientId}\n * Example: https://api.workos.com/user_management/client_01KC6057N3C66XJAXZ65YHAC72\n */\n [IDP_TYPE.WORKOS]: (clientId) => `https://api.workos.com/user_management/${clientId}`,\n /**\n * Firebase issuer: https://securetoken.google.com/{projectId}\n * Example: https://securetoken.google.com/my-project-123\n */\n [IDP_TYPE.FIREBASE]: (projectId) => `https://securetoken.google.com/${projectId}`,\n /**\n * OneLogin issuer: https://{subdomain}.onelogin.com/oidc/2\n * Example: https://acme.onelogin.com/oidc/2\n */\n [IDP_TYPE.ONELOGIN]: (subdomain) => `https://${subdomain}.onelogin.com/oidc/2`,\n /**\n * Logto issuer: https://{tenant}.logto.app/oidc\n * Example: https://my-tenant.logto.app/oidc\n */\n [IDP_TYPE.LOGTO]: (tenant) => `https://${tenant}.logto.app/oidc`\n};\n/**\n * Get the expected issuer URL for an IDP configuration.\n *\n * For standard IDPs (Okta, Azure, Auth0, Google), the issuer URL follows\n * a known pattern based on the domain. For Custom OIDC, an explicit\n * issuer URL must be provided.\n *\n * @param idpType - The IDP type\n * @param domain - The IDP domain (e.g., \"acme.okta.com\")\n * @param explicitIssuer - Explicit issuer URL (takes precedence if provided)\n * @returns The issuer URL, or null if it cannot be determined\n *\n * @example\n * ```ts\n * getIdpIssuerUrl('okta', 'acme.okta.com')\n * // => 'https://acme.okta.com'\n *\n * getIdpIssuerUrl('azure', 'contoso.onmicrosoft.com')\n * // => 'https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0'\n *\n * getIdpIssuerUrl('auth0', 'acme.auth0.com')\n * // => 'https://acme.auth0.com/'\n *\n * getIdpIssuerUrl('google', null)\n * // => 'https://accounts.google.com'\n *\n * getIdpIssuerUrl('custom_oidc', null, 'https://auth.example.com')\n * // => 'https://auth.example.com'\n * ```\n */\nexport function getIdpIssuerUrl(idpType, domain, explicitIssuer) {\n // Explicit issuer takes precedence\n if (explicitIssuer) {\n return explicitIssuer;\n }\n // No IDP type means no issuer\n if (!idpType) {\n return null;\n }\n // Google has a fixed issuer URL (no domain needed)\n if (idpType === IDP_TYPE.GOOGLE) {\n return 'https://accounts.google.com';\n }\n // Get the pattern for this IDP type\n const pattern = IDP_ISSUER_PATTERNS[idpType];\n // No pattern means we can't derive the issuer (e.g., custom_oidc without explicit issuer)\n if (!pattern) {\n return null;\n }\n // Other IDPs require a domain\n if (!domain) {\n return null;\n }\n return pattern(domain);\n}\n//# sourceMappingURL=constants.js.map","/**\n * JWT Verifier\n *\n * Complete JWT signature verification using jose library.\n *\n * Security:\n * - Verifies signatures using asymmetric keys only\n * - Validates all claims (alg, iss, aud, exp, etc.)\n * - Integrates with JWKS caching and rate limiting\n * - SSRF protection for JWKS URIs\n */\nimport * as jose from 'jose';\nimport { ALLOWED_ALGORITHMS } from './validators/algorithm.js';\nimport { validateTokenSize } from './validators/token-size.js';\nimport { extractAzureTenantId } from './validators/issuer.js';\nimport { getOIDCDiscoveryUrl, fetchOIDCDiscovery } from './discovery.js';\nimport { getSecureJWKS, clearJWKSCacheEntry } from './jose-jwks.js';\nimport { mapJoseError } from './jose-errors.js';\n/**\n * Default clock skew tolerance in seconds.\n */\nconst DEFAULT_CLOCK_SKEW_SECONDS = 60;\n/**\n * Default max token age in seconds (24 hours).\n */\nconst DEFAULT_MAX_TOKEN_AGE_SECONDS = 24 * 60 * 60;\n/**\n * Main entry point for identity verification.\n *\n * Validates token against org's configured IDP and returns user identity.\n *\n * Token handling policy:\n * - Validate signature against IDP's public keys\n * - Extract sub claim (user ID) and email\n * - Discard the raw token (never stored, never logged)\n *\n * @param options - Verification options\n * @returns Verification result with user identity or error\n */\nexport async function verifyUserIdentity(options) {\n const { authToken, idpConfig, maxTokenAgeSeconds = DEFAULT_MAX_TOKEN_AGE_SECONDS, retryOnKeyNotFound = true } = options;\n // 0. Check if IDP is configured\n if (!idpConfig.type) {\n return {\n success: false,\n errorCode: 'IDP_NOT_CONFIGURED',\n errorMessage: 'Organization does not have an IDP configured'\n };\n }\n // 1. Validate token size (before any parsing)\n const sizeResult = validateTokenSize(authToken);\n if (!sizeResult.valid) {\n return {\n success: false,\n errorCode: sizeResult.errorCode,\n errorMessage: sizeResult.errorMessage\n };\n }\n // 2. Get OIDC discovery URL\n let discoveryUrl;\n try {\n discoveryUrl = getOIDCDiscoveryUrl(idpConfig);\n }\n catch (error) {\n return {\n success: false,\n errorCode: 'IDP_NOT_CONFIGURED',\n errorMessage: error instanceof Error ? error.message : 'IDP configuration error'\n };\n }\n // 3. Fetch OIDC discovery\n let oidcConfig;\n try {\n oidcConfig = await fetchOIDCDiscovery(discoveryUrl);\n }\n catch (error) {\n return {\n success: false,\n errorCode: 'JWKS_FETCH_FAILED',\n errorMessage: `Failed to fetch OIDC discovery: ${error instanceof Error ? error.message : 'unknown error'}`\n };\n }\n // 4. Get secure JWKS getter (with SSRF and rate limit checks)\n const jwksResult = getSecureJWKS(oidcConfig.jwks_uri, discoveryUrl);\n if (!jwksResult.success) {\n return {\n success: false,\n errorCode: jwksResult.errorCode,\n errorMessage: jwksResult.errorMessage\n };\n }\n // 5. Verify token using jose\n let payload;\n try {\n const result = await jose.jwtVerify(authToken, jwksResult.getKey, {\n algorithms: [...ALLOWED_ALGORITHMS],\n issuer: oidcConfig.issuer,\n audience: idpConfig.clientId || undefined,\n clockTolerance: DEFAULT_CLOCK_SKEW_SECONDS,\n maxTokenAge: `${maxTokenAgeSeconds} seconds`\n });\n payload = result.payload;\n }\n catch (error) {\n // Handle key not found with retry (for key rotation)\n if (retryOnKeyNotFound && error instanceof jose.errors.JWKSNoMatchingKey) {\n clearJWKSCacheEntry(oidcConfig.jwks_uri);\n // Re-get JWKS getter after clearing cache\n const retryJwksResult = getSecureJWKS(oidcConfig.jwks_uri, discoveryUrl);\n if (!retryJwksResult.success) {\n return {\n success: false,\n errorCode: retryJwksResult.errorCode,\n errorMessage: retryJwksResult.errorMessage\n };\n }\n try {\n const result = await jose.jwtVerify(authToken, retryJwksResult.getKey, {\n algorithms: [...ALLOWED_ALGORITHMS],\n issuer: oidcConfig.issuer,\n audience: idpConfig.clientId || undefined,\n clockTolerance: DEFAULT_CLOCK_SKEW_SECONDS,\n maxTokenAge: `${maxTokenAgeSeconds} seconds`\n });\n payload = result.payload;\n }\n catch (retryError) {\n const mapped = mapJoseError(retryError);\n return {\n success: false,\n errorCode: mapped.errorCode,\n errorMessage: mapped.errorMessage\n };\n }\n }\n else {\n const mapped = mapJoseError(error);\n return {\n success: false,\n errorCode: mapped.errorCode,\n errorMessage: mapped.errorMessage\n };\n }\n }\n // 6. Custom validation: Azure tenant ID (for /common endpoints)\n const expectedTenantId = extractAzureTenantId(oidcConfig.issuer);\n if (expectedTenantId && payload.tid) {\n if (payload.tid !== expectedTenantId) {\n return {\n success: false,\n errorCode: 'AZURE_TID_MISMATCH',\n errorMessage: `Token tenant ID \"${payload.tid}\" does not match expected \"${expectedTenantId}\"`\n };\n }\n }\n // 7. Custom validation: Authorized party (azp) for multi-audience tokens\n // Per OIDC spec, multi-audience tokens SHOULD include azp. We require it for security.\n const audArray = Array.isArray(payload.aud) ? payload.aud : payload.aud ? [payload.aud] : [];\n if (audArray.length > 1 && idpConfig.clientId) {\n // Multi-audience token: require azp to be present\n if (!payload.azp) {\n return {\n success: false,\n errorCode: 'INVALID_AZP',\n errorMessage: 'Multi-audience token is missing azp (authorized party) claim. ' +\n 'Per OIDC spec, azp SHOULD be present when aud contains multiple audiences.'\n };\n }\n // azp must match our client ID\n if (payload.azp !== idpConfig.clientId) {\n return {\n success: false,\n errorCode: 'INVALID_AZP',\n errorMessage: `Authorized party \"${payload.azp}\" does not match client ID \"${idpConfig.clientId}\"`\n };\n }\n }\n else if (payload.azp && idpConfig.clientId) {\n // Single-audience token with azp present: still validate it matches\n if (payload.azp !== idpConfig.clientId) {\n return {\n success: false,\n errorCode: 'INVALID_AZP',\n errorMessage: `Authorized party \"${payload.azp}\" does not match client ID \"${idpConfig.clientId}\"`\n };\n }\n }\n // 8. Verify required claims (sub)\n if (!payload.sub) {\n return {\n success: false,\n errorCode: 'INVALID_TOKEN',\n errorMessage: 'Missing sub claim'\n };\n }\n // Success - return only the extracted claims\n return {\n success: true,\n userId: payload.sub,\n email: payload.email\n };\n}\n//# sourceMappingURL=jwt-verifier.js.map","/**\n * IDP Schemas\n *\n * Zod schemas for IDP configuration validation with type inference.\n */\nimport { z } from 'zod';\nimport { IDP_TYPES, IDP_TYPE, IDP_DISPLAY_NAMES, IDP_TYPES_REQUIRING_DOMAIN } from './constants.js';\n/**\n * IDP type schema.\n * Uses IDP_TYPES from constants.ts as single source of truth.\n */\nexport const IdpTypeSchema = z.enum(IDP_TYPES).nullable();\n/**\n * Domain format validation.\n * Domain should be a hostname without protocol or trailing slash.\n */\nconst domainSchema = z\n .string()\n .min(1)\n .refine((val) => !val.includes('://'), {\n message: 'Domain should not include protocol (http:// or https://)'\n})\n .refine((val) => !val.endsWith('/'), {\n message: 'Domain should not have trailing slash'\n})\n .nullable()\n .optional();\n/**\n * Issuer URL validation.\n * Must be a valid HTTP(S) URL.\n */\nconst issuerSchema = z\n .string()\n .refine((val) => {\n try {\n const url = new URL(val);\n return url.protocol === 'https:' || url.protocol === 'http:';\n }\n catch {\n return false;\n }\n}, { message: 'Issuer must be a valid HTTP(S) URL' })\n .nullable()\n .optional();\n/**\n * Client ID validation.\n * Can be null/undefined, but if provided must not be empty.\n */\nconst clientIdSchema = z\n .string()\n .refine((val) => val.trim().length > 0, {\n message: 'Client ID cannot be empty'\n})\n .nullable()\n .optional();\n/**\n * Base IDP configuration schema (without cross-field validation).\n */\nconst BaseIdpConfigSchema = z.object({\n type: IdpTypeSchema,\n clientId: clientIdSchema,\n domain: domainSchema,\n issuer: issuerSchema\n});\n/**\n * IDP configuration schema with cross-field validation.\n * Uses IDP_TYPES_REQUIRING_DOMAIN from constants.ts as single source of truth.\n *\n * Note: Unknown IDP types are caught by Zod's enum validation before superRefine runs.\n */\nexport const IdpConfigSchema = BaseIdpConfigSchema.superRefine((config, ctx) => {\n // If type is null, config is valid (unconfigured)\n if (!config.type) {\n return;\n }\n // Check domain requirement for IDPs that need it\n if (IDP_TYPES_REQUIRING_DOMAIN.includes(config.type)) {\n if (!config.domain) {\n // All valid enum types have display names, so this is always defined\n const displayName = IDP_DISPLAY_NAMES[config.type];\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${displayName} requires domain configuration`,\n path: ['domain']\n });\n }\n }\n // Check issuer requirement for custom OIDC\n if (config.type === IDP_TYPE.CUSTOM_OIDC && !config.issuer) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Custom OIDC Provider requires issuer URL configuration',\n path: ['issuer']\n });\n }\n});\n//# sourceMappingURL=schemas.js.map","/**\n * IDP Domain Validation\n *\n * Enhanced validation for IDP configurations with security checks:\n * - Typosquat prevention (validates domain patterns for known IDPs)\n * - ReDoS mitigation (length checks before regex matching)\n * - Wildcard rejection (prevents subdomain takeover attacks)\n */\nimport { IDP_TYPE } from './constants.js';\n/**\n * Maximum length for IDP domain strings.\n * Prevents ReDoS attacks by limiting regex input length.\n * RFC 1035 specifies 253 as max domain name length.\n */\nexport const MAX_IDP_DOMAIN_LENGTH = 253;\n/**\n * Domain patterns for known IDP providers.\n * Used to prevent typosquat attacks (e.g., okta.com.evil.com).\n *\n * These patterns enforce that domains match the expected format for each provider,\n * preventing attackers from using lookalike domains.\n */\nexport const IDP_DOMAIN_PATTERNS = {\n /**\n * Okta domains: subdomain.okta.com or subdomain.oktapreview.com\n * Examples: acme.okta.com, acme.oktapreview.com\n */\n [IDP_TYPE.OKTA]: /^[\\w-]+\\.okta\\.com$|^[\\w-]+\\.oktapreview\\.com$/,\n /**\n * Auth0 domains: tenant.auth0.com or regional variants\n * Examples: acme.auth0.com, acme.us.auth0.com, acme.eu.auth0.com, acme.au.auth0.com\n */\n [IDP_TYPE.AUTH0]: /^[\\w-]+\\.auth0\\.com$|^[\\w-]+\\.us\\.auth0\\.com$|^[\\w-]+\\.eu\\.auth0\\.com$|^[\\w-]+\\.au\\.auth0\\.com$/,\n /**\n * Azure uses tenant ID (UUID) or verified domain - validated separately in validateAzureTenant()\n */\n /**\n * Google uses fixed issuer - no domain validation needed\n */\n /**\n * WorkOS client IDs: client_ prefix followed by 20-40 alphanumeric chars\n * Example: client_01KC6057N3C66XJAXZ65YHAC72\n */\n [IDP_TYPE.WORKOS]: /^client_[A-Za-z0-9]{20,40}$/,\n /**\n * Firebase project IDs: lowercase, 6-30 chars, start with letter, end with letter/number\n * Example: my-project-123\n */\n [IDP_TYPE.FIREBASE]: /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/,\n /**\n * OneLogin subdomains: alphanumeric with hyphens\n * Example: acme, my-company\n */\n [IDP_TYPE.ONELOGIN]: /^[\\w-]+$/,\n /**\n * Logto tenants: alphanumeric with hyphens\n * Example: my-tenant, acme\n */\n [IDP_TYPE.LOGTO]: /^[\\w-]+$/\n};\n/**\n * Validates an Okta domain.\n *\n * @param domain - The domain to validate (e.g., \"acme.okta.com\")\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateOktaDomain('acme.okta.com') // { valid: true }\n * validateOktaDomain('acme.oktapreview.com') // { valid: true }\n * validateOktaDomain('okta.com.evil.com') // { valid: false, error: '...' }\n * ```\n */\nexport function validateOktaDomain(domain) {\n // Length check before regex to prevent ReDoS\n if (domain.length > MAX_IDP_DOMAIN_LENGTH) {\n return { valid: false, error: 'Domain name exceeds maximum length' };\n }\n const pattern = IDP_DOMAIN_PATTERNS[IDP_TYPE.OKTA];\n if (!pattern.test(domain)) {\n return {\n valid: false,\n error: `Invalid Okta domain format. Must match pattern: subdomain.okta.com or subdomain.oktapreview.com. Got: ${domain}`\n };\n }\n return { valid: true };\n}\n/**\n * Validates an Auth0 domain.\n *\n * @param domain - The domain to validate (e.g., \"acme.auth0.com\")\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateAuth0Domain('acme.auth0.com') // { valid: true }\n * validateAuth0Domain('acme.us.auth0.com') // { valid: true }\n * validateAuth0Domain('auth0.com.evil.com') // { valid: false, error: '...' }\n * ```\n */\nexport function validateAuth0Domain(domain) {\n // Length check before regex to prevent ReDoS\n if (domain.length > MAX_IDP_DOMAIN_LENGTH) {\n return { valid: false, error: 'Domain name exceeds maximum length' };\n }\n const pattern = IDP_DOMAIN_PATTERNS[IDP_TYPE.AUTH0];\n if (!pattern.test(domain)) {\n return {\n valid: false,\n error: `Invalid Auth0 domain format. Must match pattern: tenant.auth0.com (or .us.auth0.com, .eu.auth0.com, .au.auth0.com). Got: ${domain}`\n };\n }\n return { valid: true };\n}\n/**\n * UUID pattern for Azure tenant IDs.\n * Format: 8-4-4-4-12 hex chars (e.g., \"12345678-1234-1234-1234-123456789abc\")\n */\nconst AZURE_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n/**\n * Domain pattern for Azure verified domains.\n * Format: valid domain name (e.g., \"contoso.com\", \"acme.onmicrosoft.com\")\n */\nconst AZURE_DOMAIN_PATTERN = /^[\\w-]+(\\.[\\w-]+)+$/;\n/**\n * Validates an Azure AD tenant ID or verified domain.\n *\n * Azure accepts either:\n * - A tenant ID (UUID format)\n * - A verified domain (e.g., contoso.com, acme.onmicrosoft.com)\n *\n * @param tenantIdOrDomain - The tenant ID or domain to validate\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateAzureTenant('12345678-1234-1234-1234-123456789abc') // { valid: true }\n * validateAzureTenant('contoso.com') // { valid: true }\n * validateAzureTenant('invalid') // { valid: false, error: '...' }\n * ```\n */\nexport function validateAzureTenant(tenantIdOrDomain) {\n // Length check before regex to prevent ReDoS\n if (tenantIdOrDomain.length > MAX_IDP_DOMAIN_LENGTH) {\n return { valid: false, error: 'Tenant ID or domain exceeds maximum length' };\n }\n // Check if it's a valid UUID (tenant ID)\n if (AZURE_UUID_PATTERN.test(tenantIdOrDomain)) {\n return { valid: true };\n }\n // Check if it's a valid domain\n if (AZURE_DOMAIN_PATTERN.test(tenantIdOrDomain)) {\n return { valid: true };\n }\n return {\n valid: false,\n error: `Invalid Azure AD tenant format. Must be a tenant ID (UUID) or verified domain. Got: ${tenantIdOrDomain}`\n };\n}\n/**\n * Validates a custom OIDC issuer URL.\n *\n * Requirements:\n * - Must be a valid URL\n * - Must use HTTPS protocol (security requirement)\n *\n * @param issuer - The issuer URL to validate\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateCustomOidcIssuer('https://auth.example.com') // { valid: true }\n * validateCustomOidcIssuer('http://auth.example.com') // { valid: false, error: '...' }\n * validateCustomOidcIssuer('not-a-url') // { valid: false, error: '...' }\n * ```\n */\nexport function validateCustomOidcIssuer(issuer) {\n try {\n const url = new URL(issuer);\n if (url.protocol !== 'https:') {\n return { valid: false, error: 'Custom OIDC issuer must use HTTPS' };\n }\n return { valid: true };\n }\n catch {\n return { valid: false, error: 'Invalid issuer URL format' };\n }\n}\n/**\n * Validates that a domain does not contain wildcards.\n *\n * Wildcard domains are rejected for security reasons:\n * - Prevents subdomain takeover attacks\n * - Ensures explicit allowlisting of domains\n *\n * @param domain - The domain to check\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateNoWildcard('https://app.example.com') // { valid: true }\n * validateNoWildcard('*.example.com') // { valid: false, error: '...' }\n * ```\n */\nexport function validateNoWildcard(domain) {\n if (domain.startsWith('*.') || domain.includes('*')) {\n return {\n valid: false,\n error: `Wildcard domains are not allowed for security reasons. Please add each subdomain explicitly instead of \"${domain}\".`\n };\n }\n return { valid: true };\n}\n/**\n * Validates a WorkOS client ID.\n *\n * @param clientId - The client ID to validate (e.g., \"client_01KC6057N3C66XJAXZ65YHAC72\")\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateWorkOsClientId('client_01KC6057N3C66XJAXZ65YHAC72') // { valid: true }\n * validateWorkOsClientId('01KC6057N3C66XJAXZ65YHAC72') // { valid: false, error: '...' }\n * ```\n */\nexport function validateWorkOsClientId(clientId) {\n // Length check before regex to prevent ReDoS\n if (clientId.length > 50) {\n return { valid: false, error: 'WorkOS client ID exceeds maximum length' };\n }\n const pattern = IDP_DOMAIN_PATTERNS[IDP_TYPE.WORKOS];\n if (!pattern.test(clientId)) {\n return {\n valid: false,\n error: `Invalid WorkOS client ID format. Must start with \"client_\" followed by 20-40 alphanumeric characters. Got: ${clientId}`\n };\n }\n return { valid: true };\n}\n/**\n * Validates a Firebase project ID.\n *\n * @param projectId - The project ID to validate (e.g., \"my-project-123\")\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateFirebaseProjectId('my-project-123') // { valid: true }\n * validateFirebaseProjectId('My-Project') // { valid: false, error: '...' }\n * validateFirebaseProjectId('ab') // { valid: false, error: '...' }\n * ```\n */\nexport function validateFirebaseProjectId(projectId) {\n // Length check before regex to prevent ReDoS\n if (projectId.length > 30) {\n return { valid: false, error: 'Firebase project ID exceeds maximum length of 30 characters' };\n }\n if (projectId.length < 6) {\n return { valid: false, error: 'Firebase project ID must be at least 6 characters' };\n }\n const pattern = IDP_DOMAIN_PATTERNS[IDP_TYPE.FIREBASE];\n if (!pattern.test(projectId)) {\n return {\n valid: false,\n error: `Invalid Firebase project ID format. Must be lowercase, 6-30 chars, start with a letter, and contain only lowercase letters, numbers, and hyphens. Got: ${projectId}`\n };\n }\n return { valid: true };\n}\n/**\n * Validates a OneLogin subdomain.\n *\n * @param subdomain - The subdomain to validate (e.g., \"acme\")\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateOneLoginSubdomain('acme') // { valid: true }\n * validateOneLoginSubdomain('my-company') // { valid: true }\n * validateOneLoginSubdomain('acme.onelogin.com') // { valid: false, error: '...' }\n * ```\n */\nexport function validateOneLoginSubdomain(subdomain) {\n // Length check before regex to prevent ReDoS\n if (subdomain.length > MAX_IDP_DOMAIN_LENGTH) {\n return { valid: false, error: 'OneLogin subdomain exceeds maximum length' };\n }\n // Check for common mistake of including full domain\n if (subdomain.includes('.onelogin.com')) {\n return {\n valid: false,\n error: 'Please enter only the subdomain, not the full URL. For example, enter \"acme\" instead of \"acme.onelogin.com\".'\n };\n }\n const pattern = IDP_DOMAIN_PATTERNS[IDP_TYPE.ONELOGIN];\n if (!pattern.test(subdomain)) {\n return {\n valid: false,\n error: `Invalid OneLogin subdomain format. Must contain only letters, numbers, underscores, and hyphens. Got: ${subdomain}`\n };\n }\n return { valid: true };\n}\n/**\n * Validates a Logto tenant name.\n *\n * @param tenant - The tenant name to validate (e.g., \"my-tenant\")\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateLogtoTenant('my-tenant') // { valid: true }\n * validateLogtoTenant('acme') // { valid: true }\n * validateLogtoTenant('https://my-tenant.logto.app') // { valid: false, error: '...' }\n * ```\n */\nexport function validateLogtoTenant(tenant) {\n // Length check before regex to prevent ReDoS\n if (tenant.length > MAX_IDP_DOMAIN_LENGTH) {\n return { valid: false, error: 'Logto tenant name exceeds maximum length' };\n }\n // Check for common mistake of including full URL\n if (tenant.includes('.logto.app') || tenant.startsWith('https://')) {\n return {\n valid: false,\n error: 'Please enter only the tenant name, not the full URL. For example, enter \"my-tenant\" instead of \"my-tenant.logto.app\".'\n };\n }\n const pattern = IDP_DOMAIN_PATTERNS[IDP_TYPE.LOGTO];\n if (!pattern.test(tenant)) {\n return {\n valid: false,\n error: `Invalid Logto tenant format. Must contain only letters, numbers, underscores, and hyphens. Got: ${tenant}`\n };\n }\n return { valid: true };\n}\n/**\n * Validates IDP domain based on provider type.\n *\n * Dispatches to the appropriate validator based on IDP type:\n * - Okta: validateOktaDomain\n * - Azure: validateAzureTenant\n * - Auth0: validateAuth0Domain\n * - Google: No validation needed (uses fixed issuer)\n * - Custom OIDC: Validates issuer URL instead\n *\n * @param idpType - The IDP type\n * @param domain - The domain to validate (may be null for Google/Custom OIDC)\n * @param issuer - The issuer URL (only for Custom OIDC)\n * @returns Validation result\n */\nexport function validateIdpDomain(idpType, domain, issuer) {\n switch (idpType) {\n case IDP_TYPE.OKTA:\n if (!domain) {\n return { valid: false, error: 'Okta requires domain (e.g., acme.okta.com)' };\n }\n return validateOktaDomain(domain);\n case IDP_TYPE.AZURE:\n if (!domain) {\n return { valid: false, error: 'Azure AD requires tenant domain or tenant ID' };\n }\n return validateAzureTenant(domain);\n case IDP_TYPE.AUTH0:\n if (!domain) {\n return { valid: false, error: 'Auth0 requires domain (e.g., acme.auth0.com)' };\n }\n return validateAuth0Domain(domain);\n case IDP_TYPE.GOOGLE:\n // Google doesn't require domain (uses standard issuer)\n return { valid: true };\n case IDP_TYPE.CUSTOM_OIDC:\n if (!issuer) {\n return { valid: false, error: 'Custom OIDC requires issuer URL' };\n }\n return validateCustomOidcIssuer(issuer);\n case IDP_TYPE.WORKOS:\n // WorkOS doesn't require stored domain - it uses runtime clientId to construct issuer URL\n return { valid: true };\n case IDP_TYPE.FIREBASE:\n if (!domain) {\n return { valid: false, error: 'Firebase requires project ID (e.g., my-project-123)' };\n }\n return validateFirebaseProjectId(domain);\n case IDP_TYPE.ONELOGIN:\n if (!domain) {\n return { valid: false, error: 'OneLogin requires subdomain (e.g., acme)' };\n }\n return validateOneLoginSubdomain(domain);\n case IDP_TYPE.LOGTO:\n if (!domain) {\n return { valid: false, error: 'Logto requires tenant name (e.g., my-tenant)' };\n }\n return validateLogtoTenant(domain);\n default:\n return { valid: false, error: `Unknown IDP type: ${idpType}` };\n }\n}\n/**\n * Validates a complete IDP configuration for security and correctness.\n *\n * Performs comprehensive validation including:\n * - Wildcard rejection in allowed_domains\n * - IDP-specific domain/issuer validation\n * - Typosquat prevention for known IDPs\n * - ReDoS mitigation via length checks\n *\n * @param config - The IDP configuration to validate\n * @returns Validation result\n *\n * @example\n * ```ts\n * validateIdpConfigSecurity({\n * idp_type: 'okta',\n * idp_domain: 'acme.okta.com',\n * idp_client_id: 'abc123',\n * allowed_domains: ['https://app.acme.com']\n * }) // { valid: true }\n *\n * validateIdpConfigSecurity({\n * idp_type: 'okta',\n * idp_domain: 'okta.com.evil.com', // Typosquat attempt\n * idp_client_id: 'abc123',\n * allowed_domains: []\n * }) // { valid: false, error: 'Invalid Okta domain format...' }\n * ```\n */\nexport function validateIdpConfigSecurity(config) {\n // Null/unconfigured IDP is valid\n if (!config.idp_type) {\n return { valid: true };\n }\n // Validate allowed_domains: no wildcards allowed (subdomain takeover risk)\n if (config.allowed_domains) {\n for (const domain of config.allowed_domains) {\n const wildcardResult = validateNoWildcard(domain);\n if (!wildcardResult.valid) {\n return wildcardResult;\n }\n }\n }\n // Validate IDP-specific domain/issuer\n const domainResult = validateIdpDomain(config.idp_type, config.idp_domain, config.idp_issuer);\n if (!domainResult.valid) {\n return domainResult;\n }\n // Warnings (don't fail validation, but log)\n if (!config.idp_client_id) {\n // This is logged in the app layer, not here\n // Just note that client ID is recommended for audience validation\n }\n if (!config.allowed_domains || config.allowed_domains.length === 0) {\n // This is logged in the app layer, not here\n // Just note that allowed_domains is recommended for production\n }\n return { valid: true };\n}\n//# sourceMappingURL=domain-validation.js.map","/**\n * Error Codes - Single Source of Truth\n *\n * All authentication and authorization error codes are defined here.\n * This is the canonical source - other packages should import from here.\n *\n * Error codes are organized into categories:\n * - Token validation errors (from JWT verification)\n * - Key/JWKS errors (from key fetching)\n * - Configuration errors (from IDP setup)\n * - Provider-specific errors (Azure, etc.)\n * - Application-level errors (org lookup, origin validation)\n */\n// =============================================================================\n// Error Code Definitions\n// =============================================================================\n/**\n * Token validation error codes.\n * Returned when JWT verification fails.\n */\nexport const TOKEN_ERROR_CODES = {\n /** No token provided */\n TOKEN_REQUIRED: 'TOKEN_REQUIRED',\n /** Token has expired (exp claim in the past) */\n TOKEN_EXPIRED: 'TOKEN_EXPIRED',\n /** Token is malformed or invalid */\n INVALID_TOKEN: 'INVALID_TOKEN',\n /** Token signature verification failed */\n INVALID_SIGNATURE: 'INVALID_SIGNATURE',\n /** Token issuer doesn't match expected IDP */\n INVALID_ISSUER: 'INVALID_ISSUER',\n /** Token audience doesn't match client ID */\n INVALID_AUDIENCE: 'INVALID_AUDIENCE',\n /** Token uses unsupported signing algorithm */\n INVALID_ALGORITHM: 'INVALID_ALGORITHM',\n /** Authorized party (azp) claim mismatch */\n INVALID_AZP: 'INVALID_AZP',\n /** Token is too old (iat claim) */\n INVALID_TOKEN_AGE: 'INVALID_TOKEN_AGE',\n /** Token exceeds maximum size */\n TOKEN_TOO_LARGE: 'TOKEN_TOO_LARGE',\n};\n/**\n * Key/JWKS error codes.\n * Returned when fetching or using signing keys fails.\n */\nexport const KEY_ERROR_CODES = {\n /** Signing key not found in JWKS */\n KEY_NOT_FOUND: 'KEY_NOT_FOUND',\n /** Failed to fetch JWKS from IDP */\n JWKS_FETCH_FAILED: 'JWKS_FETCH_FAILED',\n /** Too many JWKS fetch requests */\n JWKS_RATE_LIMITED: 'JWKS_RATE_LIMITED',\n};\n/**\n * Configuration error codes.\n * Returned when IDP or security configuration is invalid.\n */\nexport const CONFIG_ERROR_CODES = {\n /** Organization has no IDP configured */\n IDP_NOT_CONFIGURED: 'IDP_NOT_CONFIGURED',\n /** JWKS URL blocked by SSRF protection */\n SSRF_BLOCKED: 'SSRF_BLOCKED',\n /** allowed_audiences must be configured for production */\n ALLOWLIST_REQUIRED: 'ALLOWLIST_REQUIRED',\n};\n/**\n * Provider-specific error codes.\n */\nexport const PROVIDER_ERROR_CODES = {\n /** Azure AD tenant ID mismatch */\n AZURE_TID_MISMATCH: 'AZURE_TID_MISMATCH',\n};\n/**\n * Application-level error codes.\n * Returned by application logic (not JWT verification).\n */\nexport const APP_ERROR_CODES = {\n /** Organization not found for domain/issuer */\n ORG_NOT_FOUND: 'ORG_NOT_FOUND',\n /** Origin not in organization's allowed domains */\n ORIGIN_NOT_ALLOWED: 'ORIGIN_NOT_ALLOWED',\n /** Database operation failed */\n DATABASE_ERROR: 'DATABASE_ERROR',\n /** Anonymous mode requires localhost */\n LOCALHOST_REQUIRED: 'LOCALHOST_REQUIRED',\n /** Anonymous mode requires API key */\n API_KEY_REQUIRED: 'API_KEY_REQUIRED',\n /** Feature not yet implemented */\n FEATURE_NOT_IMPLEMENTED: 'FEATURE_NOT_IMPLEMENTED',\n /** Unexpected internal error */\n INTERNAL_ERROR: 'INTERNAL_ERROR',\n /** client_id parameter missing from request */\n MISSING_CLIENT_ID: 'MISSING_CLIENT_ID',\n /** Neither Origin header nor org_id in body */\n MISSING_ORG_CONTEXT: 'MISSING_ORG_CONTEXT',\n /** client_id not in organization's allowed_audiences */\n CLIENT_ID_NOT_ALLOWED: 'CLIENT_ID_NOT_ALLOWED',\n /** Token does not contain a user identifier (sub claim) */\n MISSING_USER_ID: 'MISSING_USER_ID',\n /** Network error - unable to reach authentication server */\n NETWORK_ERROR: 'NETWORK_ERROR',\n /** Token exchange failed (non-network error) */\n TOKEN_EXCHANGE_ERROR: 'TOKEN_EXCHANGE_ERROR',\n};\n/**\n * All error codes combined.\n * Use this for exhaustive switch statements.\n */\nexport const AUTH_ERROR_CODE = {\n ...TOKEN_ERROR_CODES,\n ...KEY_ERROR_CODES,\n ...CONFIG_ERROR_CODES,\n ...PROVIDER_ERROR_CODES,\n ...APP_ERROR_CODES,\n};\n// =============================================================================\n// HTTP Status Mapping\n// =============================================================================\n/**\n * HTTP status codes for each error code.\n * Used for API responses.\n */\nexport const ERROR_HTTP_STATUS = {\n // Token errors -> 401 Unauthorized (except TOKEN_TOO_LARGE -> 400)\n [AUTH_ERROR_CODE.TOKEN_REQUIRED]: 401,\n [AUTH_ERROR_CODE.TOKEN_EXPIRED]: 401,\n [AUTH_ERROR_CODE.INVALID_TOKEN]: 401,\n [AUTH_ERROR_CODE.INVALID_SIGNATURE]: 401,\n [AUTH_ERROR_CODE.INVALID_ISSUER]: 401,\n [AUTH_ERROR_CODE.INVALID_AUDIENCE]: 401,\n [AUTH_ERROR_CODE.INVALID_ALGORITHM]: 401,\n [AUTH_ERROR_CODE.INVALID_AZP]: 401,\n [AUTH_ERROR_CODE.INVALID_TOKEN_AGE]: 401,\n [AUTH_ERROR_CODE.TOKEN_TOO_LARGE]: 400,\n // Key errors\n [AUTH_ERROR_CODE.KEY_NOT_FOUND]: 401,\n [AUTH_ERROR_CODE.JWKS_FETCH_FAILED]: 502,\n [AUTH_ERROR_CODE.JWKS_RATE_LIMITED]: 429,\n // Config errors\n [AUTH_ERROR_CODE.IDP_NOT_CONFIGURED]: 500,\n [AUTH_ERROR_CODE.SSRF_BLOCKED]: 400,\n [AUTH_ERROR_CODE.ALLOWLIST_REQUIRED]: 400,\n // Provider errors\n [AUTH_ERROR_CODE.AZURE_TID_MISMATCH]: 401,\n // App errors\n [AUTH_ERROR_CODE.ORG_NOT_FOUND]: 404,\n [AUTH_ERROR_CODE.ORIGIN_NOT_ALLOWED]: 403,\n [AUTH_ERROR_CODE.DATABASE_ERROR]: 503,\n [AUTH_ERROR_CODE.LOCALHOST_REQUIRED]: 403,\n [AUTH_ERROR_CODE.API_KEY_REQUIRED]: 400,\n [AUTH_ERROR_CODE.FEATURE_NOT_IMPLEMENTED]: 501,\n [AUTH_ERROR_CODE.INTERNAL_ERROR]: 500,\n [AUTH_ERROR_CODE.MISSING_CLIENT_ID]: 400,\n [AUTH_ERROR_CODE.MISSING_ORG_CONTEXT]: 400,\n [AUTH_ERROR_CODE.CLIENT_ID_NOT_ALLOWED]: 403,\n [AUTH_ERROR_CODE.MISSING_USER_ID]: 401,\n [AUTH_ERROR_CODE.NETWORK_ERROR]: 503,\n [AUTH_ERROR_CODE.TOKEN_EXCHANGE_ERROR]: 500,\n};\n// =============================================================================\n// Utility Functions\n// =============================================================================\n/**\n * Get HTTP status code for an error code.\n */\nexport function getHttpStatus(errorCode) {\n return ERROR_HTTP_STATUS[errorCode] ?? 500;\n}\n/**\n * Check if an error code indicates an authentication failure (401).\n */\nexport function isAuthError(errorCode) {\n return getHttpStatus(errorCode) === 401;\n}\n/**\n * Check if an error is retryable (transient failures).\n */\nexport function isRetryable(errorCode) {\n const retryableCodes = [\n AUTH_ERROR_CODE.JWKS_FETCH_FAILED,\n AUTH_ERROR_CODE.JWKS_RATE_LIMITED,\n AUTH_ERROR_CODE.DATABASE_ERROR,\n AUTH_ERROR_CODE.INTERNAL_ERROR,\n AUTH_ERROR_CODE.NETWORK_ERROR,\n ];\n return retryableCodes.includes(errorCode);\n}\n/**\n * Check if an error is recoverable by the user (e.g., sign in again).\n */\nexport function isRecoverable(errorCode) {\n const unrecoverableCodes = [\n AUTH_ERROR_CODE.IDP_NOT_CONFIGURED,\n AUTH_ERROR_CODE.ORG_NOT_FOUND,\n AUTH_ERROR_CODE.ORIGIN_NOT_ALLOWED,\n AUTH_ERROR_CODE.SSRF_BLOCKED,\n AUTH_ERROR_CODE.FEATURE_NOT_IMPLEMENTED,\n AUTH_ERROR_CODE.ALLOWLIST_REQUIRED,\n AUTH_ERROR_CODE.CLIENT_ID_NOT_ALLOWED,\n AUTH_ERROR_CODE.MISSING_USER_ID,\n ];\n return !unrecoverableCodes.includes(errorCode);\n}\n/**\n * Type guard to check if a string is a valid AuthErrorCode.\n */\nexport function isAuthErrorCode(code) {\n return Object.values(AUTH_ERROR_CODE).includes(code);\n}\n/**\n * Helper for exhaustive switch statements.\n * TypeScript will error if any case is missing.\n *\n * @example\n * ```ts\n * function handleError(code: AuthErrorCode) {\n * switch (code) {\n * case 'TOKEN_REQUIRED': return 'Please sign in'\n * // ... all other cases\n * default:\n * return assertNever(code) // Error if any case missing\n * }\n * }\n * ```\n */\nexport function assertNever(value, message) {\n throw new Error(message ?? `Unhandled error code: ${value}`);\n}\n//# sourceMappingURL=codes.js.map","/**\n * Error Builder - Exhaustive Error Response Construction\n *\n * Creates user-friendly error responses with:\n * - Clear error titles\n * - Actionable messages\n * - Step-by-step fix instructions\n * - Links to dashboard/docs\n *\n * Uses exhaustive switch to ensure all error codes are handled.\n * TypeScript will error at compile time if a new error code is added\n * but not handled here.\n */\nimport { AUTH_ERROR_CODE, getHttpStatus, isRecoverable, assertNever, } from './codes.js';\n/**\n * Metadata for each error code.\n * This is the single source of truth for error messages.\n */\nfunction getErrorMetadata(code, context) {\n switch (code) {\n // =========================================================================\n // Token Validation Errors\n // =========================================================================\n case AUTH_ERROR_CODE.TOKEN_REQUIRED:\n return {\n title: 'Sign In Required',\n message: 'Please sign in to continue.',\n docsLink: '/docs/auth/sso-setup',\n };\n case AUTH_ERROR_CODE.TOKEN_EXPIRED:\n return {\n title: 'Session Expired',\n message: 'Your session has expired. Please sign in again.',\n };\n case AUTH_ERROR_CODE.INVALID_TOKEN:\n return {\n title: 'Authentication Error',\n message: 'Your authentication token is invalid. Please sign in again.',\n };\n case AUTH_ERROR_CODE.INVALID_SIGNATURE:\n return {\n title: 'Authentication Failed',\n message: \"We couldn't verify your identity. Please sign in again.\",\n };\n case AUTH_ERROR_CODE.INVALID_ISSUER:\n return {\n title: 'Wrong Authentication Provider',\n message: \"Your token is from a different identity provider than expected.\",\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Go to Integration > Identity Provider',\n 'Verify the configuration matches your actual IDP:',\n '- Make sure you selected the correct IDP type',\n '- Verify the domain/issuer matches your IDP settings',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/idp-issuer-validation',\n };\n case AUTH_ERROR_CODE.INVALID_AUDIENCE:\n return {\n title: 'Wrong Application',\n message: 'This authentication token is for a different application. Please sign in again.',\n callToAction: {\n steps: [\n 'Verify you are using the correct IDP application',\n 'Check that the Client ID in your dashboard matches your IDP app',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/idp-configuration',\n };\n case AUTH_ERROR_CODE.INVALID_ALGORITHM:\n return {\n title: 'Unsupported Token Format',\n message: 'Your identity provider is using an unsupported signing algorithm.',\n callToAction: {\n steps: [\n 'Configure your IDP to use RS256 or ES256 signing algorithm',\n 'HS256 (symmetric) is not supported for security reasons',\n ],\n },\n docsLink: '/docs/supported-algorithms',\n };\n case AUTH_ERROR_CODE.INVALID_AZP:\n return {\n title: 'Invalid Authorized Party',\n message: 'The token authorized party does not match the expected client.',\n callToAction: {\n steps: [\n 'For multi-audience tokens, ensure the azp claim matches your client_id',\n 'Check your IDP application configuration',\n ],\n },\n docsLink: '/docs/multi-audience-tokens',\n };\n case AUTH_ERROR_CODE.INVALID_TOKEN_AGE:\n return {\n title: 'Token Too Old',\n message: 'Your authentication token is too old. Please sign in again.',\n callToAction: {\n steps: [\n 'Request a fresh token from your identity provider',\n 'If this persists, check your IDP token lifetime settings',\n ],\n },\n };\n case AUTH_ERROR_CODE.TOKEN_TOO_LARGE:\n return {\n title: 'Token Too Large',\n message: 'The authentication token exceeds the maximum allowed size.',\n callToAction: {\n steps: [\n 'Normal ID tokens are typically 1-4KB',\n 'Check if your IDP is including excessive claims',\n 'Consider using access tokens instead of ID tokens if they are smaller',\n ],\n },\n };\n // =========================================================================\n // Key/JWKS Errors\n // =========================================================================\n case AUTH_ERROR_CODE.KEY_NOT_FOUND:\n return {\n title: 'Key Not Found',\n message: 'Authentication key not found. Try signing in again or contact support.',\n callToAction: {\n steps: [\n \"The signing key may have been rotated by your IDP\",\n 'Try signing out and signing in again to get a fresh token',\n ],\n },\n };\n case AUTH_ERROR_CODE.JWKS_FETCH_FAILED:\n return {\n title: 'Cannot Reach Authentication Provider',\n message: \"We couldn't connect to your identity provider to verify your credentials.\",\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Go to Integration > Identity Provider',\n 'Verify the IDP Domain is correct:',\n '- Okta: Check your Okta admin URL (e.g., acme.okta.com)',\n '- Azure AD: Verify your tenant domain or tenant ID',\n '- Auth0: Check your Auth0 domain (e.g., acme.auth0.com)',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/finding-idp-domain',\n };\n case AUTH_ERROR_CODE.JWKS_RATE_LIMITED:\n return {\n title: 'Too Many Requests',\n message: 'Too many authentication attempts. Please wait a moment and try again.',\n };\n // =========================================================================\n // Configuration Errors\n // =========================================================================\n case AUTH_ERROR_CODE.IDP_NOT_CONFIGURED:\n return {\n title: 'Authentication Not Set Up',\n message: 'Your organization has not configured an identity provider yet.',\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Navigate to Integration > Identity Provider',\n 'Select your identity provider (Okta, Azure AD, Auth0, etc.)',\n 'Complete the configuration',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/sso-setup',\n };\n case AUTH_ERROR_CODE.SSRF_BLOCKED:\n return {\n title: 'Invalid IDP URL',\n message: 'The identity provider URL is not allowed for security reasons.',\n callToAction: {\n steps: [\n 'Only public HTTPS endpoints are permitted',\n 'Internal/private URLs are blocked',\n 'Check your IDP domain configuration',\n ],\n },\n dashboardLink: '/integration',\n };\n // =========================================================================\n // Provider-Specific Errors\n // =========================================================================\n case AUTH_ERROR_CODE.AZURE_TID_MISMATCH:\n return {\n title: 'Azure Tenant Mismatch',\n message: \"Your Azure AD token's tenant ID doesn't match the configured tenant.\",\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Go to Integration > Identity Provider',\n 'Verify the Tenant ID matches your Azure AD configuration',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/azure-setup',\n };\n // =========================================================================\n // Application-Level Errors\n // =========================================================================\n case AUTH_ERROR_CODE.ORG_NOT_FOUND:\n return {\n title: 'Organization Not Found',\n message: \"We couldn't find an organization for this domain.\",\n callToAction: {\n steps: [\n 'Verify this widget is embedded on an authorized domain',\n 'Contact your administrator if this domain should be authorized',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/allowed-domains',\n };\n case AUTH_ERROR_CODE.ORIGIN_NOT_ALLOWED:\n return {\n title: 'Domain Not Authorized',\n message: context?.currentDomain\n ? `The domain \"${context.currentDomain}\" is not authorized.`\n : 'This domain is not authorized to use this widget.',\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Go to Integration > Identity Provider',\n `Add this domain to the 'Allowed Domains' list${context?.currentDomain ? `: ${context.currentDomain}` : ''}`,\n 'Save your changes',\n ],\n examples: ['https://app.acme.com', 'https://crm.acme.com'],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/managing-allowed-domains',\n };\n case AUTH_ERROR_CODE.DATABASE_ERROR:\n return {\n title: 'Service Unavailable',\n message: 'Service temporarily unavailable. Please try again later.',\n };\n case AUTH_ERROR_CODE.LOCALHOST_REQUIRED:\n return {\n title: 'Development Mode Only',\n message: 'Anonymous mode is only available on localhost for development.',\n callToAction: {\n steps: [\n 'For production, configure SSO authentication',\n 'For development, run on localhost',\n ],\n },\n docsLink: '/docs/development-mode',\n };\n case AUTH_ERROR_CODE.API_KEY_REQUIRED:\n return {\n title: 'API Key Required',\n message: 'Anonymous mode requires an Anthropic API key.',\n callToAction: {\n steps: [\n 'Pass your Anthropic API key in the dev-mode configuration',\n 'Or configure SSO authentication for production use',\n ],\n },\n docsLink: '/docs/development-mode',\n };\n case AUTH_ERROR_CODE.FEATURE_NOT_IMPLEMENTED:\n return {\n title: 'Coming Soon',\n message: 'This feature is not yet available.',\n };\n case AUTH_ERROR_CODE.INTERNAL_ERROR:\n return {\n title: 'Something Went Wrong',\n message: 'An unexpected error occurred. Please try again.',\n };\n // =========================================================================\n // Client ID / Allowlist Errors\n // =========================================================================\n case AUTH_ERROR_CODE.MISSING_CLIENT_ID:\n return {\n title: 'Client ID Required',\n message: 'A client_id parameter is required for authentication.',\n callToAction: {\n steps: [\n 'Pass the client_id when connecting to Char',\n 'For browser: connect({ idToken, clientId })',\n 'For SSR: include client_id in the ticket request body',\n ],\n },\n docsLink: '/docs/client-id-setup',\n };\n case AUTH_ERROR_CODE.MISSING_ORG_CONTEXT:\n return {\n title: 'Organization Context Required',\n message: 'Could not determine your organization. For SSR, include org_id in the request.',\n callToAction: {\n steps: [\n 'For browser requests: Origin header is used automatically',\n 'For SSR requests: include org_id in the request body',\n 'Find your org_id in the dashboard under Integration > OAuth',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/ssr-authentication',\n };\n case AUTH_ERROR_CODE.ALLOWLIST_REQUIRED:\n return {\n title: 'Allowed Audiences Required',\n message: 'Production usage requires configuring allowed_audiences in your dashboard.',\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Go to Integration > OAuth',\n 'Add your OIDC client ID(s) to the Allowed Client IDs list',\n 'Save your changes',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/allowed-audiences',\n };\n case AUTH_ERROR_CODE.CLIENT_ID_NOT_ALLOWED:\n return {\n title: 'Client ID Not Authorized',\n message: 'This client_id is not in the allowed audiences list.',\n callToAction: {\n steps: [\n 'Open your dashboard',\n 'Go to Integration > OAuth',\n 'Add this client_id to the Allowed Client IDs list',\n 'Save your changes',\n ],\n },\n dashboardLink: '/integration',\n docsLink: '/docs/allowed-audiences',\n };\n case AUTH_ERROR_CODE.MISSING_USER_ID:\n return {\n title: 'Missing User ID',\n message: 'Token does not contain a user identifier (sub claim).',\n callToAction: {\n steps: [\n 'Ensure your IDP includes the sub claim in ID tokens',\n 'The sub claim is standard in OIDC - check your IDP application settings',\n 'Verify your IDP is configured to return ID tokens (not just access tokens)',\n ],\n },\n docsLink: '/docs/token-requirements',\n };\n case AUTH_ERROR_CODE.NETWORK_ERROR:\n return {\n title: 'Network Error',\n message: 'Unable to reach authentication server. Please check your connection and try again.',\n callToAction: {\n steps: [\n 'Check your internet connection',\n 'Try refreshing the page',\n 'If the problem persists, contact support',\n ],\n },\n };\n case AUTH_ERROR_CODE.TOKEN_EXCHANGE_ERROR:\n return {\n title: 'Authentication Failed',\n message: 'Failed to exchange your credentials for a session token.',\n callToAction: {\n steps: [\n 'Try signing in again',\n 'Clear your browser cache and cookies',\n 'If the problem persists, contact your administrator',\n ],\n },\n docsLink: '/docs/troubleshooting-auth',\n };\n default:\n // TypeScript will error here if any error code is not handled\n return assertNever(code, `Unhandled error code in getErrorMetadata: ${code}`);\n }\n}\n// =============================================================================\n// Builder Function\n// =============================================================================\n/**\n * Build a complete error response for an error code.\n *\n * This function handles ALL error codes exhaustively.\n * TypeScript will error at compile time if a new error code is added\n * but not handled.\n *\n * @example\n * ```ts\n * const response = buildAuthError({\n * errorCode: 'ORIGIN_NOT_ALLOWED',\n * context: { currentDomain: 'https://example.com' }\n * })\n * // Returns complete error response with title, message, call to action, etc.\n * ```\n */\nexport function buildAuthError(options) {\n const { errorCode, message, context } = options;\n const metadata = getErrorMetadata(errorCode, context);\n // Resolve dynamic message if it's a function\n const resolvedMessage = typeof metadata.message === 'function' ? metadata.message(context) : metadata.message;\n // Resolve dynamic callToAction if it's a function\n const resolvedCallToAction = typeof metadata.callToAction === 'function'\n ? metadata.callToAction(context)\n : metadata.callToAction;\n return {\n errorCode,\n errorTitle: metadata.title,\n message: resolvedMessage,\n callToAction: resolvedCallToAction,\n dashboardLink: metadata.dashboardLink,\n docsLink: metadata.docsLink,\n context,\n recoverable: isRecoverable(errorCode),\n debugInfo: message,\n httpStatus: getHttpStatus(errorCode),\n };\n}\n/**\n * Create a JSON Response from an error.\n *\n * @example\n * ```ts\n * return createAuthErrorResponse({\n * errorCode: 'TOKEN_EXPIRED',\n * message: 'Token expired at 2024-01-01'\n * })\n * // Returns Response with JSON body and appropriate status code\n * ```\n */\nexport function createAuthErrorResponse(options) {\n const errorResponse = buildAuthError(options);\n return new Response(JSON.stringify({\n error: {\n code: errorResponse.errorCode,\n title: errorResponse.errorTitle,\n message: errorResponse.message,\n callToAction: errorResponse.callToAction,\n dashboardLink: errorResponse.dashboardLink,\n docsLink: errorResponse.docsLink,\n recoverable: errorResponse.recoverable,\n },\n }), {\n status: errorResponse.httpStatus,\n headers: {\n 'Content-Type': 'application/json',\n 'WWW-Authenticate': `Bearer error=\"${errorResponse.errorCode}\"`,\n },\n });\n}\n//# sourceMappingURL=builder.js.map","/**\n * Convert InitContextResult error to AuthError\n *\n * Takes the structured error response from the backend and converts it\n * to an AuthError that the error boundary can display properly.\n */\n\nimport { isAuthErrorCode, APP_ERROR_CODES, type ErrorContext } from \"@char-ai/auth\";\nimport type { InitContextResult } from \"@mcp-b/shared-types\";\nimport type { AuthError, AuthErrorCode } from \"./auth-errors\";\n\n/**\n * Map backend error codes to frontend error codes.\n * Uses isAuthErrorCode from @char-ai/auth to validate known codes.\n */\nfunction mapErrorCode(\n backendCode: InitContextResult[\"errorCode\"]\n): AuthErrorCode {\n if (!backendCode) {\n return APP_ERROR_CODES.INTERNAL_ERROR;\n }\n\n // If it's a known auth error code, use it directly\n if (isAuthErrorCode(backendCode)) {\n return backendCode;\n }\n\n // Unknown code - return internal error\n return APP_ERROR_CODES.INTERNAL_ERROR;\n}\n\n/**\n * Convert InitContextResult failure to AuthError\n */\nexport function convertInitErrorToAuthError(\n result: InitContextResult\n): AuthError {\n if (result.success) {\n throw new Error(\"Cannot convert successful result to error\");\n }\n\n const code = mapErrorCode(result.errorCode);\n\n return {\n code,\n title: result.errorTitle || \"Authentication Error\",\n message: result.message,\n callToAction: result.callToAction,\n dashboardLink: result.dashboardLink,\n docsLink: result.docsLink,\n // Cast context since Zod passthrough produces `unknown` for extra properties\n // but we know the backend produces valid ErrorContext data\n context: result.context as ErrorContext | undefined,\n recoverable: result.recoverable ?? false,\n debugInfo: result.debugInfo,\n };\n}\n\n/**\n * AuthError class that can be thrown and caught\n */\nexport class AuthErrorException extends Error implements AuthError {\n code: AuthErrorCode;\n title: string;\n callToAction?: AuthError[\"callToAction\"];\n dashboardLink?: string;\n docsLink?: string;\n context?: AuthError[\"context\"];\n recoverable: boolean;\n debugInfo?: string;\n\n constructor(authError: AuthError) {\n super(authError.message);\n this.name = \"AuthErrorException\";\n this.code = authError.code;\n this.title = authError.title;\n this.message = authError.message;\n this.callToAction = authError.callToAction;\n this.dashboardLink = authError.dashboardLink;\n this.docsLink = authError.docsLink;\n this.context = authError.context;\n this.recoverable = authError.recoverable;\n this.debugInfo = authError.debugInfo;\n\n // Maintain proper stack trace\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AuthErrorException);\n }\n }\n}\n\n/**\n * Create and throw an AuthErrorException from InitContextResult\n */\nexport function throwInitError(result: InitContextResult): never {\n const authError = convertInitErrorToAuthError(result);\n throw new AuthErrorException(authError);\n}\n","import { useLayoutEffect, useRef } from 'react'\n\nimport stableStringifyImpl from 'fast-json-stable-stringify'\nimport { isToolUIPart, type UIMessage } from 'ai'\n\n/**\n * Returns a ref that always contains the latest value.\n * Useful for accessing fresh values in callbacks without adding to dependency arrays.\n *\n * Per Vercel React best practices (advanced-use-latest):\n * - Prevents effect re-runs while avoiding stale closures\n * - Use when a callback needs the latest value but shouldn't re-subscribe on changes\n */\nexport function useLatest<T>(value: T): { readonly current: T } {\n\tconst ref = useRef(value)\n\tuseLayoutEffect(() => {\n\t\tref.current = value\n\t}, [value])\n\treturn ref\n}\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type {\n\tHubToSiteMessage,\n\tPolicyEventMessage,\n\tSyncedToolSchema,\n\tToolSourcesUpdateMessage,\n} from '@mcp-b/shared-types'\n\n/**\n * Small internal helpers for `useThreadRuntime`.\n *\n * Keep these React-safe (no module-level mutable state) and dependency-light.\n */\nexport function stableStringify(value: unknown): string {\n\treturn stableStringifyImpl(value ?? null)\n}\n\n/**\n * Generate a short 4-character tab ID.\n * Used for source metadata and request routing between embedded agent instances.\n *\n * IMPORTANT: tabId vs sourceId\n * - tabId: This 4-char session ID, stable for the life of the embedded agent instance\n * - sourceId: WebSocket connection ID assigned by server, changes on reconnect\n *\n * requestTabId is included in chat requests so the backend can prefer tools from this tab.\n *\n * Format: 4 base36 characters (0-9, a-z) giving 1.6M+ possible combinations.\n * Example: \"a3x9\", \"5k2p\", \"zz99\"\n */\nfunction generateShortTabId(): string {\n\tif (typeof window === 'undefined') return 'srvr'\n\n\t// Generate 4-char base36 hash (a-z, 0-9)\n\t// 36^4 = 1,679,616 possible combinations\n\tconst random = Math.floor(Math.random() * 1679616)\n\treturn random.toString(36).padStart(4, '0')\n}\n\n/**\n * Unique tab ID for this embedded agent instance.\n * Generated once at module load time - lives in memory only.\n * Each import of this module gets its own unique ID.\n *\n * This is NOT a browser tab ID or a server-assigned sourceId.\n * It's a session identifier for routing requests and selecting matching tool sources.\n */\nconst EMBEDDED_AGENT_TAB_ID = generateShortTabId()\n\n/**\n * Get the tab ID for this embedded agent instance.\n * This ID is generated once when the module loads and remains constant.\n *\n * Used for:\n * - Request routing hint: `requestTabId` in chat requests\n * - Routing tool calls back to the correct embedded agent instance\n *\n * @returns 4-character tab ID unique to this module instance\n */\nexport function getEmbeddedAgentTabId(): string {\n\treturn EMBEDDED_AGENT_TAB_ID\n}\n\nexport function areSyncedToolSchemasEquivalent(\n\ta: readonly SyncedToolSchema[],\n\tb: readonly SyncedToolSchema[],\n): boolean {\n\tif (a === b) return true\n\tif (a.length !== b.length) return false\n\n\tconst byName = new Map<string, SyncedToolSchema>()\n\tfor (const schema of a) byName.set(schema.name, schema)\n\n\tfor (const next of b) {\n\t\tconst prev = byName.get(next.name)\n\t\tif (!prev) return false\n\t\tif ((prev.description ?? '') !== (next.description ?? '')) return false\n\t\tif (stableStringify(prev.inputSchema) !== stableStringify(next.inputSchema)) return false\n\t\tif (stableStringify(prev.annotations ?? null) !== stableStringify(next.annotations ?? null))\n\t\t\treturn false\n\t\tif (stableStringify(prev.sources ?? null) !== stableStringify(next.sources ?? null))\n\t\t\treturn false\n\t}\n\n\treturn true\n}\n\nexport function safeParseHubToSiteMessage(data: unknown): HubToSiteMessage | null {\n\tif (typeof data !== 'string') return null\n\n\ttry {\n\t\tconst parsed = JSON.parse(data) as unknown\n\t\tif (!parsed || typeof parsed !== 'object') return null\n\n\t\tconst msg = parsed as Partial<HubToSiteMessage>\n\t\tif (msg.type === 'ping') return { type: 'ping' }\n\t\tif (\n\t\t\tmsg.type === 'invoke' &&\n\t\t\ttypeof msg.callId === 'string' &&\n\t\t\ttypeof msg.toolName === 'string'\n\t\t) {\n\t\t\treturn {\n\t\t\t\ttype: 'invoke',\n\t\t\t\tcallId: msg.callId,\n\t\t\t\ttoolName: msg.toolName,\n\t\t\t\targs: msg.args as Record<string, unknown> | undefined,\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t} catch {\n\t\treturn null\n\t}\n}\n\nexport function safeParseToolSourcesMessage(data: unknown): ToolSourcesUpdateMessage | null {\n\tif (typeof data !== 'string') return null\n\n\ttry {\n\t\tconst parsed = JSON.parse(data) as unknown\n\t\tif (!parsed || typeof parsed !== 'object') return null\n\n\t\tconst msg = parsed as Partial<ToolSourcesUpdateMessage>\n\t\tif (msg.type !== 'tool_sources' || !Array.isArray(msg.sources)) return null\n\t\treturn { type: 'tool_sources', sources: msg.sources }\n\t} catch {\n\t\treturn null\n\t}\n}\n\nexport function safeParsePolicyEventMessage(data: unknown): PolicyEventMessage | null {\n\tif (typeof data !== 'string') return null\n\n\ttry {\n\t\tconst parsed = JSON.parse(data) as unknown\n\t\tif (!parsed || typeof parsed !== 'object') return null\n\n\t\tconst msg = parsed as Partial<PolicyEventMessage>\n\t\tif (msg.type !== 'policy_event' || !msg.event || typeof msg.event !== 'object') return null\n\t\treturn {\n\t\t\ttype: 'policy_event',\n\t\t\tevent: msg.event as PolicyEventMessage['event'],\n\t\t}\n\t} catch {\n\t\treturn null\n\t}\n}\n\nexport function formatToolResult(result: CallToolResult): string {\n\tconst textContent = result.content.find((c) => c.type === 'text')\n\treturn textContent?.text ?? JSON.stringify(result.content)\n}\n\nexport function sliceMessagesUntil<T extends { id: string }>(\n\tmessages: T[],\n\tparentId: string | null,\n): T[] {\n\tif (parentId === null) return []\n\tconst index = messages.findIndex((m) => m.id === parentId)\n\tif (index === -1) return messages\n\treturn messages.slice(0, index + 1)\n}\n\nfunction shallowEqualRecords(\n\ta: Record<string, unknown> | undefined,\n\tb: Record<string, unknown> | undefined,\n): boolean {\n\tif (a === b) return true\n\tif (!a || !b) return false\n\n\tconst aKeys = Object.keys(a)\n\tconst bKeys = Object.keys(b)\n\tif (aKeys.length !== bKeys.length) return false\n\n\tfor (const key of aKeys) {\n\t\tif (!Object.prototype.hasOwnProperty.call(b, key)) return false\n\t\tif (a[key] !== b[key]) return false\n\t}\n\n\treturn true\n}\n\nexport function useShallowStableObject<T extends Record<string, unknown> | undefined>(value: T): T {\n\tconst ref = useRef(value)\n\tif (!shallowEqualRecords(ref.current, value)) {\n\t\tref.current = value\n\t}\n\treturn ref.current\n}\n\n/**\n * Get tool call IDs for tools that are pending approval.\n * These are tools in 'input-available' state without output - waiting for user action.\n */\nexport function getPendingToolCallIds(messages: UIMessage[]): string[] {\n\tconst lastMessage = messages[messages.length - 1]\n\tif (!lastMessage || lastMessage.role !== 'assistant' || !lastMessage.parts) {\n\t\treturn []\n\t}\n\n\treturn lastMessage.parts\n\t\t.filter((part): part is Extract<typeof part, { toolCallId: string }> =>\n\t\t\tisToolUIPart(part) &&\n\t\t\tpart.state === 'input-available' &&\n\t\t\tpart.output === undefined\n\t\t)\n\t\t.map((part) => part.toolCallId)\n}\n","/**\n * useToolSourceMetadata\n *\n * Tracks page metadata (URL, title, favicon) for tool source identification.\n * This metadata helps identify which site tools come from in cross-app RPC scenarios.\n *\n * Simplified version - removed history API patching for safety when embedded on other sites.\n */\n\nimport { useCallback, useEffect, useState } from 'react'\n\nimport type { ToolConnectionMetadata } from '@mcp-b/shared-types'\n\nimport { getEmbeddedAgentTabId } from './thread-runtime-utils'\n\n/**\n * Options for useToolSourceMetadata hook.\n */\nexport interface UseToolSourceMetadataOptions {\n\t/**\n\t * Whether to actively track metadata.\n\t * Should be enabled when manager is connected.\n\t */\n\tenabled: boolean\n}\n\n/**\n * Result from useToolSourceMetadata hook.\n */\nexport interface UseToolSourceMetadataResult {\n\t/**\n\t * Current page metadata (URL, title, icon, etc.)\n\t */\n\tmetadata: ToolConnectionMetadata | undefined\n}\n\n/**\n * Hook that tracks page metadata for tool source identification.\n *\n * Tracks:\n * - Page URL and origin\n * - Document title (with observer for SPA title changes)\n * - Favicon URL (with observer for dynamic icon updates)\n * - Tab session ID\n *\n * Simplified from original implementation:\n * - No history API patching (safer for embedded contexts)\n * - No popstate/hashchange listeners (not needed for metadata)\n * - Keeps title/favicon observers for SPA support\n * - Keeps focus/visibilitychange for reconnection scenarios\n *\n * @param options - Configuration options\n * @returns Current page metadata\n */\nexport function useToolSourceMetadata(\n\toptions: UseToolSourceMetadataOptions,\n): UseToolSourceMetadataResult {\n\tconst { enabled } = options\n\tconst tabId = getEmbeddedAgentTabId()\n\n\tconst getMetadata = useCallback((): ToolConnectionMetadata | undefined => {\n\t\tif (typeof window === 'undefined') return undefined\n\n\t\tconst iconUrl = (() => {\n\t\t\ttry {\n\t\t\t\tconst link = document.querySelector(\"link[rel~='icon']\") as HTMLLinkElement | null\n\t\t\t\tconst href = link?.getAttribute('href')\n\t\t\t\tif (!href) return undefined\n\t\t\t\treturn new URL(href, window.location.href).toString()\n\t\t\t} catch {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t})()\n\n\t\treturn {\n\t\t\turl: window.location.href,\n\t\t\torigin: window.location.origin,\n\t\t\ttitle: document.title?.trim() || undefined,\n\t\t\ticonUrl,\n\t\t\ttabId,\n\t\t}\n\t}, [tabId])\n\n\tconst [metadata, setMetadata] = useState<ToolConnectionMetadata | undefined>(() =>\n\t\tenabled ? getMetadata() : undefined,\n\t)\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\tsetMetadata(undefined)\n\t\t\treturn\n\t\t}\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst updateMetadata = () => {\n\t\t\tsetMetadata(getMetadata())\n\t\t}\n\n\t\t// Set initial metadata\n\t\tupdateMetadata()\n\n\t\t// Listen for focus and visibility changes (for reconnection scenarios)\n\t\twindow.addEventListener('focus', updateMetadata)\n\t\tdocument.addEventListener('visibilitychange', updateMetadata)\n\n\t\t// Watch for title changes (common in SPAs)\n\t\tconst titleObserver = new MutationObserver(updateMetadata)\n\t\tconst titleElement = document.querySelector('title')\n\t\tif (titleElement) {\n\t\t\ttitleObserver.observe(titleElement, { childList: true })\n\t\t}\n\n\t\t// Watch for favicon changes (less common but possible)\n\t\tconst headObserver = new MutationObserver(updateMetadata)\n\t\theadObserver.observe(document.head, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true,\n\t\t\tattributes: true,\n\t\t\tattributeFilter: ['rel', 'href'],\n\t\t})\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('focus', updateMetadata)\n\t\t\tdocument.removeEventListener('visibilitychange', updateMetadata)\n\t\t\ttitleObserver.disconnect()\n\t\t\theadObserver.disconnect()\n\t\t}\n\t}, [enabled, getMetadata])\n\n\treturn { metadata }\n}\n","/**\n * useToolSourceRegistration\n *\n * Registers local MCP tools with ThreadManager for cross-app RPC.\n * This allows other sites to discover and invoke tools from this embedding site.\n */\n\nimport { useEffect, useMemo, useRef } from 'react'\n\nimport type { SyncedToolSchema, ToolConnectionMetadata, ToolWithSource, ThreadManagerAgent, ThreadManagerState } from '@mcp-b/shared-types'\nimport type { useAgent } from 'agents/react'\n\nimport { stableStringify } from './thread-runtime-utils'\n\n/**\n * Options for useToolSourceRegistration hook.\n */\nexport interface UseToolSourceRegistrationOptions {\n\t/**\n\t * ThreadManager agent connection.\n\t */\n\tmanager: ReturnType<typeof useAgent<ThreadManagerAgent, ThreadManagerState>>\n\n\t/**\n\t * MCP tools to register with ThreadManager.\n\t */\n\ttools: ToolWithSource[]\n\n\t/**\n\t * Page metadata for tool source identification.\n\t */\n\tmetadata: ToolConnectionMetadata | undefined\n}\n\n/**\n * Hook that registers local MCP tools with ThreadManager.\n *\n * When tools are registered:\n * - Other sites can discover these tools via ThreadManager\n * - Cross-app RPC can invoke tools from this site\n * - UI can display tool source information (site name, icon, URL)\n *\n * @param options - Configuration options\n */\nexport function useToolSourceRegistration(options: UseToolSourceRegistrationOptions): void {\n\tconst { manager, tools, metadata } = options\n\n\tconst toolsRef = useRef(tools)\n\ttoolsRef.current = tools\n\n\t// Create stable key for tools to detect changes\n\tconst localToolSchemasKey = useMemo(() => {\n\t\tif (!metadata?.tabId) return 'no-tab-id'\n\n\t\tconst schemas: SyncedToolSchema[] =\n\t\t\ttools.map((t) => ({\n\t\t\t\tname: t.name,\n\t\t\t\tdescription: t.description,\n\t\t\t\tinputSchema: t.inputSchema,\n\t\t\t\tannotations: t.annotations,\n\t\t\t}))\n\n\t\tschemas.sort((a, b) => a.name.localeCompare(b.name))\n\t\treturn stableStringify(schemas)\n\t}, [tools, metadata?.tabId])\n\n\t// Track last registered key to avoid duplicate logs\n\tconst lastRegisteredKeyRef = useRef<string | null>(null)\n\n\t// Register tools with ThreadManager\n\tuseEffect(() => {\n\t\t// Only log if key changed to reduce noise\n\t\tif (localToolSchemasKey !== lastRegisteredKeyRef.current) {\n\t\t\tconsole.debug('[useToolSourceRegistration] Effect triggered', {\n\t\t\t\treadyState: manager.readyState,\n\t\t\t\thasMetadata: !!metadata,\n\t\t\t\ttoolCount: toolsRef.current.length,\n\t\t\t\tkeyChanged: lastRegisteredKeyRef.current !== localToolSchemasKey,\n\t\t\t})\n\t\t}\n\n\t\tif (manager.readyState !== WebSocket.OPEN) {\n\t\t\treturn\n\t\t}\n\n\t\tconst registerTools = async () => {\n\t\t\ttry {\n\t\t\t\tif (!metadata) {\n\t\t\t\t\tconsole.warn('[useToolSourceRegistration] Missing tab metadata; skipping tool registration.')\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst localTools = toolsRef.current\n\t\t\t\tconst toolSchemas: SyncedToolSchema[] = localTools.map((t) => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinputSchema: t.inputSchema,\n\t\t\t\t\tannotations: t.annotations,\n\t\t\t\t}))\n\n\t\t\t\tconsole.debug('[useToolSourceRegistration] Registering tools with ThreadManager', {\n\t\t\t\t\ttoolCount: toolSchemas.length,\n\t\t\t\t\ttoolNames: toolSchemas.map((t) => t.name),\n\t\t\t\t})\n\n\t\t\t\tif (toolSchemas.length > 0) {\n\t\t\t\t\tawait manager.stub.registerTools({ tools: toolSchemas, metadata })\n\t\t\t\t\tlastRegisteredKeyRef.current = localToolSchemasKey\n\t\t\t\t\tconsole.debug('[useToolSourceRegistration] Successfully registered tools')\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[useToolSourceRegistration] Tool registration error:', error)\n\t\t\t}\n\t\t}\n\n\t\tregisterTools()\n\t}, [manager, manager.readyState, localToolSchemasKey, metadata])\n}\n","/**\n * useCloudflareThreadAdapter\n *\n * Connects to the ThreadManager Durable Object, initializes context, syncs thread state,\n * and exposes an assistant-ui `ExternalStoreThreadListAdapter` for thread list primitives.\n *\n * IMPORTANT: This hook expects authentication to be already resolved by TicketExchangeGate.\n * It no longer handles ticket exchange internally - that's done before this hook runs.\n */\n\nimport type { ExternalStoreThreadListAdapter } from '@assistant-ui/react'\nimport { useAgent } from 'agents/react'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type {\n\tCreateThreadParams,\n\tInitContextResult,\n\tPolicyEvent,\n\tPolicyPluginStatus,\n\tSiteToHubMessage,\n\tThreadManagerAgent,\n\tThreadManagerState,\n\tThreadSummary,\n\tThreadUpdateParams,\n\tThreadWithDeleted,\n\tToolSourceInfo,\n\tToolWithSource,\n} from '@mcp-b/shared-types'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\n\nimport type { AuthError } from '../utils/auth-errors'\nimport { throwInitError } from '../utils/convert-init-error'\nimport {\n\tgetEmbeddedAgentTabId,\n\tsafeParseHubToSiteMessage,\n\tsafeParsePolicyEventMessage,\n\tsafeParseToolSourcesMessage,\n\tstableStringify,\n\tuseLatest,\n} from './thread-runtime-utils'\nimport { useToolSourceMetadata } from './useToolSourceMetadata'\nimport { useToolSourceRegistration } from './useToolSourceRegistration'\n\nimport type { ResolvedAuth } from '../providers/TicketExchangeGate'\n\n// Re-export TicketAuth for consumers\nexport type { TicketAuth } from '@char-ai/auth'\n\n/** localStorage key for anonymous session ID persistence */\nconst ANONYMOUS_SESSION_KEY = 'webmcp-anonymous-session-id'\n\n/**\n * Get or create a stable anonymous session ID.\n * Persisted in localStorage so the same DO is used across page refreshes.\n */\nfunction getOrCreateAnonymousId(): string {\n\tif (typeof window === 'undefined') {\n\t\treturn `anon-${crypto.randomUUID()}`\n\t}\n\n\ttry {\n\t\tlet sessionId = localStorage.getItem(ANONYMOUS_SESSION_KEY)\n\t\tif (!sessionId) {\n\t\t\tsessionId = `anon-${crypto.randomUUID()}`\n\t\t\tlocalStorage.setItem(ANONYMOUS_SESSION_KEY, sessionId)\n\t\t}\n\t\treturn sessionId\n\t} catch (error) {\n\t\t// localStorage unavailable (private browsing, etc.) - session won't persist across refreshes\n\t\tconsole.warn('[WebMCP] localStorage unavailable - anonymous session will not persist across refreshes', {\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t})\n\t\treturn `anon-${crypto.randomUUID()}`\n\t}\n}\n\n/**\n * Options for the useCloudflareThreadAdapter hook.\n */\nexport interface UseCloudflareThreadAdapterOptions {\n\t/**\n\t * The host for the Cloudflare Agent WebSocket connection.\n\t * @default 'localhost:8787'\n\t */\n\thost?: string\n\n\t/**\n\t * Resolved authentication from TicketExchangeGate.\n\t * Contains either authenticated mode (with ticketAuth) or anonymous mode (with anthropicApiKey).\n\t *\n\t * This replaces the individual authToken, clientId, ticketAuth, and anthropicApiKey props.\n\t * Authentication is resolved by TicketExchangeGate BEFORE this hook is called.\n\t */\n\tresolvedAuth: ResolvedAuth\n\n\t/**\n\t * MCP tools to register with ThreadManager.\n\t * These tools will be available for cross-app RPC.\n\t */\n\tmcpTools?: ToolWithSource[]\n\n\t/**\n\t * Function to execute MCP tools locally.\n\t */\n\texecuteMCPTool?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t) => Promise<CallToolResult>\n}\n\n/**\n * Result from useCloudflareThreadAdapter.\n */\nexport interface UseCloudflareThreadAdapterResult {\n\t/**\n\t * Current selected thread ID.\n\t */\n\tcurrentThreadId: string | undefined\n\n\t/**\n\t * Set the current selected thread ID.\n\t */\n\tsetCurrentThreadId: (threadId: string | undefined) => void\n\n\t/**\n\t * assistant-ui adapter for thread list primitives.\n\t */\n\tthreadListAdapter: ExternalStoreThreadListAdapter\n\n\t/**\n\t * Whether initContext() has completed successfully.\n\t */\n\tisInitialized: boolean\n\n\t/**\n\t * Whether the WebSocket is currently connected.\n\t */\n\tisConnected: boolean\n\n\t/**\n\t * Whether the thread list has synced at least once and initContext is ready.\n\t */\n\tisReady: boolean\n\n\t/**\n\t * The internal end_users.id resolved from initContext().\n\t */\n\tendUserId: string | null\n\n\t/**\n\t * Organization ID resolved from initContext.\n\t * SSO-First: Org-level only (no site concept).\n\t */\n\torganizationId: string | null\n\n\t/**\n\t * The ThreadManager agent connection (for tool registration, etc.).\n\t */\n\tmanager: ReturnType<typeof useAgent<ThreadManagerAgent, ThreadManagerState>>\n\n\t/**\n\t * Available tool sources from ThreadManager.\n\t * Used for cross-app RPC tool routing.\n\t */\n\ttoolSources: ToolSourceInfo[]\n\n\t/**\n\t * Policy plugin runtime status from ThreadManager.\n\t */\n\tpolicyPluginStatus: PolicyPluginStatus\n\n\t/**\n\t * Recent policy decision events (newest first).\n\t */\n\tpolicyEvents: PolicyEvent[]\n\n\t/**\n\t * Clear in-memory policy events on the client.\n\t */\n\tclearPolicyEvents: () => void\n\n\t/**\n\t * Authentication error from initContext (if failed).\n\t * Used to display error UI when IDP token validation fails.\n\t */\n\tauthError: AuthError | null\n}\n\nfunction sortThreadsByRecency<\n\tT extends { lastMessageAt: number | null; createdAt: number },\n>(list: readonly T[]): T[] {\n\treturn [...list].sort((a, b) => {\n\t\tconst aTime = a.lastMessageAt ?? a.createdAt\n\t\tconst bTime = b.lastMessageAt ?? b.createdAt\n\t\treturn bTime - aTime\n\t})\n}\n\nfunction isRegularThread(thread: ThreadSummary): thread is ThreadSummary & { status: 'regular' } {\n\treturn thread.status === 'regular'\n}\n\nfunction isArchivedThread(\n\tthread: ThreadSummary,\n): thread is ThreadSummary & { status: 'archived' } {\n\treturn thread.status === 'archived'\n}\n\n/**\n * Hook that manages thread list state and syncs with ThreadManager DO.\n *\n * ## Simplified Authentication (Post-TicketExchangeGate)\n *\n * Authentication is now resolved by TicketExchangeGate BEFORE this hook runs.\n * This hook receives resolvedAuth which contains either:\n * - Authenticated mode: ticketAuth with userId, orgId, and ticket\n * - Anonymous mode: anthropicApiKey for localhost dev\n *\n * Benefits:\n * - No ticket exchange logic here (moved to TicketExchangeGate)\n * - No two-phase DO naming (org:user known upfront from ticket)\n * - Simpler initialization flow\n * - No race conditions with cached DO state\n */\nexport function useCloudflareThreadAdapter(\n\toptions: UseCloudflareThreadAdapterOptions,\n): UseCloudflareThreadAdapterResult {\n\tconst {\n\t\thost,\n\t\tresolvedAuth,\n\t\tmcpTools,\n\t\texecuteMCPTool,\n\t} = options\n\n\t// Extract auth info from resolvedAuth\n\tconst isAnonymous = resolvedAuth.mode === 'anonymous'\n\tconst ticketAuth = resolvedAuth.ticketAuth\n\tconst anthropicApiKey = resolvedAuth.anthropicApiKey\n\n\t// Compute user ID and org ID from resolved auth\n\t// Since auth is already resolved, we know userId and orgId upfront\n\tconst effectiveUserId = useMemo(() => {\n\t\tif (ticketAuth) {\n\t\t\t// Authenticated mode: org:user composite name (known upfront from ticket)\n\t\t\treturn `${ticketAuth.orgId}:${ticketAuth.userId}`\n\t\t}\n\t\t// Anonymous mode: localStorage-backed session ID\n\t\treturn getOrCreateAnonymousId()\n\t}, [ticketAuth])\n\n\tconst [isInitialized, setIsInitialized] = useState(false)\n\tconst [initialSyncComplete, setInitialSyncComplete] = useState(false)\n\tconst [endUserId, setEndUserId] = useState<string | null>(null)\n\tconst [organizationId, setOrganizationId] = useState<string | null>(ticketAuth?.orgId ?? null)\n\tconst [authError, setAuthError] = useState<AuthError | null>(null)\n\tconst [threads, setThreads] = useState<ThreadWithDeleted[]>([])\n\t// Single source of truth: thread selection comes from DO state\n\t// No local currentThreadId - derive from lastSelectedThreadId\n\tconst [lastSelectedThreadId, setLastSelectedThreadId] = useState<string | null>(null)\n\n\tconst initPromiseRef = useRef<Promise<InitContextResult> | null>(null)\n\tconst initAttemptedRef = useRef(false)\n\tconst autoCreateAttemptedRef = useRef(false)\n\n\t// Track component mount state to prevent state updates after unmount\n\tconst isMountedRef = useRef(true)\n\tuseEffect(() => {\n\t\tisMountedRef.current = true\n\t\treturn () => {\n\t\t\tisMountedRef.current = false\n\t\t}\n\t}, [])\n\n\t// Connect to ThreadManager DO (one per user, or org:user for authenticated)\n\t// - Authenticated: keyed by org:userId (from ticket) - known upfront!\n\t// - Anonymous: keyed by localStorage session ID\n\t//\n\t// SECURITY: Token is NOT passed in URL query string to prevent leakage.\n\t// Authentication happens via initContextWithTicket (RPC) using the already-obtained ticket.\n\tconst manager = useAgent<ThreadManagerAgent, ThreadManagerState>({\n\t\tagent: 'ThreadManager',\n\t\tname: effectiveUserId,\n\t\thost,\n\t\t// SECURITY: Do NOT pass auth_token in query string - it gets logged in URLs\n\t\t// Anonymous mode only passes a flag (no sensitive data)\n\t\t// Authenticated mode: uses tickets obtained via TicketExchangeGate\n\t\tquery: isAnonymous ? { anonymous: 'true' } : undefined,\n\t\tonStateUpdate: (state, source) => {\n\t\t\t// Always use server data directly\n\t\t\tsetThreads(state.threads)\n\t\t\t// Track DO-persisted selection\n\t\t\tif (state.lastSelectedThreadId !== undefined) {\n\t\t\t\tsetLastSelectedThreadId(state.lastSelectedThreadId)\n\t\t\t}\n\t\t\t// Detect initialization from server state (Agents SDK syncs on connect)\n\t\t\t// CRITICAL: Only trust cached state for ANONYMOUS mode.\n\t\t\t// For authenticated mode, we MUST validate the ticket first via ensureInitialized().\n\t\t\t// Otherwise, a user could connect to a DO with cached state from a different user's session.\n\t\t\tif (source === 'server' && state.endUserId && state.organizationId && isAnonymous) {\n\t\t\t\t// Validate server state before trusting it\n\t\t\t\tif (typeof state.endUserId !== 'string' || state.endUserId.trim() === '') {\n\t\t\t\t\tconsole.error('[useCloudflareThreadAdapter] Invalid endUserId from server:', state.endUserId)\n\t\t\t\t\tsetAuthError({\n\t\t\t\t\t\tcode: 'INTERNAL_ERROR',\n\t\t\t\t\t\ttitle: 'Invalid Server Response',\n\t\t\t\t\t\tmessage: 'The server returned an invalid user identifier. Please refresh the page.',\n\t\t\t\t\t\tdebugInfo: `Invalid endUserId: ${JSON.stringify(state.endUserId)}`,\n\t\t\t\t\t\trecoverable: true,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (typeof state.organizationId !== 'string' || state.organizationId.trim() === '') {\n\t\t\t\t\tconsole.error('[useCloudflareThreadAdapter] Invalid organizationId from server:', state.organizationId)\n\t\t\t\t\tsetAuthError({\n\t\t\t\t\t\tcode: 'INTERNAL_ERROR',\n\t\t\t\t\t\ttitle: 'Invalid Server Response',\n\t\t\t\t\t\tmessage: 'The server returned an invalid organization identifier. Please refresh the page.',\n\t\t\t\t\t\tdebugInfo: `Invalid organizationId: ${JSON.stringify(state.organizationId)}`,\n\t\t\t\t\t\trecoverable: true,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tsetEndUserId(state.endUserId)\n\t\t\t\tsetOrganizationId(state.organizationId)\n\t\t\t\tsetIsInitialized(true)\n\t\t\t}\n\t\t\tif (source === 'server') setInitialSyncComplete(true)\n\t\t},\n\t})\n\n\t// Get unique ID for this embedded agent instance\n\t// Generated at module load time - lives in memory only\n\tconst tabId = getEmbeddedAgentTabId()\n\n\t// Track tool sources from ThreadManager\n\tconst [toolSources, setToolSources] = useState<ToolSourceInfo[]>([])\n\tconst [policyEvents, setPolicyEvents] = useState<PolicyEvent[]>([])\n\tconst [policyPluginStatus, setPolicyPluginStatus] = useState<PolicyPluginStatus>({\n\t\tenabled: false,\n\t\tname: 'policy-langguard.ai',\n\t})\n\n\tuseEffect(() => {\n\t\tconst handleMessage = (event: MessageEvent) => {\n\t\t\tconst toolSourcesMessage = safeParseToolSourcesMessage(event.data)\n\t\t\tif (toolSourcesMessage) {\n\t\t\t\tsetToolSources((prev) =>\n\t\t\t\t\tstableStringify(prev) === stableStringify(toolSourcesMessage.sources)\n\t\t\t\t\t\t? prev\n\t\t\t\t\t\t: toolSourcesMessage.sources,\n\t\t\t\t)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst policyEventMessage = safeParsePolicyEventMessage(event.data)\n\t\t\tif (!policyEventMessage) return\n\n\t\t\tsetPolicyEvents((prev) => [policyEventMessage.event, ...prev].slice(0, 25))\n\t\t}\n\t\tmanager.addEventListener('message', handleMessage)\n\t\treturn () => manager.removeEventListener('message', handleMessage)\n\t}, [manager])\n\n\t// Load policy plugin status after connection opens.\n\tuseEffect(() => {\n\t\tif (manager.readyState !== WebSocket.OPEN) return\n\n\t\tmanager.stub.getPolicyPluginStatus()\n\t\t\t.then((status) => {\n\t\t\t\tsetPolicyPluginStatus(status)\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tconsole.warn('[useCloudflareThreadAdapter] Failed to get policy plugin status:', error)\n\t\t\t})\n\t}, [manager, manager.readyState])\n\n\t// Track page metadata for tool source identification\n\tconst { metadata } = useToolSourceMetadata({\n\t\tenabled: manager.readyState === WebSocket.OPEN && isInitialized,\n\t})\n\n\t// Register local tools with ThreadManager\n\tuseToolSourceRegistration({\n\t\tmanager,\n\t\ttools: mcpTools ?? [],\n\t\tmetadata,\n\t})\n\n\t// Widget-level tool invocation handler\n\tuseEffect(() => {\n\t\tif (!executeMCPTool) return\n\t\tif (!tabId) return\n\n\t\tconst handleMessage = async (event: MessageEvent) => {\n\t\t\tconst msg = safeParseHubToSiteMessage(event.data)\n\t\t\tif (!msg) return\n\n\t\t\tif (msg.type === 'invoke') {\n\t\t\t\t// Server already targeted us - just execute\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await executeMCPTool(msg.toolName, msg.args ?? {})\n\t\t\t\t\tconst response: SiteToHubMessage = {\n\t\t\t\t\t\ttype: 'result',\n\t\t\t\t\t\tcallId: msg.callId,\n\t\t\t\t\t\tresult,\n\t\t\t\t\t}\n\t\t\t\t\tmanager.send(JSON.stringify(response))\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst response: SiteToHubMessage = {\n\t\t\t\t\t\ttype: 'result',\n\t\t\t\t\t\tcallId: msg.callId,\n\t\t\t\t\t\tresult: {\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\t\ttext: error instanceof Error ? error.message : 'Tool execution failed',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t\tmanager.send(JSON.stringify(response))\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (msg.type === 'ping') {\n\t\t\t\tconst response: SiteToHubMessage = { type: 'pong' }\n\t\t\t\tmanager.send(JSON.stringify(response))\n\t\t\t}\n\t\t}\n\n\t\tmanager.addEventListener('message', handleMessage)\n\t\treturn () => manager.removeEventListener('message', handleMessage)\n\t}, [executeMCPTool, tabId, manager])\n\n\t// Reset state when resolvedAuth changes (e.g., user logs out/in)\n\tconst prevTicketRef = useRef<string | undefined>(ticketAuth?.ticket)\n\tconst prevAnonymousKeyRef = useRef<string | undefined>(anthropicApiKey)\n\n\tuseEffect(() => {\n\t\tconst ticketChanged = ticketAuth?.ticket !== prevTicketRef.current\n\t\tconst keyChanged = anthropicApiKey !== prevAnonymousKeyRef.current\n\n\t\tif (!ticketChanged && !keyChanged) return\n\n\t\tprevTicketRef.current = ticketAuth?.ticket\n\t\tprevAnonymousKeyRef.current = anthropicApiKey\n\n\t\t// Reset initialization state for fresh auth\n\t\tinitPromiseRef.current = null\n\t\tinitAttemptedRef.current = false\n\t\tautoCreateAttemptedRef.current = false\n\t\tsetIsInitialized(false)\n\t\tsetInitialSyncComplete(false)\n\t\tsetEndUserId(null)\n\t\tsetOrganizationId(ticketAuth?.orgId ?? null)\n\t\tsetAuthError(null)\n\t\t// Don't clear threads - server state will be synced via onStateUpdate\n\t\tsetLastSelectedThreadId(null)\n\t\tsetPolicyEvents([])\n\t}, [ticketAuth?.ticket, ticketAuth?.orgId, anthropicApiKey])\n\n\t// If the ThreadManager connection drops, force initContext() again on the next reconnect.\n\t// Durable Objects and WebSocket sessions can restart independently of client state.\n\tuseEffect(() => {\n\t\tif (manager.readyState === WebSocket.OPEN) return\n\n\t\t// Log state reset for debugging connection lifecycle\n\t\tconsole.debug('[useCloudflareThreadAdapter] Connection not open, resetting initialization state', {\n\t\t\treadyState: manager.readyState,\n\t\t})\n\n\t\tinitPromiseRef.current = null\n\t\tinitAttemptedRef.current = false\n\t\tsetIsInitialized(false)\n\t\tsetInitialSyncComplete(false)\n\t}, [manager.readyState])\n\n\tconst ensureInitialized = useCallback(async (): Promise<void> => {\n\t\tif (manager.readyState !== WebSocket.OPEN) {\n\t\t\tthrow new Error('ThreadManager is not connected')\n\t\t}\n\n\t\tconst origin = typeof window !== 'undefined' ? window.location.origin : undefined\n\n\t\t// Initialize context via WebSocket RPC\n\t\t// Authentication is already resolved by TicketExchangeGate - no ticket exchange here!\n\t\tif (!initPromiseRef.current) {\n\t\t\tif (isAnonymous) {\n\t\t\t\t// Anonymous mode: localhost dev, user-provided API key\n\t\t\t\tinitPromiseRef.current = manager.stub.initContextAnonymous({ origin, anthropicApiKey })\n\t\t\t} else if (ticketAuth) {\n\t\t\t\t// Authenticated mode: ticket was already obtained by TicketExchangeGate\n\t\t\t\t// Just validate it with the ThreadManager DO\n\t\t\t\tinitPromiseRef.current = manager.stub.initContextWithTicket({\n\t\t\t\t\tticket: ticketAuth.ticket,\n\t\t\t\t\torigin,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\t// This shouldn't happen if TicketExchangeGate did its job\n\t\t\t\tthrow new Error('No authentication method available')\n\t\t\t}\n\t\t}\n\n\t\tconst initResult = await initPromiseRef.current\n\t\tif (!initResult) return\n\n\t\t// Prevent state updates if component unmounted during async init\n\t\tif (!isMountedRef.current) return\n\n\t\tif (!initResult.success) {\n\t\t\tthrowInitError(initResult)\n\t\t}\n\n\t\tsetEndUserId(initResult.endUserId)\n\t\tif (initResult.organizationId) setOrganizationId(initResult.organizationId)\n\t\tsetIsInitialized(true)\n\t}, [manager, ticketAuth, anthropicApiKey, isAnonymous])\n\n\t// Initialize context when WebSocket connects\n\t// Uses ref pattern to prevent infinite loops from ensureInitialized recreation\n\tuseEffect(() => {\n\t\t// Only attempt once per connection cycle (prevents infinite loop)\n\t\tif (initAttemptedRef.current) return\n\t\tif (manager.readyState !== WebSocket.OPEN) return\n\t\tif (isInitialized) return\n\t\tif (authError) return // Don't retry if we already have an error\n\n\t\tinitAttemptedRef.current = true\n\n\t\tensureInitialized().catch((error) => {\n\t\t\tconsole.error('[useCloudflareThreadAdapter] initContext error:', error)\n\t\t\t// If it's an AuthErrorException, extract the error details\n\t\t\tif (error && typeof error === 'object' && 'code' in error && 'title' in error) {\n\t\t\t\tsetAuthError(error as AuthError)\n\t\t\t} else {\n\t\t\t\t// Convert unknown errors to a user-visible error state\n\t\t\t\t// This prevents the UI from appearing \"stuck\" on non-auth errors\n\t\t\t\tsetAuthError({\n\t\t\t\t\tcode: 'INTERNAL_ERROR',\n\t\t\t\t\ttitle: 'Connection Error',\n\t\t\t\t\tmessage: error instanceof Error ? error.message : 'Failed to initialize. Please try again.',\n\t\t\t\t\trecoverable: true,\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: ensureInitialized recreates when state changes; this effect intentionally gates by connection flags to avoid loops.\n\t\t}, [manager.readyState, isInitialized, authError])\n\n\t// Memoize thread lists - only recompute when threads array changes\n\tconst activeThreads = useMemo(() => {\n\t\tconst nonDeleted = threads.filter((t): t is ThreadSummary => t.status !== 'deleted')\n\t\treturn sortThreadsByRecency(nonDeleted.filter(isRegularThread))\n\t}, [threads])\n\n\tconst archivedThreads = useMemo(() => {\n\t\tconst nonDeleted = threads.filter((t): t is ThreadSummary => t.status !== 'deleted')\n\t\treturn sortThreadsByRecency(nonDeleted.filter(isArchivedThread))\n\t}, [threads])\n\n\n\t// Derive currentThreadId from DO state (single source of truth)\n\t// Selection policy:\n\t// - Use DO-persisted selection if it's still in active threads\n\t// - Otherwise fall back to most recent active thread\n\t// - Do NOT auto-select archived threads\n\tconst currentThreadId = useMemo(() => {\n\t\tif (lastSelectedThreadId && activeThreads.some((t) => t.id === lastSelectedThreadId)) {\n\t\t\treturn lastSelectedThreadId\n\t\t}\n\t\treturn activeThreads[0]?.id\n\t}, [lastSelectedThreadId, activeThreads])\n\n\tconst isConnected = manager.readyState === WebSocket.OPEN\n\tconst isReady = isConnected && isInitialized && initialSyncComplete\n\t// Show threads if we have them, even if not fully initialized yet\n\t// This prevents flashing empty state when we already have data from server\n\tconst isLoading = !isReady && activeThreads.length === 0\n\n\t// Stable refs for values used in callbacks (per Vercel best practices: advanced-use-latest)\n\tconst managerRef = useLatest(manager)\n\tconst ensureInitializedRef = useLatest(ensureInitialized)\n\tconst organizationIdRef = useLatest(organizationId)\n\tconst activeThreadsRef = useLatest(activeThreads)\n\tconst currentThreadIdRef = useLatest(currentThreadId)\n\n\t// Stable callback: fire-and-forget to DO, let onStateUpdate sync back\n\tconst setCurrentThreadId = useCallback((threadId: string | undefined) => {\n\t\tif (!threadId) return\n\t\tmanagerRef.current.stub.setLastSelectedThread(threadId).catch((error) => {\n\t\t\tconsole.warn('[WebMCP] Could not persist thread selection to DO:', error)\n\t\t})\n\t}, [managerRef])\n\n\t// Stable callback for thread creation\n\tconst createThread = useCallback(async (): Promise<string> => {\n\t\tawait ensureInitializedRef.current()\n\n\t\tconst params = {\n\t\t\t...(organizationIdRef.current ? { organizationId: organizationIdRef.current } : {}),\n\t\t} satisfies CreateThreadParams\n\n\t\tconst result = await managerRef.current.stub.createThread(params)\n\t\t// Thread will be selected via onStateUpdate when DO broadcasts the new thread\n\t\treturn result.threadId\n\t}, [ensureInitializedRef, organizationIdRef, managerRef])\n\n\t// Auto-create initial thread for new users\n\t// This ensures every user always has at least one active thread,\n\t// preventing \"Cannot send message: No active thread\" errors on first load\n\tuseEffect(() => {\n\t\t// Only attempt once per component lifecycle\n\t\tif (autoCreateAttemptedRef.current) return\n\n\t\t// Wait for full initialization\n\t\tif (!isInitialized) return\n\t\tif (!initialSyncComplete) return\n\n\t\t// Only create if user has no active threads\n\t\tif (activeThreads.length > 0) return\n\n\t\t// Mark as attempted to prevent duplicate attempts\n\t\tautoCreateAttemptedRef.current = true\n\n\t\tconsole.info('[useCloudflareThreadAdapter] Auto-creating initial thread for new user')\n\n\t\tcreateThread().catch((error) => {\n\t\t\tconsole.error('[useCloudflareThreadAdapter] Failed to auto-create initial thread:', error)\n\t\t\t// Don't block UI - user can manually create via thread list\n\t\t})\n\t}, [isInitialized, initialSyncComplete, activeThreads.length, createThread])\n\n\t// Stable callback for rename\n\tconst onRename = useCallback(async (threadId: string, newTitle: string) => {\n\t\tawait ensureInitializedRef.current()\n\t\tawait managerRef.current.stub.updateThread(\n\t\t\tthreadId,\n\t\t\t{ title: newTitle } satisfies ThreadUpdateParams,\n\t\t)\n\t}, [ensureInitializedRef, managerRef])\n\n\t// Stable callback for archive\n\tconst onArchive = useCallback(async (threadId: string) => {\n\t\tawait ensureInitializedRef.current()\n\t\tawait managerRef.current.stub.archiveThread(threadId)\n\t\t// If archiving current thread, select next active or create new\n\t\tif (threadId === currentThreadIdRef.current) {\n\t\t\tconst nextActive = activeThreadsRef.current.filter((t) => t.id !== threadId)[0]?.id\n\t\t\tif (nextActive) {\n\t\t\t\tmanagerRef.current.stub.setLastSelectedThread(nextActive).catch((error) => {\n\t\t\t\t\tconsole.warn('[WebMCP] Failed to update thread selection after archive:', error)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\t// If the user archived their last active thread, create a new one\n\t\t\t\t// createThread will trigger onStateUpdate which updates selection\n\t\t\t\tawait createThread()\n\t\t\t}\n\t\t}\n\t}, [ensureInitializedRef, managerRef, currentThreadIdRef, activeThreadsRef, createThread])\n\n\t// Stable callback for unarchive\n\tconst onUnarchive = useCallback(async (threadId: string) => {\n\t\tawait ensureInitializedRef.current()\n\t\tawait managerRef.current.stub.restoreThread(threadId)\n\t}, [ensureInitializedRef, managerRef])\n\n\t// Stable callback for delete\n\tconst onDelete = useCallback(async (threadId: string) => {\n\t\tawait ensureInitializedRef.current()\n\t\tawait managerRef.current.stub.deleteThread(threadId)\n\t\t// If deleting current thread, select next active\n\t\tif (threadId === currentThreadIdRef.current) {\n\t\t\tconst nextActive = activeThreadsRef.current.filter((t) => t.id !== threadId)[0]?.id\n\t\t\tif (nextActive) {\n\t\t\t\tmanagerRef.current.stub.setLastSelectedThread(nextActive).catch((error) => {\n\t\t\t\t\tconsole.warn('[WebMCP] Failed to update thread selection after delete:', error)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}, [ensureInitializedRef, managerRef, currentThreadIdRef, activeThreadsRef])\n\n\t// Stable wrapper for onSwitchToNewThread (assistant-ui expects void return)\n\tconst onSwitchToNewThread = useCallback(async () => {\n\t\tawait createThread()\n\t}, [createThread])\n\n\t// Memoize threadListAdapter - only changes when data or stable callbacks change\n\tconst threadListAdapter = useMemo<ExternalStoreThreadListAdapter>(() => ({\n\t\tthreadId: currentThreadId,\n\t\tisLoading,\n\t\tthreads: activeThreads,\n\t\tarchivedThreads,\n\t\tonSwitchToNewThread,\n\t\tonSwitchToThread: setCurrentThreadId,\n\t\tonRename,\n\t\tonArchive,\n\t\tonUnarchive,\n\t\tonDelete,\n\t}), [\n\t\tcurrentThreadId,\n\t\tisLoading,\n\t\tactiveThreads,\n\t\tarchivedThreads,\n\t\tonSwitchToNewThread,\n\t\tsetCurrentThreadId,\n\t\tonRename,\n\t\tonArchive,\n\t\tonUnarchive,\n\t\tonDelete,\n\t])\n\n\tconst clearPolicyEvents = useCallback(() => {\n\t\tsetPolicyEvents([])\n\t}, [])\n\n\treturn {\n\t\tcurrentThreadId,\n\t\tsetCurrentThreadId,\n\t\tthreadListAdapter,\n\t\tisInitialized,\n\t\tisConnected,\n\t\tisReady,\n\t\tendUserId,\n\t\torganizationId,\n\t\tauthError,\n\t\tmanager,\n\t\ttoolSources,\n\t\tpolicyPluginStatus,\n\t\tpolicyEvents,\n\t\tclearPolicyEvents,\n\t}\n}\n","import { z } from 'zod';\n// Thread status enum\nexport const ThreadStatusSchema = z.enum(['regular', 'archived']);\n// Thread summary (matches assistant-ui ExternalStoreThreadData)\nexport const ThreadSummarySchema = z.object({\n id: z.string(),\n status: ThreadStatusSchema,\n title: z.string().optional(),\n remoteId: z.string().optional(),\n externalId: z.string().optional(),\n organizationId: z.string(),\n messageCount: z.number(),\n totalTokens: z.number().optional(),\n lastMessageAt: z.number().nullable(),\n createdAt: z.number(),\n});\n// Thread with deleted status (for soft-delete)\nexport const ThreadWithDeletedSchema = z.union([\n ThreadSummarySchema,\n ThreadSummarySchema.omit({ status: true }).extend({\n status: z.literal('deleted'),\n }),\n]);\n// Thread metadata (stored in ThreadAgent DO)\nexport const ThreadMetadataSchema = z.object({\n threadId: z.string(),\n userId: z.string(),\n threadManagerName: z.string().optional(),\n organizationId: z.string(),\n title: z.string().nullable(),\n createdAt: z.number(),\n});\n// RPC params/results\nexport const CreateThreadParamsSchema = z.object({\n title: z.string().optional(),\n organizationId: z.string().optional(),\n});\nexport const CreateThreadResultSchema = z.object({\n threadId: z.string(),\n});\nexport const ThreadUpdateParamsSchema = z.object({\n title: z.string().optional(),\n messageCount: z.number().optional(),\n totalTokensDelta: z.number().optional(),\n lastMessageAt: z.number().optional(),\n});\n// Context resolved via initContext() RPC call\nexport const ThreadManagerContextSchema = z.object({\n endUserId: z.string(),\n organizationId: z.string(),\n externalId: z.string(),\n});\n","import { z } from 'zod';\nimport { ThreadWithDeletedSchema } from './thread';\n// ThreadManager state (synced to frontend via Agent SDK)\nexport const ThreadManagerStateSchema = z.object({\n threads: z.array(ThreadWithDeletedSchema),\n endUserId: z.string().nullable(),\n organizationId: z.string().nullable(),\n externalId: z.string().nullable(),\n isAnonymous: z.boolean().optional(),\n anthropicApiKey: z.string().optional(),\n lastSelectedThreadId: z.string().nullable().optional(),\n});\n","import { z } from 'zod';\n// Tool source selector for routing\nexport const ToolSourceSelectorSchema = z.object({\n sourceId: z.string(),\n tabId: z.string(),\n});\n// Tool source metadata\nexport const ToolSourceSchema = z.object({\n sourceId: z.string(),\n tabId: z.string(),\n origin: z.string().optional(),\n url: z.string().optional(),\n title: z.string().optional(),\n iconUrl: z.string().optional(),\n connectedAt: z.number(),\n lastSeenAt: z.number().optional(),\n});\n// Tool source info (for UI display)\nexport const ToolSourceInfoSchema = ToolSourceSchema.extend({\n toolCount: z.number(),\n});\n// Connection metadata (RPC param)\nexport const ToolConnectionMetadataSchema = z.object({\n origin: z.string().optional(),\n url: z.string().optional(),\n title: z.string().optional(),\n iconUrl: z.string().optional(),\n tabId: z.string(),\n});\n// Thread tool selection\nexport const ThreadToolSelectionSchema = z.object({\n selectedSources: z.array(ToolSourceSelectorSchema),\n});\n// Tool sources update message (broadcast)\nexport const ToolSourcesUpdateMessageSchema = z.object({\n type: z.literal('tool_sources'),\n sources: z.array(ToolSourceInfoSchema),\n});\n","import { z } from 'zod';\nexport const ToolApprovalModeSchema = z.enum(['auto', 'ask']);\nexport const ToolApprovalSettingsSchema = z.object({\n mode: ToolApprovalModeSchema,\n});\n","import { z } from 'zod';\nimport { ThreadMetadataSchema } from './thread.js';\nimport { ThreadToolSelectionSchema } from './tool-source.js';\nimport { ToolApprovalModeSchema } from './tool-approval.js';\n/**\n * Voice session state - synced across all connected clients.\n */\nexport const VoiceSessionStateSchema = z.object({\n /** Whether a voice session is active */\n isActive: z.boolean(),\n /** Whether microphone is muted */\n isMuted: z.boolean(),\n /** Unique session identifier (non-empty) */\n sessionId: z.string().min(1),\n /** Voice routing mode */\n routingMode: z.enum(['direct', 'realtimekit']).default('direct'),\n /** Human handoff status */\n handoffStatus: z.enum(['ai_only', 'handoff_pending', 'human_active']).default('ai_only'),\n /** RealtimeKit meeting ID for human handoff */\n realtimeKitMeetingId: z.string().optional(),\n /** RealtimeKit participant ID for the customer */\n realtimeKitCustomerParticipantId: z.string().optional(),\n /** RealtimeKit participant ID for the support agent */\n realtimeKitSupportParticipantId: z.string().optional(),\n});\n/**\n * State for ThreadAgent Durable Object.\n * Synced across all connected clients via Cloudflare Agents.\n */\nexport const ThreadAgentStateSchema = z.object({\n threadMetadata: ThreadMetadataSchema.nullable(),\n toolSelection: ThreadToolSelectionSchema.nullable(),\n /**\n * Tool approval mode - synced across all connected clients.\n * 'ask' = require approval for destructive tools\n * 'auto' = auto-execute all tools\n */\n approvalMode: ToolApprovalModeSchema,\n /**\n * Voice session state - synced across all connected clients.\n * null when no voice session is active.\n */\n voiceSession: VoiceSessionStateSchema.nullable(),\n /**\n * Whether this is an anonymous session (localhost dev mode).\n * Anonymous sessions use user-provided API key instead of org credentials.\n */\n isAnonymous: z.boolean().optional(),\n /**\n * Anthropic API key for anonymous mode.\n * Only set when isAnonymous=true.\n */\n anthropicApiKey: z.string().optional(),\n});\n","import { z } from 'zod';\nimport { ToolSourceSchema } from './tool-source';\n// Tool annotations (subset of MCP Tool annotations we care about)\nexport const ToolAnnotationsSchema = z\n .object({\n title: z.string().optional(),\n readOnlyHint: z.boolean().optional(),\n destructiveHint: z.boolean().optional(),\n idempotentHint: z.boolean().optional(),\n openWorldHint: z.boolean().optional(),\n})\n .catchall(z.any()); // Allow additional fields from MCP spec\n// Synced tool schema (what we send to LLM / store in state)\nexport const SyncedToolSchemaSchema = z.object({\n name: z.string(),\n description: z.string().optional(),\n inputSchema: z.record(z.any()).optional(),\n annotations: ToolAnnotationsSchema.optional(),\n sources: z.array(ToolSourceSchema).optional(),\n});\n// Constant for tool source selector argument\nexport const TOOL_SOURCE_SELECTOR = '__sourceId';\n","import { z } from 'zod';\n// Policy decision status returned by the interceptor\nexport const PolicyDecisionStatusSchema = z.enum(['success', 'notify', 'failure']);\n// Violation payload returned by the interceptor\nexport const PolicyViolationSchema = z.object({\n policy_id: z.string(),\n status: z.enum(['notify', 'block']),\n details: z.string().optional(),\n});\n// Runtime status for policy plugin configuration\nexport const PolicyPluginStatusSchema = z.object({\n enabled: z.boolean(),\n name: z.string(),\n});\n// Event pushed from ThreadManager when a tool call is evaluated by policy\nexport const PolicyEventSchema = z.object({\n toolName: z.string(),\n callId: z.string(),\n status: PolicyDecisionStatusSchema,\n message: z.string(),\n violations: z.array(PolicyViolationSchema),\n latencyMs: z.number(),\n timestamp: z.number(),\n source: z.object({\n tabId: z.string().nullable().optional(),\n origin: z.string().nullable().optional(),\n url: z.string().nullable().optional(),\n title: z.string().nullable().optional(),\n }),\n});\n// Broadcast message for policy events\nexport const PolicyEventMessageSchema = z.object({\n type: z.literal('policy_event'),\n event: PolicyEventSchema,\n});\n","import { z } from 'zod';\nimport { PolicyDecisionStatusSchema, PolicyViolationSchema } from './policy-plugin.js';\n/**\n * Optional policy decision metadata attached to a tool call artifact.\n * This powers inline governance UI on the corresponding tool result card.\n */\nexport const ToolCallPolicyMetadataSchema = z.object({\n /** Policy plugin/integration display name */\n pluginName: z.string(),\n /** Policy decision status for this invocation */\n status: PolicyDecisionStatusSchema,\n /** Human-readable policy decision summary */\n message: z.string(),\n /** Detailed policy violations, if any */\n violations: z.array(PolicyViolationSchema),\n /** Policy interceptor latency in milliseconds */\n latencyMs: z.number().optional(),\n /** Timestamp when the policy decision was made (ms since epoch) */\n evaluatedAt: z.number().optional(),\n /** Interceptor call ID for correlation/debugging */\n callId: z.string().optional(),\n});\n/**\n * Metadata captured during tool execution.\n * Stored in the `artifact` field of tool-call message parts in assistant-ui.\n * This data persists in the thread and can be synced externally.\n */\nexport const ToolCallMetadataSchema = z.object({\n /** Timestamp when the tool call started (ms since epoch) */\n startedAt: z.number(),\n /** Duration of the tool call in milliseconds */\n duration: z.number(),\n /** Source ID of the MCP server that handled the call */\n sourceId: z.string(),\n /** Whether the tool call resulted in an error */\n isError: z.boolean().optional(),\n /** Whether the tool call was aborted (e.g., tool removed during execution) */\n wasAborted: z.boolean().optional(),\n /** Optional policy decision metadata from governance interceptor */\n policy: ToolCallPolicyMetadataSchema.optional(),\n});\n","import { z } from 'zod';\n// Hub to site message (backend -> browser tab)\nexport const HubToSiteMessageSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('invoke'),\n callId: z.string(),\n toolName: z.string(),\n args: z.record(z.unknown()).optional(),\n }),\n z.object({\n type: z.literal('ping'),\n }),\n]);\n// Site to hub message (browser tab -> backend)\n// Note: CallToolResult comes from @modelcontextprotocol/sdk - we use passthrough\nexport const SiteToHubMessageSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('result'),\n callId: z.string(),\n result: z\n .object({\n content: z.array(z.unknown()),\n isError: z.boolean().optional(),\n })\n .passthrough(), // CallToolResult shape, allow extra fields\n }),\n z.object({\n type: z.literal('pong'),\n }),\n]);\n","import { z } from 'zod';\n// Import error code constants and types from the single source of truth\nimport { AUTH_ERROR_CODE, } from '@char-ai/auth';\n/**\n * Zod schema for AuthErrorCode.\n * Built from the AUTH_ERROR_CODE constant to stay in sync with @char-ai/auth.\n */\nconst authErrorCodeValues = Object.values(AUTH_ERROR_CODE);\nexport const AuthErrorCodeSchema = z.enum(authErrorCodeValues);\n/**\n * Zod schema for ErrorCallToAction.\n * Validates the structure defined in @char-ai/auth.\n */\nexport const ErrorCallToActionSchema = z.object({\n steps: z.array(z.string()),\n examples: z.array(z.string()).optional(),\n});\n/**\n * Zod schema for ErrorContext.\n * Validates the structure defined in @char-ai/auth.\n * Uses passthrough to allow additional context properties.\n *\n * Note: We don't use `satisfies` here because Zod's passthrough produces\n * `unknown` for additional properties, while ErrorContext uses `string | undefined`.\n * The TypeScript type is re-exported from @char-ai/auth for type safety.\n */\nexport const ErrorContextSchema = z\n .object({\n issuer: z.string().optional(),\n configuredIssuer: z.string().optional(),\n currentDomain: z.string().optional(),\n allowedDomains: z.array(z.string()).optional(),\n expectedIssuer: z.string().optional(),\n actualIssuer: z.string().optional(),\n missingField: z.string().optional(),\n})\n .catchall(z.any());\n// Init context result (RPC return)\nexport const InitContextResultSchema = z.object({\n success: z.boolean(),\n endUserId: z.string(),\n organizationId: z.string().optional(),\n isAnonymous: z.boolean().optional(),\n hasOrgContext: z.boolean().optional(),\n message: z.string(),\n errorCode: AuthErrorCodeSchema.optional(),\n errorTitle: z.string().optional(),\n callToAction: ErrorCallToActionSchema.optional(),\n dashboardLink: z.string().optional(),\n docsLink: z.string().optional(),\n context: ErrorContextSchema.optional(),\n recoverable: z.boolean().optional(),\n debugInfo: z.string().optional(),\n});\n","import { z } from 'zod';\nexport const RealtimeKitJoinResultSchema = z.object({\n meetingId: z.string(),\n participantId: z.string(),\n authToken: z.string(),\n expiresAt: z.string().optional(),\n});\n","import { z } from 'zod';\n// Todo status\nexport const TodoStatusSchema = z.enum(['new', 'pending', 'in-progress', 'done']);\n// Todo item\nexport const TodoSchema = z.object({\n text: z.string(),\n status: TodoStatusSchema,\n});\n// Update todos input\nexport const UpdateTodosInputSchema = z.object({\n new: z.array(z.string()),\n inProgress: z.array(z.number()),\n done: z.array(z.number()),\n clearPreviouslyDone: z.boolean(),\n insertAt: z.number().optional(),\n});\n// Update todos result\nexport const UpdateTodosResultSchema = z.object({\n todos: z.array(TodoSchema),\n});\n// Ask for plan approval input\nexport const AskForPlanApprovalInputSchema = z.object({\n explainer: z.string(),\n});\n// Ask for plan approval result\nexport const AskForPlanApprovalResultSchema = z.object({\n todos: z.array(TodoSchema),\n approved: z.boolean(),\n});\n","import { z } from 'zod';\n/**\n * MCP Client Types\n *\n * Types for MCP client connections and tool management.\n * These extend/complement the MCP SDK types.\n */\n// =============================================================================\n// Connection States\n// =============================================================================\n/**\n * Simple connection state for MCP clients\n */\nexport const MCPClientStateSchema = z.enum(['idle', 'connecting', 'connected', 'error']);\n/**\n * Extended connection state for MCP clients with more granular states.\n * Useful for UI feedback during connection lifecycle.\n */\nexport const MCPConnectionStateSchema = z.enum([\n 'idle', // Not connected, no connection attempt\n 'discovering', // Checking server existence and capabilities\n 'connecting', // Establishing transport connection\n 'loading', // Connected, loading capabilities (tools, resources, prompts)\n 'ready', // Fully connected and operational\n 'error', // Connection or operation failed\n]);\n// =============================================================================\n// Source Configuration\n// =============================================================================\n/**\n * Configuration for tab-based MCP sources (same-tab or iframe)\n */\nexport const TabSourceConfigSchema = z.object({\n type: z.literal('tab'),\n /** Target origin for postMessage security (default: window.location.origin for same-tab) */\n targetOrigin: z.string().optional(),\n /** Channel ID for the TabClientTransport (default: 'mcp-default') */\n channelId: z.string().optional(),\n});\n/**\n * Configuration for HTTP-based MCP sources (remote servers)\n */\nexport const HttpSourceConfigSchema = z.object({\n type: z.literal('http'),\n /** Server URL */\n url: z.string(),\n /** Optional authentication token (Bearer) */\n authToken: z.string().optional(),\n /** Connection timeout in milliseconds (default: 30000) */\n timeout: z.number().optional(),\n /** Auto-reconnect on disconnect (default: true) */\n autoReconnect: z.boolean().optional(),\n /**\n * Transport type preference:\n * - 'auto': Try HTTP first, fallback to SSE (default)\n * - 'http': HTTP Streamable transport only\n * - 'sse': Server-Sent Events transport only\n */\n transportType: z.enum(['auto', 'http', 'sse']).optional(),\n /** Custom headers to include in requests */\n customHeaders: z.record(z.string()).optional(),\n});\n/**\n * Unified configuration for MCP sources\n */\nexport const MCPSourceConfigSchema = z.discriminatedUnion('type', [\n TabSourceConfigSchema,\n HttpSourceConfigSchema,\n]);\n// =============================================================================\n// Tool with Source\n// =============================================================================\n/**\n * Tool annotations schema (mirrors MCP SDK Tool.annotations)\n * Note: This is a more complete version for tools with source tracking\n */\nexport const ToolAnnotationsFullSchema = z\n .object({\n title: z.string().optional(),\n readOnlyHint: z.boolean().optional(),\n destructiveHint: z.boolean().optional(),\n idempotentHint: z.boolean().optional(),\n openWorldHint: z.boolean().optional(),\n})\n .passthrough();\n/**\n * Tool with source tracking for multi-source tool management.\n * The _sourceId identifies which client to route tool calls to.\n *\n * This extends the MCP SDK Tool interface shape.\n */\nexport const ToolWithSourceSchema = z.object({\n name: z.string(),\n description: z.string().optional(),\n inputSchema: z.record(z.unknown()).optional(),\n annotations: ToolAnnotationsFullSchema.optional(),\n /** Source identifier - 'local' for useWebMCP, 'remote' for remote MCP, or iframe/tab ID */\n _sourceId: z.string(),\n});\n// =============================================================================\n// MCP Source State\n// =============================================================================\n/**\n * State of an MCP source connection.\n *\n * Note: This schema uses z.unknown() for arrays of SDK types (Tool, Resource, etc.)\n * because we don't want to re-define those schemas here. Runtime validation\n * of these arrays should be done at the boundary where SDK types are received.\n */\nexport const MCPSourceSchema = z.object({\n /** Unique identifier for this source */\n id: z.string(),\n /** Configuration used to create this source */\n config: MCPSourceConfigSchema,\n /** Connection state */\n state: MCPClientStateSchema,\n /** Connection error message (if any) */\n error: z.string().nullable(),\n /** Tools available from this source */\n tools: z.array(z.unknown()),\n /** Resources available from this source */\n resources: z.array(z.unknown()),\n /** Resource templates available from this source */\n resourceTemplates: z.array(z.unknown()),\n /** Prompts available from this source */\n prompts: z.array(z.unknown()),\n});\n","/**\n * Determine whether a tool should be considered destructive.\n * Defaults to destructive when annotations are missing (MCP default).\n */\nexport function isToolDestructive(annotations) {\n if (!annotations)\n return true;\n if (annotations.readOnlyHint === true)\n return false;\n if (typeof annotations.destructiveHint === 'boolean')\n return annotations.destructiveHint;\n return true;\n}\n","import {\n\tunstable_createMessageConverter,\n\ttype useExternalMessageConverter,\n\ttype ReasoningMessagePart,\n\ttype ToolCallMessagePart,\n\ttype TextMessagePart,\n\ttype SourceMessagePart,\n} from '@assistant-ui/react'\nimport { getToolName, isToolUIPart } from 'ai'\nimport type { ToolCallMetadata } from '@mcp-b/shared-types'\n\nimport type { UIMessage } from 'ai'\n\n// Type for message parts from the AI SDK\ntype MessagePart = NonNullable<UIMessage['parts']>[number]\n\n// JSON object type for tool args\ntype JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue }\ntype JSONObject = { [key: string]: JSONValue }\n\n/**\n * Strips incomplete JSON closing delimiters for streaming args.\n * The AI SDK's fix-json adds these during streaming, but they're not final.\n */\nfunction stripClosingDelimiters(json: string) {\n\treturn json.replace(/[}\\]\"]+$/, '')\n}\n\nfunction getRawInput(part: unknown): string | null {\n\tconst rawInput = (part as { rawInput?: unknown } | null)?.rawInput\n\treturn typeof rawInput === 'string' && rawInput.length > 0 ? rawInput : null\n}\n\ntype ConvertedPart = TextMessagePart | ReasoningMessagePart | ToolCallMessagePart | SourceMessagePart\n\n/**\n * Converts message parts from Cloudflare Agents SDK format to Assistant UI format.\n *\n * Handles all tool states: input-streaming, input-available, approval-requested,\n * output-available, output-error. Adds status: { type: 'requires-action' } for\n * tools awaiting HITL approval.\n *\n * Uses a two-pass approach over the filtered parts array:\n * 1. Build a dedup map (last index per toolCallId) from the filtered array\n * 2. Convert each part, skipping earlier duplicates of the same tool call\n */\nconst convertParts = (\n\tmessage: UIMessage,\n\tmetadata: useExternalMessageConverter.Metadata\n): ConvertedPart[] => {\n\tif (!message.parts || message.parts.length === 0) {\n\t\treturn []\n\t}\n\n\t// Filter out non-renderable parts first, then build dedup map from the\n\t// same array. This ensures index comparisons use a consistent frame.\n\tconst parts = message.parts.filter(\n\t\t(p) => p.type !== 'step-start' && p.type !== 'file'\n\t)\n\n\t// When a tool call appears multiple times (e.g. streaming updates),\n\t// only the last occurrence should be rendered.\n\tconst toolCallLastIndex = new Map<string, number>()\n\tfor (let i = 0; i < parts.length; i++) {\n\t\tconst p = parts[i]\n\t\tif (isToolUIPart(p)) {\n\t\t\ttoolCallLastIndex.set(p.toolCallId, i)\n\t\t}\n\t}\n\n\t// Read toolStatuses from message metadata (server source) first, then converter metadata (local fallback)\n\t// Server metadata is the source of truth for HITL approval state\n\tconst messageMetadata = (message as UIMessage & { metadata?: { custom?: { toolStatuses?: Record<string, { type: string; payload?: unknown }> } } })?.metadata?.custom\n\tconst messageToolStatuses = messageMetadata?.toolStatuses\n\tconst converterMetadata = metadata as useExternalMessageConverter.Metadata & {\n\t\ttoolArtifacts?: Record<string, ToolCallMetadata>\n\t}\n\n\tconst result: ConvertedPart[] = []\n\n\tfor (let i = 0; i < parts.length; i++) {\n\t\tconst part = parts[i]\n\t\tconst type = part.type\n\n\t\tif (type === 'text') {\n\t\t\tresult.push({ type: 'text', text: part.text } satisfies TextMessagePart)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (type === 'reasoning') {\n\t\t\tresult.push({ type: 'reasoning', text: part.text } satisfies ReasoningMessagePart)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (isToolUIPart(part)) {\n\t\t\t// Skip earlier occurrences of the same tool call (keep last only)\n\t\t\tif (toolCallLastIndex.get(part.toolCallId) !== i) continue\n\n\t\t\tconst toolName = getToolName(part)\n\t\t\tconst toolCallId = part.toolCallId\n\n\t\t\t// Extract args and result based on state\n\t\t\tlet args: JSONObject = {}\n\t\t\tlet argsText: string\n\t\t\tlet toolResult: unknown\n\t\t\tlet isError = false\n\n\t\t\t// Prefer rawInput to keep argsText append-only across streaming.\n\t\t\t// Avoids assistant-ui \"argsText can only be appended\" errors.\n\t\t\tconst rawInput = getRawInput(part)\n\n\t\t\tif (part.state === 'input-streaming' || part.state === 'input-available' || part.state === 'approval-requested') {\n\t\t\t\targs = (part.input as JSONObject) || {}\n\t\t\t} else if (part.state === 'output-available') {\n\t\t\t\targs = (part.input as JSONObject) || {}\n\t\t\t\ttoolResult = part.output\n\t\t\t} else if (part.state === 'output-error') {\n\t\t\t\targs = (part.input as JSONObject) || {}\n\t\t\t\tisError = true\n\t\t\t\ttoolResult = { error: part.errorText }\n\t\t\t}\n\n\t\t\tif (rawInput) {\n\t\t\t\targsText = rawInput\n\t\t\t} else if (part.state === 'input-streaming') {\n\t\t\t\targsText = ''\n\t\t\t} else {\n\t\t\t\targsText = JSON.stringify(part.input ?? args)\n\t\t\t}\n\t\t\tif (part.state === 'input-streaming') {\n\t\t\t\targsText = stripClosingDelimiters(argsText)\n\t\t\t}\n\n\t\t\t// Detect tools that need approval:\n\t\t\t// 1. Server/local metadata says interrupt\n\t\t\t// 2. Tool is in input-available or approval-requested state without output (HITL)\n\t\t\tconst serverStatus = messageToolStatuses?.[toolCallId]\n\t\t\tconst localStatus = metadata.toolStatuses?.[toolCallId]\n\t\t\tconst toolStatus = serverStatus || localStatus\n\t\t\tconst artifact = converterMetadata.toolArtifacts?.[toolCallId]\n\n\t\t\tconst needsApproval = toolStatus?.type === 'interrupt' ||\n\t\t\t\t((part.state === 'input-available' || part.state === 'approval-requested') && part.output === undefined)\n\n\t\t\tconst statusPayload = toolStatus?.type === 'interrupt' && 'payload' in toolStatus\n\t\t\t\t? toolStatus.payload\n\t\t\t\t: undefined\n\n\t\t\tconst interruptPayload = needsApproval\n\t\t\t\t? { type: 'human' as const, payload: statusPayload ?? { toolName, args } }\n\t\t\t\t: undefined\n\n\t\t\tresult.push({\n\t\t\t\ttype: 'tool-call',\n\t\t\t\ttoolName,\n\t\t\t\ttoolCallId,\n\t\t\t\targsText,\n\t\t\t\targs,\n\t\t\t\tresult: toolResult,\n\t\t\t\tisError,\n\t\t\t\t...(artifact && { artifact }),\n\t\t\t\t...(interruptPayload && {\n\t\t\t\t\tinterrupt: interruptPayload,\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\ttype: 'requires-action' as const,\n\t\t\t\t\t\treason: 'interrupt',\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t} satisfies ToolCallMessagePart)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (type === 'source-url') {\n\t\t\tresult.push({\n\t\t\t\ttype: 'source',\n\t\t\t\tsourceType: 'url',\n\t\t\t\tid: part.sourceId,\n\t\t\t\turl: part.url,\n\t\t\t\ttitle: part.title || '',\n\t\t\t} satisfies SourceMessagePart)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (type === 'source-document') {\n\t\t\tconsole.warn(`Source document part type ${type} is not yet supported in conversion`)\n\t\t\tcontinue\n\t\t}\n\n\t\tconsole.warn(`Unsupported message part type: ${type}`)\n\t}\n\n\treturn result\n}\n\n/**\n * Message converter for Cloudflare Agents SDK messages.\n *\n * Uses unstable_createMessageConverter to receive metadata including toolStatuses,\n * which is required for the requires-action status to work with Assistant UI's\n * native tool confirmation flow.\n *\n * Usage:\n * ```ts\n * const messages = CloudflareMessageConverter.useThreadMessages({\n * isRunning,\n * messages: chat.messages,\n * metadata: useMemo(() => ({\n * toolStatuses,\n * ...(chat.error && { error: chat.error.message }),\n * }), [toolStatuses, chat.error]),\n * })\n * ```\n */\nexport const CloudflareMessageConverter = unstable_createMessageConverter(\n\t(message: UIMessage, metadata: useExternalMessageConverter.Metadata) => {\n\t\tconst createdAt = new Date()\n\n\t\tswitch (message.role) {\n\t\t\tcase 'user': {\n\t\t\t\tconst fileParts = message.parts?.filter(\n\t\t\t\t\t(p): p is Extract<MessagePart, { type: 'file' }> => p.type === 'file'\n\t\t\t\t)\n\t\t\t\tconst attachments = fileParts?.map((part, idx) => ({\n\t\t\t\t\tid: idx.toString(),\n\t\t\t\t\ttype: part.mediaType?.startsWith('image/') ? ('image' as const) : ('file' as const),\n\t\t\t\t\tname: part.filename ?? 'file',\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\tpart.mediaType?.startsWith('image/')\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\ttype: 'image' as const,\n\t\t\t\t\t\t\t\t\timage: part.url,\n\t\t\t\t\t\t\t\t\tfilename: part.filename ?? 'file',\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\ttype: 'file' as const,\n\t\t\t\t\t\t\t\t\tfilename: part.filename ?? 'file',\n\t\t\t\t\t\t\t\t\tdata: part.url,\n\t\t\t\t\t\t\t\t\tmimeType: part.mediaType ?? 'application/octet-stream',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tcontentType: part.mediaType ?? 'application/octet-stream',\n\t\t\t\t\tstatus: { type: 'complete' as const },\n\t\t\t\t}))\n\t\t\t\treturn {\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tid: message.id,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tcontent: convertParts(message, metadata),\n\t\t\t\t\tattachments,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcase 'system':\n\t\t\t\treturn {\n\t\t\t\t\trole: 'system',\n\t\t\t\t\tid: message.id,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tcontent: convertParts(message, metadata),\n\t\t\t\t}\n\n\t\t\tcase 'assistant': {\n\t\t\t\t// Type cast is safe: message comes from Vercel AI SDK's UIMessage type.\n\t\t\t\t// The `annotations` and `data` properties are optional AI SDK extensions\n\t\t\t\t// that may or may not be present. Cast allows access without runtime errors.\n\t\t\t\t// No security risk since we're only reading optional fields from a trusted source.\n\t\t\t\tconst msgWithMeta = message as unknown as {\n\t\t\t\t\tannotations?: JSONValue[]\n\t\t\t\t\tdata?: JSONValue | JSONValue[]\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tid: message.id,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tcontent: convertParts(message, metadata),\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\tunstable_annotations: msgWithMeta.annotations,\n\t\t\t\t\t\tunstable_data: Array.isArray(msgWithMeta.data)\n\t\t\t\t\t\t\t? msgWithMeta.data\n\t\t\t\t\t\t\t: msgWithMeta.data\n\t\t\t\t\t\t\t\t? [msgWithMeta.data]\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tcustom: {},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn(`Unsupported message role: ${message.role}`)\n\t\t\t\treturn []\n\t\t}\n\t}\n)\n\nexport { CloudflareMessageConverter as default }\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport {\n\tuseExternalStoreRuntime,\n\ttype AppendMessage,\n\ttype AssistantRuntime,\n\ttype ExternalStoreThreadListAdapter,\n\ttype ThreadMessage,\n} from '@assistant-ui/react'\nimport { useAgentChat } from '@cloudflare/ai-chat/react'\nimport {\n\tisToolDestructive,\n\ttype ToolCallMetadata,\n\ttype ThreadAgentState,\n\ttype ThreadManagerAgent,\n\ttype ThreadManagerState,\n\ttype ThreadToolSelection,\n\ttype ToolApprovalMode,\n\ttype ToolSourceInfo,\n\ttype ToolWithSource,\n\ttype ThreadAgentAgent,\n\ttype SerializableValue,\n} from '@mcp-b/shared-types'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { useAgent } from 'agents/react'\nimport type { UIMessage } from 'ai'\n\nimport { CloudflareMessageConverter } from '../utils/converter'\nimport {\n\tformatToolResult,\n\tgetEmbeddedAgentTabId,\n\tgetPendingToolCallIds,\n\tsliceMessagesUntil,\n\tuseLatest,\n} from './thread-runtime-utils'\n\nconst DISCONNECTED_THREAD_ID = '__disconnected__'\n\n/**\n * Options for the useThreadRuntime hook.\n */\nexport interface UseThreadRuntimeOptions {\n\t/**\n\t * The thread ID to connect to.\n\t * When null/undefined, the hook returns a minimal disconnected runtime.\n\t */\n\tthreadId: string | null | undefined\n\n\t/**\n\t * The host for Cloudflare Agent WebSocket connections.\n\t */\n\thost?: string\n\n\t/**\n\t * IDP token for SSO-first authentication.\n\t * When provided: Used for WebSocket authentication to ThreadAgent DO.\n\t * When omitted: Anonymous mode (ThreadAgent initialized via ThreadManager).\n\t */\n\tauthToken?: string\n\n\t/**\n\t * ThreadManager agent instance (reused from parent adapter).\n\t * Used to invoke tools remotely via ThreadManager for governance/policy enforcement.\n\t */\n\tmanager: ReturnType<typeof useAgent<ThreadManagerAgent, ThreadManagerState>>\n\n\t/**\n\t * MCP tools to sync to the backend.\n\t */\n\tmcpTools?: ToolWithSource[]\n\n\t/**\n\t * Function to execute MCP tools locally.\n\t * NOTE: Tool execution for chat goes through ThreadManager.invokeTool instead.\n\t */\n\texecuteMCPTool?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t) => Promise<CallToolResult>\n\n\t/**\n\t * Available tool sources from ThreadManager.\n\t * Received from adapter - used for cross-app RPC tool routing.\n\t */\n\ttoolSources: ToolSourceInfo[]\n\n\t/**\n\t * Additional adapters to use with the runtime.\n\t */\n\tthreadListAdapter: ExternalStoreThreadListAdapter\n}\n\n/**\n * Options for adding tool output.\n */\nexport interface AddToolOutputOptions {\n\ttoolCallId: string\n\toutput: unknown\n}\n\nexport interface ExecuteToolOptions {\n\ttoolCallId?: string\n}\n\n/**\n * Voice sync callbacks for backend-first architecture.\n * These directly call ThreadAgent DO to persist voice messages.\n */\nexport interface VoiceSyncCallbacks {\n\t/** Append a user voice message to the thread */\n\tappendUserMessage: (text: string) => void\n\t/** Append an assistant voice message to the thread */\n\tappendAssistantMessage: (text: string) => void\n\t/** Append a voice tool call to the thread */\n\tappendToolCall: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t\tresult: string,\n\t\tisError: boolean,\n\t) => void\n}\n\n/**\n * Result from useThreadRuntime.\n */\nexport interface UseThreadRuntimeResult {\n\t/**\n\t * The Assistant UI runtime.\n\t */\n\truntime: AssistantRuntime\n\n\t/**\n\t * Reset the thread (clears messages).\n\t */\n\treset: () => Promise<void>\n\n\t/**\n\t * Whether the thread is ready for message submission.\n\t * True when threadId exists and WebSocket is connected.\n\t * UI should disable submit button when false.\n\t */\n\tisReady: boolean\n\n\t/**\n\t * Whether there are pending HITL tool approvals.\n\t * UI should disable send button and show approval indicator when true.\n\t * Derived from server message metadata - single source of truth.\n\t */\n\thasPendingApprovals: boolean\n\n\t/**\n\t * Tool execution helpers for manual approvals.\n\t */\n\ttoolExecution: {\n\t\texecuteTool: (\n\t\t\ttoolName: string,\n\t\t\targs: Record<string, unknown>,\n\t\t\toptions?: ExecuteToolOptions,\n\t\t) => Promise<CallToolResult>\n\t\tgetToolMetadata: (\n\t\t\ttoolName: string,\n\t\t) => { description?: string; annotations?: ToolWithSource['annotations'] } | null\n\t\t/**\n\t\t * Add tool output (v6 pattern - sends via WebSocket and updates local state).\n\t\t * Used by client-side UI tools (done, form) and approval flow.\n\t\t */\n\t\taddToolOutput: (options: AddToolOutputOptions) => void\n\t}\n\n\t/**\n\t * Tool approval settings (synced from Agent state).\n\t */\n\ttoolApproval: {\n\t\t/** Current mode (from Agent state - single source of truth) */\n\t\tmode: ToolApprovalMode\n\t\t/** Set mode via Agent (broadcasts to all connected clients) */\n\t\tsetMode: (mode: ToolApprovalMode) => void\n\t\t/** Check if a tool is destructive based on its annotations */\n\t\tisDestructive: (annotations?: ToolWithSource['annotations']) => boolean\n\t}\n\n\t/**\n\t * Tool source selection.\n\t */\n\ttoolSelection: {\n\t\tsources: ToolSourceInfo[]\n\t\tselection: ThreadToolSelection | null\n\t\tsetSelection: (selection: ThreadToolSelection | null) => Promise<void>\n\t\tcurrentSourceId?: string\n\t}\n\n\t/**\n\t * Voice sync callbacks for backend-first architecture.\n\t */\n\tvoiceSync: VoiceSyncCallbacks\n\n\t/**\n\t * Voice session state from ThreadAgent (used for handoff UI).\n\t */\n\tvoiceSession: ThreadAgentState[\"voiceSession\"] | null\n\n\t/**\n\t * Raw ThreadAgent client for RPC calls.\n\t */\n\tthreadAgent: ReturnType<typeof useAgent<ThreadAgentAgent, ThreadAgentState>>\n}\n\nfunction extractToolCallMetadata(result: { isError?: boolean; _meta?: unknown }): ToolCallMetadata | null {\n\tconst rawMeta = (result as { _meta?: unknown })._meta\n\tif (!rawMeta || typeof rawMeta !== 'object') return null\n\n\tconst charMeta = (rawMeta as Record<string, unknown>).char\n\tif (!charMeta || typeof charMeta !== 'object') return null\n\n\tconst toolInvocation = (charMeta as Record<string, unknown>).toolInvocation\n\tif (!toolInvocation || typeof toolInvocation !== 'object') return null\n\n\tconst metadata = toolInvocation as Partial<ToolCallMetadata>\n\tif (\n\t\ttypeof metadata.sourceId !== 'string' ||\n\t\ttypeof metadata.startedAt !== 'number' ||\n\t\ttypeof metadata.duration !== 'number'\n\t) {\n\t\treturn null\n\t}\n\n\treturn {\n\t\tsourceId: metadata.sourceId,\n\t\tstartedAt: metadata.startedAt,\n\t\tduration: metadata.duration,\n\t\tisError: result.isError === true || metadata.isError === true || undefined,\n\t\twasAborted: metadata.wasAborted,\n\t\tpolicy: metadata.policy,\n\t}\n}\n\n/**\n * Hook that provides Assistant UI runtime for a single thread.\n *\n * This hook:\n * 1. Connects to ThreadAgent DO for the specified thread\n * 2. Subscribes to Agent state for approval mode (synced across all clients)\n * 3. Handles tool execution via onToolCall callback (v6 pattern)\n * 4. Provides runtime for assistant-ui components\n *\n * NOTE: Tool execution for chat is routed through ThreadManager.invokeTool to enforce\n * policy/governance. The AI only sees tool schemas; execution happens remotely.\n *\n * @param options - Configuration options\n * @returns Assistant UI runtime for the thread\n */\nexport function useThreadRuntime(options: UseThreadRuntimeOptions): UseThreadRuntimeResult {\n\tconst {\n\t\tthreadId,\n\t\thost,\n\t\tauthToken,\n\t\tmanager,\n\t\tmcpTools,\n\t\ttoolSources,\n\t\tthreadListAdapter,\n\t} = options\n\n\t// Agent state - synced from ThreadAgent DO\n\tconst [agentState, setAgentState] = useState<ThreadAgentState | null>(null)\n\n\t// Tool selection state - synced with ThreadAgent\n\tconst [toolSelection, setToolSelectionState] = useState<ThreadToolSelection | null>(null)\n\tconst [toolCallArtifacts, setToolCallArtifacts] = useState<Record<string, ToolCallMetadata>>({})\n\tconst tabId = getEmbeddedAgentTabId()\n\tconst currentSourceId = useMemo(() => {\n\t\tconst match = toolSources.find((source) => source.tabId === tabId)\n\t\treturn match?.sourceId\n\t}, [toolSources, tabId])\n\n\t// Tool execution state is handled inside tool UI components.\n\n\t// Connect to ThreadAgent DO for this thread\n\t// Subscribe to state updates for approval mode sync\n\t//\n\t// SECURITY: Token is NOT passed in URL query string to prevent leakage via:\n\t// - Server access logs\n\t// - Proxy logs\n\t// - Browser history\n\t// - Network monitoring tools\n\t// Authentication context is established via ThreadManager's ticket-based auth.\n\tconst threadAgent = useAgent<ThreadAgentAgent, ThreadAgentState>({\n\t\tagent: 'ThreadAgent',\n\t\tname: threadId ?? DISCONNECTED_THREAD_ID,\n\t\thost,\n\t\t// Token authentication is handled by ThreadManager (via ticket exchange),\n\t\t// not by URL query params. Passing token in URL is a security risk.\n\t\tstartClosed: threadId == null,\n\t\tonStateUpdate: (state) => {\n\t\t\tsetAgentState(state)\n\t\t\tsetToolSelectionState(state?.toolSelection ?? null)\n\t\t},\n\t})\n\n\t// Use ref to access latest threadAgent without adding to deps\n\t// This prevents cleanup from running on every render due to unstable object reference\n\tconst threadAgentRef = useLatest(threadAgent)\n\n\t// Cleanup on unmount only\n\t// Thread switching is handled by key-based remount in CloudflareThreadRuntimeProvider,\n\t// so we only need to close the WebSocket when the component unmounts\n\tuseEffect(() => {\n\t\treturn () => {\n\t\t\t// Close WebSocket if not already fully closed (state 3)\n\t\t\t// This handles CONNECTING (0), OPEN (1), and CLOSING (2) states\n\t\t\t// Calling close() on CLOSING is safe and may help ensure proper cleanup\n\t\t\tconst agent = threadAgentRef.current\n\t\t\tif (agent.readyState !== WebSocket.CLOSED) {\n\t\t\t\tagent.close()\n\t\t\t}\n\t\t}\n\t}, [])\n\n\t// Read approval mode from Agent state (single source of truth)\n\tconst approvalMode = agentState?.approvalMode ?? 'ask'\n\n\t// Set approval mode via Agent (broadcasts to all connected clients)\n\tconst setApprovalMode = useCallback(\n\t\t(mode: ToolApprovalMode) => {\n\t\t\tif (!threadId) {\n\t\t\t\tconsole.warn('[useThreadRuntime] Cannot set approval mode: No active thread')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (threadAgent.readyState !== WebSocket.OPEN) {\n\t\t\t\tconsole.warn('[useThreadRuntime] Cannot set approval mode: WebSocket not connected')\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Fire RPC call - state update will come back via onStateUpdate broadcast\n\t\t\tthreadAgent.stub.setApprovalMode(mode).catch((error) => {\n\t\t\t\tconsole.error('[useThreadRuntime] Failed to set approval mode:', error)\n\t\t\t\t// Note: If this fails, the UI may briefly show the wrong state until next sync.\n\t\t\t\t// The Agent state is the source of truth, so UI will auto-correct on next sync.\n\t\t\t})\n\t\t},\n\t\t[threadId, threadAgent],\n\t)\n\n\tconst mcpToolsRef = useRef(mcpTools)\n\tmcpToolsRef.current = mcpTools\n\n\tconst approvalModeRef = useLatest(approvalMode)\n\n\t// Tracks client-side tool calls being handled (both auto-exec and approval-required).\n\t// Only the last result sends autoContinue: true, preventing duplicate model continuations.\n\tconst pendingClientToolCallsRef = useRef(new Set<string>())\n\n\tuseEffect(() => {\n\t\tsetToolSelectionState(null)\n\t\tsetToolCallArtifacts({})\n\t}, [threadId])\n\n\tconst setToolSelection = useCallback(\n\t\tasync (selection: ThreadToolSelection | null) => {\n\t\t\tif (!threadId) return\n\t\t\tif (threadAgent.readyState !== WebSocket.OPEN) return\n\n\t\t\ttry {\n\t\t\t\tconst result = await threadAgent.stub.setToolSelection(selection)\n\t\t\t\tsetToolSelectionState(result ?? null)\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[useThreadRuntime] Failed to set tool selection:', error)\n\t\t\t}\n\t\t},\n\t\t[threadId, threadAgent],\n\t)\n\n\t// Get tool metadata for approval UI\n\tconst getToolMetadata = useCallback(\n\t\t(toolName: string): { description?: string; annotations?: ToolWithSource['annotations'] } | null => {\n\t\t\tconst tool = mcpTools?.find((t) => t.name === toolName)\n\t\t\tif (!tool) return null\n\t\t\treturn {\n\t\t\t\tdescription: tool.description,\n\t\t\t\tannotations: tool.annotations,\n\t\t\t}\n\t\t},\n\t\t[mcpTools],\n\t)\n\n\t// Tool execution is remote via ThreadManager.invokeTool.\n\t// Canonical tool names - no prefix stripping needed.\n\tconst executeTool = useCallback(\n\t\tasync (\n\t\t\ttoolName: string,\n\t\t\targs: Record<string, unknown>,\n\t\t\toptions?: ExecuteToolOptions,\n\t\t): Promise<CallToolResult> => {\n\t\t\tif (manager.readyState !== WebSocket.OPEN) {\n\t\t\t\tthrow new Error('ThreadManager is not connected')\n\t\t\t}\n\n\t\t\t// Execute remotely via ThreadManager (enforces policy interceptor)\n\t\t\tconst result = await manager.stub.invokeTool({\n\t\t\t\ttoolName,\n\t\t\t\targs: (args ?? {}) as Record<string, SerializableValue>,\n\t\t\t}) as CallToolResult\n\n\t\t\tif (options?.toolCallId) {\n\t\t\t\tconst toolCallId = options.toolCallId\n\t\t\t\tconst metadata = extractToolCallMetadata(result)\n\t\t\t\tif (metadata) {\n\t\t\t\t\tsetToolCallArtifacts((prev) => ({\n\t\t\t\t\t\t...prev,\n\t\t\t\t\t\t[toolCallId]: metadata,\n\t\t\t\t\t}))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result\n\t\t},\n\t\t[manager],\n\t)\n\n\t// Ref for chat.addToolOutput - used by onToolCall before `chat` is in scope.\n\t// Safe because onToolCall fires asynchronously after the hook returns.\n\tconst chatAddToolOutputRef = useRef<((options: { toolCallId: string; output: unknown; autoContinue?: boolean }) => void) | null>(null)\n\n\t// Chat hook with ThreadAgent using v6 onToolCall pattern\n\tconst chat = useAgentChat<ThreadAgentState, UIMessage>({\n\t\tagent: threadAgent,\n\t\tautoContinueAfterToolResult: true,\n\t\tresume: true,\n\t\t// Auto-execute tools that don't need approval; let UnifiedToolFallback handle the rest.\n\t\t// Server tools (done, form, skills) are not in mcpToolsRef and fall through to their custom UIs.\n\t\t// Tool results are batched: only the last result sends autoContinue: true to prevent\n\t\t// the server from triggering multiple model continuations for parallel tool calls.\n\t\tonToolCall: async (toolcall) => {\n\t\t\tconst { toolCall } = toolcall\n\t\t\tconst tools = mcpToolsRef.current\n\t\t\tconst tool = tools?.find((t) => t.name === toolCall.toolName)\n\t\t\tif (!tool) return\n\n\t\t\t// Register SYNCHRONOUSLY (before any await) so the set is fully populated\n\t\t\t// before any async tool execution completes.\n\t\t\tpendingClientToolCallsRef.current.add(toolCall.toolCallId)\n\n\t\t\tconst mode = approvalModeRef.current\n\t\t\tif (mode === 'ask' && isToolDestructive(tool.annotations)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await executeTool(\n\t\t\t\t\ttoolCall.toolName,\n\t\t\t\t\t(toolCall.input ?? {}) as Record<string, unknown>,\n\t\t\t\t\t{ toolCallId: toolCall.toolCallId },\n\t\t\t\t)\n\t\t\t\tconst resultText = formatToolResult(result)\n\t\t\t\tpendingClientToolCallsRef.current.delete(toolCall.toolCallId)\n\t\t\t\tchatAddToolOutputRef.current?.({\n\t\t\t\t\ttoolCallId: toolCall.toolCallId,\n\t\t\t\t\toutput: result.isError ? `Error: ${resultText}` : resultText,\n\t\t\t\t\tautoContinue: pendingClientToolCallsRef.current.size === 0,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tpendingClientToolCallsRef.current.delete(toolCall.toolCallId)\n\t\t\t\tchatAddToolOutputRef.current?.({\n\t\t\t\t\ttoolCallId: toolCall.toolCallId,\n\t\t\t\t\toutput: `Error: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tautoContinue: pendingClientToolCallsRef.current.size === 0,\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\t// Send messages and routing info to server\n\t\t// Tools are already registered with ThreadManager via the hub\n\t\tprepareSendMessagesRequest: async (options) => {\n\t\t\tconst tools = mcpToolsRef.current;\n\t\t\treturn {\n\t\t\t\tbody: {\n\t\t\t\t\tmessages: options.messages,\n\t\t\t\t\tclientTools: tools,\n\t\t\t\t\trequestTabId: tabId, // For hybrid local/remote tool routing\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t})\n\n\t// Populate ref so onToolCall can call addToolOutput\n\tchatAddToolOutputRef.current = chat.addToolOutput\n\n\t// Connection readiness - UI should disable submit until ready\n\tconst isReady = Boolean(threadId) && threadAgent.readyState === WebSocket.OPEN\n\n\t// Derive pending approvals from tool state (single source of truth)\n\t// Tools with needsApproval on server pause in input-available state without output\n\tconst hasPendingApprovals = useMemo(() => {\n\t\treturn getPendingToolCallIds(chat.messages).length > 0\n\t}, [chat.messages])\n\n\t// Running state derived from chat status\n\tconst isRunning = chat.status === 'submitted' || chat.status === 'streaming'\n\n\t// Convert messages using our CloudflareMessageConverter\n\tconst messages = CloudflareMessageConverter.useThreadMessages({\n\t\tisRunning,\n\t\tmessages: chat.messages,\n\t\tmetadata: useMemo(\n\t\t\t() => ({\n\t\t\t\ttoolArtifacts: toolCallArtifacts,\n\t\t\t\t...(chat.error && { error: chat.error.message }),\n\t\t\t}),\n\t\t\t[toolCallArtifacts, chat.error],\n\t\t),\n\t})\n\n\tconst onNew = useCallback(\n\t\tasync (message: AppendMessage) => {\n\t\t\t// Voice messages should only be added to thread history, not trigger a chat agent run.\n\t\t\t// Voice mode has its own agent (OpenAI Realtime) that handles the conversation.\n\t\t\tconst isVoiceMessage =\n\t\t\t\ttypeof message === 'object' &&\n\t\t\t\tmessage !== null &&\n\t\t\t\t'metadata' in message &&\n\t\t\t\ttypeof message.metadata === 'object' &&\n\t\t\t\tmessage.metadata !== null &&\n\t\t\t\t'custom' in message.metadata &&\n\t\t\t\ttypeof message.metadata.custom === 'object' &&\n\t\t\t\tmessage.metadata.custom !== null &&\n\t\t\t\t'source' in message.metadata.custom &&\n\t\t\t\tmessage.metadata.custom.source === 'voice'\n\n\t\t\tif (isVoiceMessage) {\n\t\t\t\t// Convert AppendMessage to UIMessage format and add to chat history\n\t\t\t\t// without triggering a new AI run. The voice agent handles responses.\n\t\t\t\tconst firstContent = message.content[0]\n\t\t\t\tif (!firstContent || firstContent.type !== 'text') return\n\n\t\t\t\t// UIMessage uses 'parts' array for content, not a 'content' string\n\t\t\t\tconst voiceUIMessage: UIMessage = {\n\t\t\t\t\tid: `voice-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,\n\t\t\t\t\trole: message.role,\n\t\t\t\t\tparts: [{ type: 'text', text: firstContent.text }],\n\t\t\t\t}\n\n\t\t\t\t// Add to chat history without triggering AI run\n\t\t\t\t// Use functional update to avoid stale closure when multiple messages arrive quickly\n\t\t\t\tchat.setMessages((prev) => [...prev, voiceUIMessage])\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst firstContent = message.content[0]\n\t\t\tif (!firstContent || firstContent.type !== 'text') return\n\n\t\t\t// Block if no thread - UI should disable submit until thread is ready\n\t\t\tif (!threadId) {\n\t\t\t\tconsole.warn('[useThreadRuntime] Cannot send message: No active thread')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tpendingClientToolCallsRef.current.clear()\n\t\t\t\t// Server-side (ThreadAgent DO) cancels any pending tool calls in onChatMessage\n\t\t\t\tawait chat.sendMessage({ text: firstContent.text })\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[useThreadRuntime] Failed to send message:', {\n\t\t\t\t\terror: error instanceof Error ? error.message : error,\n\t\t\t\t\tthreadId,\n\t\t\t\t})\n\t\t\t\t// Re-throw so the UI can handle/display the error\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[threadId, chat],\n\t)\n\n\tconst onEdit = useCallback(\n\t\tasync (message: AppendMessage) => {\n\t\t\tif (!threadId) return\n\n\t\t\tconst firstContent = message.content[0]\n\t\t\tif (!firstContent || firstContent.type !== 'text') return\n\n\t\t\t// Save previous messages for rollback on error\n\t\t\tconst previousMessages = chat.messages\n\n\t\t\t// Slice removes the message with pending tools, no need to cancel explicitly\n\t\t\tconst newMessages = sliceMessagesUntil(chat.messages, message.parentId ?? null)\n\t\t\tchat.setMessages(newMessages)\n\n\t\t\ttry {\n\t\t\t\tpendingClientToolCallsRef.current.clear()\n\t\t\t\tawait chat.sendMessage({ text: firstContent.text })\n\t\t\t} catch (error) {\n\t\t\t\t// Rollback to previous state on failure\n\t\t\t\tconsole.error('[useThreadRuntime] Edit failed, rolling back:', {\n\t\t\t\t\terror: error instanceof Error ? error.message : error,\n\t\t\t\t\tthreadId,\n\t\t\t\t})\n\t\t\t\tchat.setMessages(previousMessages)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[threadId, chat],\n\t)\n\n\tconst onReload = useCallback(\n\t\tasync (parentId: string | null): Promise<void> => {\n\t\t\tif (!threadId) return\n\n\t\t\t// Save previous messages for rollback on error\n\t\t\tconst previousMessages = chat.messages\n\n\t\t\t// Slice removes the message with pending tools, no need to cancel explicitly\n\t\t\tconst newMessages = sliceMessagesUntil(chat.messages, parentId)\n\t\t\tchat.setMessages(newMessages)\n\n\t\t\ttry {\n\t\t\t\tpendingClientToolCallsRef.current.clear()\n\t\t\t\tawait chat.regenerate()\n\t\t\t} catch (error) {\n\t\t\t\t// Rollback to previous state on failure\n\t\t\t\tconsole.error('[useThreadRuntime] Reload failed, rolling back:', {\n\t\t\t\t\terror: error instanceof Error ? error.message : error,\n\t\t\t\t\tthreadId,\n\t\t\t\t})\n\t\t\t\tchat.setMessages(previousMessages)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[threadId, chat],\n\t)\n\n\tconst onCancel = useCallback(async (): Promise<void> => {\n\t\tpendingClientToolCallsRef.current.clear()\n\t\tchat.stop()\n\t}, [chat])\n\n\tconst onAddToolResult = useCallback(\n\t\t(options: { toolCallId: string; result: unknown; isError?: boolean }) => {\n\t\t\tif (!threadId) {\n\t\t\t\tconsole.error('[useThreadRuntime] Cannot add tool result: no active thread', {\n\t\t\t\t\ttoolCallId: options.toolCallId,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tpendingClientToolCallsRef.current.delete(options.toolCallId)\n\t\t\t\tconst isLast = pendingClientToolCallsRef.current.size === 0\n\n\t\t\t\tchat.addToolOutput({\n\t\t\t\t\ttoolCallId: options.toolCallId,\n\t\t\t\t\toutput: options.isError ? `Error: ${options.result}` : options.result,\n\t\t\t\t\tautoContinue: isLast,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error('[useThreadRuntime] Failed to add tool result:', {\n\t\t\t\t\ttoolCallId: options.toolCallId,\n\t\t\t\t\terror: error instanceof Error ? error.message : error,\n\t\t\t\t})\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[threadId, chat],\n\t)\n\n\tconst setMessages = useCallback(\n\t\t(messages: readonly ThreadMessage[]) => {\n\t\t\tif (!threadId) return\n\t\t\tchat.setMessages(messages as unknown as UIMessage[])\n\t\t},\n\t\t[threadId, chat],\n\t)\n\n\tconst store = useMemo(\n\t\t() => ({\n\t\t\tmessages,\n\t\t\tisRunning,\n\t\t\tonNew,\n\t\t\tonEdit,\n\t\t\tonReload,\n\t\t\tonCancel,\n\t\t\tonAddToolResult,\n\t\t\tsetMessages,\n\t\t\tadapters: {\n\t\t\t\tthreadList: threadListAdapter,\n\t\t\t},\n\t\t}),\n\t\t[\n\t\t\tmessages,\n\t\t\tisRunning,\n\t\t\tonNew,\n\t\t\tonEdit,\n\t\t\tonReload,\n\t\t\tonCancel,\n\t\t\tonAddToolResult,\n\t\t\tsetMessages,\n\t\t\tthreadListAdapter,\n\t\t],\n\t)\n\n\tconst runtime = useExternalStoreRuntime(store)\n\n\tconst reset = useCallback(async () => {\n\t\tpendingClientToolCallsRef.current.clear()\n\t\tchat.clearHistory()\n\t\tsetToolCallArtifacts({})\n\t}, [chat])\n\n\t// Add tool output (v6 pattern - uses chat.addToolOutput which sends to server + updates local state)\n\t// Participates in batching: removes from pending set and only sends autoContinue: true for the last result.\n\tconst addToolOutput = useCallback(\n\t\t(options: AddToolOutputOptions) => {\n\t\t\tif (!threadId) {\n\t\t\t\tconst error = new Error('Cannot add tool output: No active thread')\n\t\t\t\tconsole.error('[useThreadRuntime]', error.message, { toolCallId: options.toolCallId })\n\t\t\t\tthrow error\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tpendingClientToolCallsRef.current.delete(options.toolCallId)\n\t\t\t\tconst isLast = pendingClientToolCallsRef.current.size === 0\n\n\t\t\t\tchat.addToolOutput({\n\t\t\t\t\ttoolCallId: options.toolCallId,\n\t\t\t\t\toutput: options.output,\n\t\t\t\t\tautoContinue: isLast,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\t// Log error with context - this is important for debugging since\n\t\t\t\t// tool outputs are sent to the AI model to continue the conversation\n\t\t\t\tconsole.error('[useThreadRuntime] Failed to add tool output:', {\n\t\t\t\t\ttoolCallId: options.toolCallId,\n\t\t\t\t\terror: error instanceof Error ? error.message : error,\n\t\t\t\t})\n\t\t\t\t// Re-throw so callers can show user feedback\n\t\t\t\tthrow error\n\t\t\t}\n\t\t},\n\t\t[threadId, chat],\n\t)\n\n\t// Voice sync callbacks - backend-first architecture\n\t// These directly call ThreadAgent DO to persist voice messages\n\t// Note: Fire-and-forget by design - voice mode shouldn't block on persistence\n\tconst runVoiceSync = useCallback(\n\t\t(\n\t\t\tactionLabel: string,\n\t\t\tcontext: Record<string, unknown>,\n\t\t\toperation: () => Promise<void>,\n\t\t) => {\n\t\t\tif (!threadId) {\n\t\t\t\tconsole.error(`[useThreadRuntime] Cannot ${actionLabel}: No active thread`, context)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (threadAgent.readyState !== WebSocket.OPEN) {\n\t\t\t\tconsole.error(`[useThreadRuntime] Cannot ${actionLabel}: WebSocket not connected`, {\n\t\t\t\t\t...context,\n\t\t\t\t\treadyState: threadAgent.readyState,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\toperation().catch((error) => {\n\t\t\t\tconsole.error(`[useThreadRuntime] Failed to ${actionLabel}:`, {\n\t\t\t\t\t...context,\n\t\t\t\t\terror: error instanceof Error ? error.message : error,\n\t\t\t\t\tthreadId,\n\t\t\t\t})\n\t\t\t})\n\t\t},\n\t\t[threadId, threadAgent],\n\t)\n\n\tconst appendVoiceUserMessage = useCallback(\n\t\t(text: string) => {\n\t\t\trunVoiceSync(\n\t\t\t\t'append voice user message',\n\t\t\t\t{ text: text.slice(0, 50) },\n\t\t\t\t() => threadAgent.stub.appendVoiceMessage('user', text),\n\t\t\t)\n\t\t},\n\t\t[runVoiceSync, threadAgent],\n\t)\n\n\tconst appendVoiceAssistantMessage = useCallback(\n\t\t(text: string) => {\n\t\t\trunVoiceSync(\n\t\t\t\t'append voice assistant message',\n\t\t\t\t{ text: text.slice(0, 50) },\n\t\t\t\t() => threadAgent.stub.appendVoiceMessage('assistant', text),\n\t\t\t)\n\t\t},\n\t\t[runVoiceSync, threadAgent],\n\t)\n\n\tconst appendVoiceToolCall = useCallback(\n\t\t(toolName: string, args: Record<string, unknown>, result: string, isError: boolean) => {\n\t\t\trunVoiceSync(\n\t\t\t\t'append voice tool call',\n\t\t\t\t{ toolName },\n\t\t\t\t() => threadAgent.stub.appendVoiceToolCall(toolName, args as Record<string, SerializableValue>, result, isError),\n\t\t\t)\n\t\t},\n\t\t[runVoiceSync, threadAgent],\n\t)\n\n\treturn {\n\t\truntime,\n\t\treset,\n\t\tisReady,\n\t\thasPendingApprovals,\n\t\ttoolExecution: {\n\t\t\texecuteTool,\n\t\t\tgetToolMetadata,\n\t\t\taddToolOutput,\n\t\t},\n\t\ttoolApproval: {\n\t\t\tmode: approvalMode,\n\t\t\tsetMode: setApprovalMode,\n\t\t\tisDestructive: isToolDestructive,\n\t\t},\n\t\ttoolSelection: {\n\t\t\tsources: toolSources,\n\t\t\tselection: toolSelection,\n\t\t\tsetSelection: setToolSelection,\n\t\t\tcurrentSourceId,\n\t\t},\n\t\tvoiceSync: {\n\t\t\tappendUserMessage: appendVoiceUserMessage,\n\t\t\tappendAssistantMessage: appendVoiceAssistantMessage,\n\t\t\tappendToolCall: appendVoiceToolCall,\n\t\t},\n\t\tvoiceSession: agentState?.voiceSession ?? null,\n\t\tthreadAgent,\n\t}\n}\n","/**\n * Tool Approval Context\n *\n * Provides tool approval settings from ThreadAgent state.\n * This replaces the old ToolApprovalProvider which managed state locally.\n * In v6, approval mode is stored in ThreadAgent and synced across all clients.\n *\n * @example\n * ```tsx\n * // In CloudflareThreadRuntimeProvider:\n * <ToolApprovalContext.Provider value={toolApproval}>\n * <App />\n * </ToolApprovalContext.Provider>\n *\n * // In a component:\n * const toolApproval = useToolApproval()\n * // or\n * const toolApproval = useOptionalToolApproval()\n * ```\n */\nimport { createContext, useContext } from 'react'\n\nimport type { ToolApprovalMode, ToolWithSource } from '@mcp-b/shared-types'\n\n/**\n * Tool Approval Context Value\n * Matches the shape returned by useThreadRuntime().toolApproval\n */\nexport interface ToolApprovalContextValue {\n\t/** Current mode (from Agent state - single source of truth) */\n\tmode: ToolApprovalMode\n\t/** Set mode via Agent (broadcasts to all connected clients) */\n\tsetMode: (mode: ToolApprovalMode) => void\n\t/** Check if a tool is destructive based on its annotations */\n\tisDestructive: (annotations?: ToolWithSource['annotations']) => boolean\n}\n\nexport const ToolApprovalContext = createContext<ToolApprovalContextValue | null>(null)\n\n/**\n * Hook to access tool approval settings\n * @throws Error if not within a ToolApprovalContext\n */\nexport function useToolApproval(): ToolApprovalContextValue {\n\tconst context = useContext(ToolApprovalContext)\n\tif (!context) {\n\t\tthrow new Error('useToolApproval must be used within a ToolApprovalContext.Provider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access tool approval settings\n * Returns null if not within a ToolApprovalContext\n */\nexport function useOptionalToolApproval(): ToolApprovalContextValue | null {\n\treturn useContext(ToolApprovalContext)\n}\n","import { createContext, useContext } from 'react'\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ToolWithSource } from '@mcp-b/shared-types'\nimport type { FC, ReactNode } from 'react'\nimport type { AddToolOutputOptions, ExecuteToolOptions } from '../hooks/useThreadRuntime'\n\nexport interface ToolExecutionContextValue {\n\texecuteTool: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t\toptions?: ExecuteToolOptions,\n\t) => Promise<CallToolResult>\n\tgetToolMetadata: (\n\t\ttoolName: string,\n\t) => { description?: string; annotations?: ToolWithSource['annotations'] } | null\n\t/**\n\t * Add tool output (v6 pattern - sends via WebSocket and updates local state).\n\t * Used by client-side UI tools (done, form) and approval flow.\n\t */\n\taddToolOutput: (options: AddToolOutputOptions) => void\n\t/**\n\t * Whether there are pending HITL tool approvals.\n\t * UI should disable send button and show approval indicator when true.\n\t * Derived from server message metadata - single source of truth.\n\t */\n\thasPendingApprovals: boolean\n}\n\nconst ToolExecutionContext = createContext<ToolExecutionContextValue | null>(null)\n\nexport interface ToolExecutionProviderProps {\n\tvalue: ToolExecutionContextValue\n\tchildren: ReactNode\n}\n\nexport const ToolExecutionProvider: FC<ToolExecutionProviderProps> = ({ value, children }) => {\n\treturn <ToolExecutionContext.Provider value={value}>{children}</ToolExecutionContext.Provider>\n}\n\nexport function useToolExecution(): ToolExecutionContextValue {\n\tconst context = useContext(ToolExecutionContext)\n\tif (!context) {\n\t\tthrow new Error('useToolExecution must be used within a ToolExecutionProvider')\n\t}\n\treturn context\n}\n\nexport function useOptionalToolExecution(): ToolExecutionContextValue | null {\n\treturn useContext(ToolExecutionContext)\n}\n","import { createContext, useContext } from 'react'\n\nimport type { ThreadToolSelection, ToolSourceInfo } from '@mcp-b/shared-types'\nimport type { FC, ReactNode } from 'react'\n\nexport interface ToolSelectionContextValue {\n\tsources: ToolSourceInfo[]\n\tselection: ThreadToolSelection | null\n\tsetSelection: (selection: ThreadToolSelection | null) => Promise<void>\n\tcurrentSourceId?: string\n}\n\nconst ToolSelectionContext = createContext<ToolSelectionContextValue | null>(null)\n\nexport interface ToolSelectionProviderProps {\n\tvalue: ToolSelectionContextValue\n\tchildren: ReactNode\n}\n\nexport const ToolSelectionProvider: FC<ToolSelectionProviderProps> = ({ value, children }) => {\n\treturn <ToolSelectionContext.Provider value={value}>{children}</ToolSelectionContext.Provider>\n}\n\nexport function useToolSelection(): ToolSelectionContextValue {\n\tconst context = useContext(ToolSelectionContext)\n\tif (!context) {\n\t\tthrow new Error('useToolSelection must be used within a ToolSelectionProvider')\n\t}\n\treturn context\n}\n\nexport function useOptionalToolSelection(): ToolSelectionContextValue | null {\n\treturn useContext(ToolSelectionContext)\n}\n","/**\n * CloudflareThreadRuntimeProvider\n *\n * Provider that combines ThreadManager (thread list) and ThreadAgent (chat) functionality.\n *\n * This provider:\n * 1. Connects to ThreadManager for thread list management\n * 2. Provides thread selection and creation\n * 3. Connects to ThreadAgent for the selected thread's chat\n * 4. Handles tool execution (local and cross-site)\n *\n * Architecture:\n * - ThreadManager DO: One per user, manages thread list and tool registry\n * - ThreadAgent DO: One per thread, handles chat messages\n * - useCloudflareThreadAdapter: Manages ThreadManager connection and thread list state\n * - useThreadRuntime: Manages ThreadAgent connection for selected thread\n */\n\nimport {\n\tcreateContext,\n\tSuspense,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\ttype ReactNode,\n\ttype FC,\n} from 'react'\nimport { Skeleton } from '@/components/ui/skeleton'\n\nimport { AssistantRuntimeProvider } from '@assistant-ui/react'\nimport type {\n\tPolicyEvent,\n\tThreadAgentAgent,\n\tThreadAgentState,\n\tThreadManagerAgent,\n\tThreadManagerState,\n\tToolWithSource,\n} from '@mcp-b/shared-types'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { useAgent } from 'agents/react'\n\nimport { ChatErrorBoundary } from '../components/errors/ChatErrorBoundary'\nimport { useCloudflareThreadAdapter } from '../hooks/useCloudflareThreadAdapter'\nimport { useThreadRuntime, type VoiceSyncCallbacks } from '../hooks/useThreadRuntime'\nimport { AuthErrorException } from '../utils/convert-init-error'\nimport type { ResolvedAuth } from './TicketExchangeGate'\nimport { ToolApprovalContext } from './ToolApprovalContext'\nimport { ToolExecutionProvider } from './ToolExecutionProvider'\nimport { ToolSelectionProvider } from './ToolSelectionProvider'\n\n/**\n * Props for CloudflareThreadRuntimeProvider.\n */\nexport interface CloudflareThreadRuntimeProviderProps {\n\tchildren: ReactNode\n\n\t/**\n\t * The host for Cloudflare Agent WebSocket connections.\n\t * @default 'localhost:8787'\n\t */\n\thost?: string\n\n\t/**\n\t * Resolved authentication from TicketExchangeGate.\n\t * Contains either authenticated mode (with ticketAuth) or anonymous mode (with anthropicApiKey).\n\t *\n\t * This replaces the individual authToken, clientId, ticketAuth, and anthropicApiKey props.\n\t * Authentication is resolved by TicketExchangeGate BEFORE this provider mounts.\n\t */\n\tresolvedAuth: ResolvedAuth\n\n\t/**\n\t * MCP tools to sync to the backend.\n\t */\n\tmcpTools?: ToolWithSource[]\n\n\t/**\n\t * Function to execute MCP tools locally.\n\t */\n\texecuteMCPTool?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t) => Promise<CallToolResult>\n}\n\n/**\n * Thread data exposed through context.\n * Subset of ThreadSummary with only the fields needed for UI rendering.\n */\nexport interface ThreadListItem {\n\tid: string\n\ttitle?: string\n\tstatus: 'regular' | 'archived'\n}\n\n/**\n * Context value for CloudflareThreadRuntimeProvider.\n */\ninterface CloudflareThreadContextValue {\n\t/** Whether the context has been initialized */\n\tisInitialized: boolean\n\t/** Whether the thread list has synced and context is ready */\n\tisReady: boolean\n\t/** Whether the thread list is still loading */\n\tisLoading: boolean\n\t/** The internal end_user ID */\n\tendUserId: string | null\n\t/** The resolved organization ID (SSO-First: org-level only) */\n\torganizationId: string | null\n\t/** Current selected thread ID */\n\tcurrentThreadId: string | undefined\n\t/** Set current selected thread ID */\n\tsetCurrentThreadId: (threadId: string | undefined) => void\n\t/** Reset the current thread (clears messages) */\n\treset: () => Promise<void>\n\t/** Start a new thread */\n\tstartNew: () => Promise<void>\n\t/** Archive a thread */\n\tarchiveThread: (threadId: string) => Promise<void>\n\t/** Active (non-archived) threads */\n\tthreads: readonly ThreadListItem[]\n\t/** Archived threads */\n\tarchivedThreads: readonly ThreadListItem[]\n\t/** Authentication error (if initialization failed) */\n\tauthError: import('../utils/auth-errors').AuthError | null\n}\n\ninterface PolicyPluginContextValue {\n\tenabled: boolean\n\tname: string\n\tevents: readonly PolicyEvent[]\n\tclearEvents: () => void\n}\n\nconst CloudflareThreadContext = createContext<CloudflareThreadContextValue | null>(null)\nconst PolicyPluginContext = createContext<PolicyPluginContextValue | null>(null)\n\n/**\n * Voice sync context - exposes backend sync callbacks for voice mode.\n * This allows VoiceThreadBridge to sync transcripts directly to ThreadAgent DO.\n */\nconst VoiceSyncContext = createContext<VoiceSyncCallbacks | null>(null)\nconst VoiceSessionContext = createContext<ThreadAgentState[\"voiceSession\"] | null | undefined>(undefined)\ntype ThreadAgentConnection = ReturnType<typeof useAgent<ThreadAgentAgent, ThreadAgentState>>\n\nconst ThreadAgentContext = createContext<ThreadAgentConnection | null>(null)\n\n/**\n * Hook to access voice sync callbacks for backend-first voice mode.\n * Returns null if not within CloudflareThreadRuntimeProvider.\n *\n * NOTE: This is an internal hook used by AgentProvider to wire VoiceThreadBridge.\n * It uses the \"optional\" pattern because VoiceThreadBridge may render before\n * ThreadRuntimeBridge (during Suspense). This is NOT a public API.\n *\n * @internal\n */\nexport function useOptionalVoiceSync(): VoiceSyncCallbacks | null {\n\treturn useContext(VoiceSyncContext)\n}\n\n/**\n * Hook to access voice sync callbacks for backend-first voice mode.\n * @throws Error if not within CloudflareThreadRuntimeProvider\n */\nexport function useVoiceSync(): VoiceSyncCallbacks {\n\tconst context = useContext(VoiceSyncContext)\n\tif (!context) {\n\t\tthrow new Error('useVoiceSync must be used within CloudflareThreadRuntimeProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to access ThreadAgent voice session state (handoff UI).\n */\nexport function useVoiceSession(): ThreadAgentState[\"voiceSession\"] | null {\n\tconst context = useContext(VoiceSessionContext)\n\tif (context === undefined) {\n\t\tthrow new Error('useVoiceSession must be used within CloudflareThreadRuntimeProvider')\n\t}\n\treturn context\n}\n\n/**\n * Optional voice session hook (returns null if provider not available).\n */\nexport function useOptionalVoiceSession(): ThreadAgentState[\"voiceSession\"] | null {\n\treturn useContext(VoiceSessionContext) ?? null\n}\n\n/**\n * Hook to access the ThreadAgent client for RPC calls.\n */\nexport function useThreadAgent(): ThreadAgentConnection {\n\tconst context = useContext(ThreadAgentContext)\n\tif (!context) {\n\t\tthrow new Error('useThreadAgent must be used within CloudflareThreadRuntimeProvider')\n\t}\n\treturn context\n}\n\n/**\n * Optional ThreadAgent client hook.\n */\nexport function useOptionalThreadAgent(): ThreadAgentConnection | null {\n\treturn useContext(ThreadAgentContext)\n}\n\n/**\n * Hook to access CloudflareThreadRuntime context.\n * Must be used within CloudflareThreadRuntimeProvider.\n */\nexport function useCloudflareThread(): CloudflareThreadContextValue {\n\tconst context = useContext(CloudflareThreadContext)\n\tif (!context) {\n\t\tthrow new Error('useCloudflareThread must be used within CloudflareThreadRuntimeProvider')\n\t}\n\treturn context\n}\n\nexport function usePolicyPlugin(): PolicyPluginContextValue {\n\tconst context = useContext(PolicyPluginContext)\n\tif (!context) {\n\t\tthrow new Error('usePolicyPlugin must be used within CloudflareThreadRuntimeProvider')\n\t}\n\treturn context\n}\n\nexport function useOptionalPolicyPlugin(): PolicyPluginContextValue | null {\n\treturn useContext(PolicyPluginContext)\n}\n\n/**\n * Loading fallback shown during thread runtime initialization.\n * Mimics the thread layout (header buttons, message bubbles, composer).\n */\nfunction ThreadRuntimeSkeleton() {\n\treturn (\n\t\t<div className=\"flex h-full flex-col\" aria-label=\"Loading thread\">\n\t\t\t{/* Header bar */}\n\t\t\t<div className=\"flex shrink-0 items-center justify-between px-4 py-3\">\n\t\t\t\t<div className=\"flex gap-2\">\n\t\t\t\t\t<Skeleton className=\"size-8 rounded-md\" />\n\t\t\t\t\t<Skeleton className=\"size-8 rounded-md\" />\n\t\t\t\t</div>\n\t\t\t\t<Skeleton className=\"size-8 rounded-md\" />\n\t\t\t</div>\n\n\t\t\t{/* Messages area */}\n\t\t\t<div className=\"flex-1 space-y-4 px-4 pt-2\">\n\t\t\t\t{/* Assistant message (left) */}\n\t\t\t\t<div className=\"flex items-start\">\n\t\t\t\t\t<Skeleton className=\"h-16 w-3/4 rounded-2xl\" />\n\t\t\t\t</div>\n\n\t\t\t\t{/* User message (right) */}\n\t\t\t\t<div className=\"flex items-start justify-end\">\n\t\t\t\t\t<Skeleton className=\"h-10 w-1/2 rounded-2xl\" />\n\t\t\t\t</div>\n\n\t\t\t\t{/* Assistant message (left) */}\n\t\t\t\t<div className=\"flex items-start\">\n\t\t\t\t\t<Skeleton className=\"h-24 w-2/3 rounded-2xl\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Composer area */}\n\t\t\t<div className=\"shrink-0 px-4 pb-4 pt-2\">\n\t\t\t\t<Skeleton className=\"h-12 w-full rounded-xl\" />\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\n/**\n * Internal bridge component that uses useThreadRuntime.\n * This is separated so Suspense can wrap it - when useAgentChat suspends,\n * only this component unmounts, not the entire provider tree.\n */\ninterface ThreadRuntimeBridgeProps {\n\tchildren: ReactNode\n\tthreadId: string | undefined\n\thost?: string\n\tresolvedAuth: ResolvedAuth\n\tmanager: ReturnType<typeof useAgent<ThreadManagerAgent, ThreadManagerState>>\n\tmcpTools?: ToolWithSource[]\n\texecuteMCPTool?: (toolName: string, args: Record<string, unknown>) => Promise<CallToolResult>\n\tthreadListAdapter: ReturnType<typeof useCloudflareThreadAdapter>['threadListAdapter']\n\ttoolSources: ReturnType<typeof useCloudflareThreadAdapter>['toolSources']\n\tonResetChange: (reset: () => Promise<void>) => void\n\t/** Callback to start a new thread (for error boundary recovery) */\n\tonStartNewThread: () => Promise<void>\n}\n\nfunction ThreadRuntimeBridge({\n\tchildren,\n\tthreadId,\n\thost,\n\tresolvedAuth,\n\tmanager,\n\tmcpTools,\n\texecuteMCPTool,\n\tthreadListAdapter,\n\ttoolSources,\n\tonResetChange,\n\tonStartNewThread,\n}: ThreadRuntimeBridgeProps) {\n\t// Connect to ThreadAgent for the selected thread\n\t// This can suspend via useAgentChat -> use()\n\t// Note: authToken is extracted from ticketAuth for ThreadAgent authentication\n\t// (ThreadAgent uses the original token for its own ticket exchange)\n\tconst authToken = resolvedAuth.mode === 'authenticated' ? resolvedAuth.ticketAuth?.ticket : undefined\n\tconst {\n\t\truntime,\n\t\treset: resetThread,\n\t\ttoolExecution,\n\t\ttoolApproval,\n\t\ttoolSelection,\n\t\thasPendingApprovals,\n\t\tvoiceSync,\n\t\tvoiceSession,\n\t\tthreadAgent,\n\t} = useThreadRuntime({\n\t\tthreadId,\n\t\thost,\n\t\tauthToken,\n\t\tmanager,\n\t\tmcpTools,\n\t\texecuteMCPTool,\n\t\ttoolSources,\n\t\tthreadListAdapter,\n\t})\n\n\t// Destructure toolExecution for stable memo dependencies\n\tconst { executeTool, getToolMetadata, addToolOutput } = toolExecution\n\n\t// Build tool execution context value with pending approvals info\n\tconst toolExecutionValue = useMemo(\n\t\t() => ({\n\t\t\texecuteTool,\n\t\t\tgetToolMetadata,\n\t\t\taddToolOutput,\n\t\t\thasPendingApprovals,\n\t\t}),\n\t\t[executeTool, getToolMetadata, addToolOutput, hasPendingApprovals],\n\t)\n\n\t// Notify parent of reset function changes\n\tconst resetThreadRef = useRef(resetThread)\n\tresetThreadRef.current = resetThread\n\tconst stableReset = useCallback(async () => {\n\t\tawait resetThreadRef.current()\n\t}, [])\n\n\t// Update parent's reset ref\n\tconst onResetChangeRef = useRef(onResetChange)\n\tonResetChangeRef.current = onResetChange\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: stableReset is the only dependency needed here\n\tuseEffect(() => {\n\t\tonResetChangeRef.current(stableReset)\n\t}, [stableReset])\n\n\treturn (\n\t\t<VoiceSyncContext.Provider value={voiceSync}>\n\t\t\t<VoiceSessionContext.Provider value={voiceSession}>\n\t\t\t\t<ThreadAgentContext.Provider value={threadAgent}>\n\t\t\t\t\t<ToolApprovalContext.Provider value={toolApproval}>\n\t\t\t\t\t\t<ToolSelectionProvider value={toolSelection}>\n\t\t\t\t\t\t\t<ToolExecutionProvider value={toolExecutionValue}>\n\t\t\t\t\t\t\t\t<ChatErrorBoundary\n\t\t\t\t\t\t\t\t\tonReset={stableReset}\n\t\t\t\t\t\t\t\t\tonStartNewThread={onStartNewThread}\n\t\t\t\t\t\t\t\t\tonError={(error, info) => {\n\t\t\t\t\t\t\t\t\t\tconsole.error('[ThreadRuntimeBridge] Chat error:', error.message)\n\t\t\t\t\t\t\t\t\t\tconsole.error('[ThreadRuntimeBridge] Component stack:', info.componentStack)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<AssistantRuntimeProvider runtime={runtime}>\n\t\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t\t</AssistantRuntimeProvider>\n\t\t\t\t\t\t\t\t</ChatErrorBoundary>\n\t\t\t\t\t\t\t</ToolExecutionProvider>\n\t\t\t\t\t\t</ToolSelectionProvider>\n\t\t\t\t\t</ToolApprovalContext.Provider>\n\t\t\t\t</ThreadAgentContext.Provider>\n\t\t\t</VoiceSessionContext.Provider>\n\t\t</VoiceSyncContext.Provider>\n\t)\n}\n\n/**\n * Provider that combines ThreadManager (thread list) and ThreadAgent (chat) functionality.\n *\n * NOTE: This component expects resolvedAuth from TicketExchangeGate.\n * Authentication should be resolved BEFORE this provider mounts.\n * Use AgentProvider which wraps this with TicketExchangeGate.\n *\n * @example\n * ```tsx\n * // This is typically used via AgentProvider, not directly.\n * // But for direct usage:\n * function ChatApp({ resolvedAuth }: { resolvedAuth: ResolvedAuth }) {\n * return (\n * <CloudflareThreadRuntimeProvider\n * resolvedAuth={resolvedAuth}\n * mcpTools={tools}\n * executeMCPTool={callTool}\n * >\n * <div className=\"flex h-screen\">\n * <Sidebar>\n * <ThreadListUI />\n * </Sidebar>\n * <Thread />\n * </div>\n * </CloudflareThreadRuntimeProvider>\n * );\n * }\n *\n * function ThreadListUI() {\n * const { startNew } = useCloudflareThread();\n * return <button onClick={() => void startNew()}>New Thread</button>;\n * }\n * ```\n */\nexport function CloudflareThreadRuntimeProvider({\n\tchildren,\n\thost,\n\tresolvedAuth,\n\tmcpTools,\n\texecuteMCPTool,\n}: CloudflareThreadRuntimeProviderProps) {\n\t// Connect to ThreadManager for thread list management\n\t// This does NOT suspend - it stays stable across thread switches\n\t// Auth is already resolved by TicketExchangeGate (no ticket exchange needed here)\n\tconst {\n\t\tcurrentThreadId,\n\t\tsetCurrentThreadId,\n\t\tthreadListAdapter,\n\t\tisInitialized,\n\t\tisReady,\n\t\tendUserId,\n\t\torganizationId,\n\t\tauthError,\n\t\tmanager,\n\t\ttoolSources,\n\t\tpolicyPluginStatus,\n\t\tpolicyEvents,\n\t\tclearPolicyEvents,\n\t} = useCloudflareThreadAdapter({\n\t\thost,\n\t\tresolvedAuth,\n\t\tmcpTools,\n\t\texecuteMCPTool,\n\t})\n\n\t// Bridge async errors to error boundary: throw during render\n\t// authError is set via useState in the adapter, so when an async error occurs,\n\t// it triggers a re-render here where we can throw synchronously\n\tif (authError) {\n\t\tthrow new AuthErrorException(authError)\n\t}\n\n\t// Reset function from ThreadRuntimeBridge (updated via callback)\n\tconst resetRef = useRef<() => Promise<void>>(async () => {})\n\tconst handleResetChange = useCallback((newReset: () => Promise<void>) => {\n\t\tresetRef.current = newReset\n\t}, [])\n\n\tconst reset = useCallback(async () => {\n\t\tawait resetRef.current()\n\t}, [])\n\n\t// Start a new thread\n\tconst onSwitchToNewThreadRef = useRef(threadListAdapter.onSwitchToNewThread)\n\tonSwitchToNewThreadRef.current = threadListAdapter.onSwitchToNewThread\n\tconst startNew = useCallback(async () => {\n\t\tawait onSwitchToNewThreadRef.current?.()\n\t}, [])\n\n\t// Extract thread data from adapter\n\tconst threads = threadListAdapter.threads ?? []\n\tconst archivedThreads = threadListAdapter.archivedThreads ?? []\n\tconst isLoading = threadListAdapter.isLoading ?? false\n\n\t// Wrap onArchive to ensure it returns Promise<void>\n\tconst onArchiveRef = useRef(threadListAdapter.onArchive)\n\tonArchiveRef.current = threadListAdapter.onArchive\n\tconst archiveThread = useCallback(async (threadId: string) => {\n\t\tawait onArchiveRef.current?.(threadId)\n\t}, [])\n\n\t// Build context value\n\tconst contextValue = useMemo<CloudflareThreadContextValue>(\n\t\t() => ({\n\t\t\tisInitialized,\n\t\t\tisReady,\n\t\t\tisLoading,\n\t\t\tendUserId,\n\t\t\torganizationId,\n\t\t\tcurrentThreadId,\n\t\t\tsetCurrentThreadId,\n\t\t\treset,\n\t\t\tstartNew,\n\t\t\tarchiveThread,\n\t\t\tthreads,\n\t\t\tarchivedThreads,\n\t\t\tauthError,\n\t\t}),\n\t\t[\n\t\t\tisInitialized,\n\t\t\tisReady,\n\t\t\tisLoading,\n\t\t\tendUserId,\n\t\t\torganizationId,\n\t\t\tcurrentThreadId,\n\t\t\tsetCurrentThreadId,\n\t\t\treset,\n\t\t\tstartNew,\n\t\t\tarchiveThread,\n\t\t\tthreads,\n\t\t\tarchivedThreads,\n\t\t\tauthError,\n\t\t],\n\t)\n\n\tconst policyPluginValue = useMemo<PolicyPluginContextValue>(\n\t\t() => ({\n\t\t\tenabled: policyPluginStatus.enabled,\n\t\t\tname: policyPluginStatus.name,\n\t\t\tevents: policyEvents,\n\t\t\tclearEvents: clearPolicyEvents,\n\t\t}),\n\t\t[policyPluginStatus.enabled, policyPluginStatus.name, policyEvents, clearPolicyEvents],\n\t)\n\n\t// CRITICAL FIX: Don't render ThreadRuntimeBridge until ThreadManager auth is complete.\n\t// This prevents ThreadAgent from connecting before ThreadManager has authenticated.\n\t//\n\t// Race condition this fixes:\n\t// 1. ThreadManager WebSocket connects\n\t// 2. onStateUpdate fires with cached threads from DO state\n\t// 3. currentThreadId is derived from cached threads\n\t// 4. Without this guard, ThreadRuntimeBridge would mount and connect to ThreadAgent\n\t// 5. Meanwhile, initContextWithTicket hasn't completed yet\n\t// 6. If auth fails, ThreadAgent would already be connected with invalid context\n\t//\n\t// With this fix: ThreadAgent only connects AFTER ThreadManager auth succeeds.\n\tif (!isInitialized) {\n\t\treturn (\n\t\t\t<CloudflareThreadContext.Provider value={contextValue}>\n\t\t\t\t<PolicyPluginContext.Provider value={policyPluginValue}>\n\t\t\t\t\t<div className=\"relative h-full w-full\">\n\t\t\t\t\t\t<ThreadRuntimeSkeleton />\n\t\t\t\t\t</div>\n\t\t\t\t</PolicyPluginContext.Provider>\n\t\t\t</CloudflareThreadContext.Provider>\n\t\t)\n\t}\n\n\treturn (\n\t\t<CloudflareThreadContext.Provider value={contextValue}>\n\t\t\t<PolicyPluginContext.Provider value={policyPluginValue}>\n\t\t\t\t<div className=\"relative h-full w-full\">\n\t\t\t\t\t<Suspense fallback={<ThreadRuntimeSkeleton />}>\n\t\t\t\t\t\t<ThreadRuntimeBridge\n\t\t\t\t\t\t\tkey={currentThreadId ?? 'disconnected'}\n\t\t\t\t\t\t\tthreadId={currentThreadId}\n\t\t\t\t\t\t\thost={host}\n\t\t\t\t\t\t\tresolvedAuth={resolvedAuth}\n\t\t\t\t\t\t\tmanager={manager}\n\t\t\t\t\t\t\tmcpTools={mcpTools}\n\t\t\t\t\t\t\texecuteMCPTool={executeMCPTool}\n\t\t\t\t\t\t\tthreadListAdapter={threadListAdapter}\n\t\t\t\t\t\t\ttoolSources={toolSources}\n\t\t\t\t\t\t\tonResetChange={handleResetChange}\n\t\t\t\t\t\t\tonStartNewThread={startNew}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</ThreadRuntimeBridge>\n\t\t\t\t\t</Suspense>\n\t\t\t\t</div>\n\t\t\t</PolicyPluginContext.Provider>\n\t\t</CloudflareThreadContext.Provider>\n\t)\n}\n","/**\n * Tool name utilities.\n *\n * Tool names are canonical across sources. Keep this helper so call sites can\n * opt into explicit normalization in one place.\n */\nexport function normalizeToolName(name: string): string {\n\treturn name\n}\n","/**\n * Formatting utilities for tool display\n *\n * Shared helpers for formatting tool names and arguments across components.\n */\n\nimport { normalizeToolName } from './tool-names'\n\n/**\n * Humanize tool name for display\n * Converts snake_case and camelCase to readable text.\n * Uses canonical tool names; no prefix stripping is applied.\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\tconst normalizedName = normalizeToolName(name)\n\n\t// Convert camelCase or snake_case to words\n\tconst words = normalizedName\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 normalizedName\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 * Cancellation message constant\n * Used when user cancels a form submission\n */\nexport const FORM_CANCELLED_MESSAGE = 'Form submission cancelled 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","/**\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\tif (!messageRuntime) {\n\t\treturn false\n\t}\n\n\tconst messageState = messageRuntime.getState()\n\tconst hasPendingPart = messageState.content.some(\n\t\t(part) =>\n\t\t\tpart.type === 'tool-call' && part.toolCallId === toolCallId && part.result === undefined\n\t)\n\tif (!hasPendingPart) {\n\t\treturn false\n\t}\n\n\ttry {\n\t\tconst partRuntime = messageRuntime.getMessagePartByToolCallId(toolCallId)\n\t\tpartRuntime.addToolResult(result)\n\t\treturn true\n\t} catch (error) {\n\t\t// Message parts can disappear between the state check and runtime lookup when voice-mode\n\t\t// threads race with the assistant-ui runtime. Treat it as a no-op so we don't crash voice mode.\n\t\tif (error instanceof Error && error.message === 'Entry not available in the store') {\n\t\t\treturn false\n\t\t}\n\t\tthrow error\n\t}\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","import { debugLog } from '../../utils/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","/**\n * Canonical realtime event and message type contracts.\n * Keep all string literals here so handler/service/hooks stay aligned.\n */\nexport const REALTIME_EVENT = {\n\tSESSION_STATE: 'session_state',\n\tSESSION_CONNECTING: 'session_connecting',\n\tSESSION_CONNECTED: 'session_connected',\n\tSESSION_CLOSED: 'session_closed',\n\tAUDIO_LEVEL: 'audio_level',\n\tUSER_TRANSCRIPT_DONE: 'user_transcript_done',\n\tASSISTANT_TRANSCRIPT: 'assistant_transcript',\n\tASSISTANT_TRANSCRIPT_DONE: 'assistant_transcript_done',\n\tTEXT: 'text',\n\tTEXT_DONE: 'text_done',\n\tTOOL_CALL_STARTED: 'tool_call_started',\n\tTOOL_CALL_COMPLETED: 'tool_call_completed',\n\tSPEECH_STARTED: 'speech_started',\n\tSPEECH_STOPPED: 'speech_stopped',\n\tAUDIO_STARTED: 'audio_started',\n\tAUDIO_STOPPED: 'audio_stopped',\n\tERROR: 'error',\n} as const\n\nexport type RealtimeEvent = (typeof REALTIME_EVENT)[keyof typeof REALTIME_EVENT]\n\nexport const REALTIME_MESSAGE = {\n\tRESPONSE_CREATED: 'response.created',\n\tRESPONSE_DONE: 'response.done',\n\tRESPONSE_CREATE: 'response.create',\n\tRESPONSE_FUNCTION_CALL_ARGUMENTS_DONE: 'response.function_call_arguments.done',\n\tRESPONSE_FUNCTION_CALL_ARGUMENTS_DELTA: 'response.function_call_arguments.delta',\n\tRESPONSE_OUTPUT_ITEM_ADDED: 'response.output_item.added',\n\tRESPONSE_OUTPUT_ITEM_DONE: 'response.output_item.done',\n\tRESPONSE_CONTENT_PART_ADDED: 'response.content_part.added',\n\tRESPONSE_CONTENT_PART_DONE: 'response.content_part.done',\n\tRESPONSE_OUTPUT_AUDIO_DELTA: 'response.output_audio.delta',\n\tRESPONSE_OUTPUT_AUDIO_DONE: 'response.output_audio.done',\n\tRESPONSE_AUDIO_DONE: 'response.audio.done',\n\tRESPONSE_AUDIO_TRANSCRIPT_DELTA: 'response.audio_transcript.delta',\n\tRESPONSE_AUDIO_TRANSCRIPT_DONE: 'response.audio_transcript.done',\n\tRESPONSE_TEXT_DELTA: 'response.text.delta',\n\tRESPONSE_TEXT_DONE: 'response.text.done',\n\tINPUT_AUDIO_BUFFER_SPEECH_STARTED: 'input_audio_buffer.speech_started',\n\tINPUT_AUDIO_BUFFER_SPEECH_STOPPED: 'input_audio_buffer.speech_stopped',\n\tINPUT_AUDIO_BUFFER_COMMITTED: 'input_audio_buffer.committed',\n\tOUTPUT_AUDIO_BUFFER_STARTED: 'output_audio_buffer.started',\n\tOUTPUT_AUDIO_BUFFER_STOPPED: 'output_audio_buffer.stopped',\n\tOUTPUT_AUDIO_BUFFER_CLEARED: 'output_audio_buffer.cleared',\n\tCONVERSATION_ITEM_CREATED: 'conversation.item.created',\n\tCONVERSATION_ITEM_TRUNCATED: 'conversation.item.truncated',\n\tCONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED:\n\t\t'conversation.item.input_audio_transcription.completed',\n\tCONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_DELTA:\n\t\t'conversation.item.input_audio_transcription.delta',\n\tCONVERSATION_ITEM_CREATE: 'conversation.item.create',\n\tSESSION_UPDATE: 'session.update',\n\tSESSION_CREATED: 'session.created',\n\tSESSION_UPDATED: 'session.updated',\n\tRATE_LIMITS_UPDATED: 'rate_limits.updated',\n\tERROR: 'error',\n} as const\n\nexport type RealtimeMessageType = (typeof REALTIME_MESSAGE)[keyof typeof REALTIME_MESSAGE]\n\nexport const AUDIO_EVENT_BY_MESSAGE = {\n\t[REALTIME_MESSAGE.OUTPUT_AUDIO_BUFFER_STARTED]: REALTIME_EVENT.AUDIO_STARTED,\n\t[REALTIME_MESSAGE.OUTPUT_AUDIO_BUFFER_STOPPED]: REALTIME_EVENT.AUDIO_STOPPED,\n\t[REALTIME_MESSAGE.RESPONSE_OUTPUT_AUDIO_DONE]: REALTIME_EVENT.AUDIO_STOPPED,\n\t[REALTIME_MESSAGE.RESPONSE_AUDIO_DONE]: REALTIME_EVENT.AUDIO_STOPPED,\n} as const\n\nexport type AudioLifecycleMessageType = keyof typeof AUDIO_EVENT_BY_MESSAGE\n\nexport const TRANSCRIPT_EVENT_BY_MESSAGE = {\n\t[REALTIME_MESSAGE.RESPONSE_AUDIO_TRANSCRIPT_DELTA]: REALTIME_EVENT.ASSISTANT_TRANSCRIPT,\n\t[REALTIME_MESSAGE.RESPONSE_AUDIO_TRANSCRIPT_DONE]: REALTIME_EVENT.ASSISTANT_TRANSCRIPT_DONE,\n\t[REALTIME_MESSAGE.RESPONSE_TEXT_DELTA]: REALTIME_EVENT.TEXT,\n\t[REALTIME_MESSAGE.RESPONSE_TEXT_DONE]: REALTIME_EVENT.TEXT_DONE,\n} as const\n\nexport type TranscriptMessageType = keyof typeof TRANSCRIPT_EVENT_BY_MESSAGE\n","/**\n * Types for OpenAI Realtime API integration\n *\n * GA API Types:\n * - GASessionConfig: Session config with nested audio object for /v1/realtime/calls\n * - TurnDetectionConfig: VAD configuration nested under audio.input\n *\n * Key GA changes from Beta:\n * - turn_detection moved from top-level to audio.input.turn_detection\n * - voice moved from top-level to audio.output.voice\n * - input_audio_transcription → audio.input.transcription\n * - Session type: 'realtime' is required\n */\n\n// ============================================================================\n// GA API Types - For /v1/realtime/calls endpoint\n// ============================================================================\n\n/**\n * Turn detection configuration (nested under audio.input in GA)\n */\nexport interface TurnDetectionConfig {\n\ttype: 'server_vad' | 'semantic_vad'\n\tthreshold?: number\n\tprefix_padding_ms?: number\n\tsilence_duration_ms?: number\n\tcreate_response?: boolean\n\tinterrupt_response?: boolean\n}\n\n/**\n * Audio transcription configuration\n */\nexport interface AudioTranscriptionConfig {\n\tmodel: 'whisper-1' | 'gpt-4o-transcribe' | 'gpt-4o-mini-transcribe' | (string & object)\n\tlanguage?: string\n}\n\n/**\n * Noise reduction configuration\n */\nexport interface NoiseReductionConfig {\n\ttype: 'near_field' | 'far_field'\n}\n\n/**\n * Audio input configuration (GA format)\n */\nexport interface AudioInputConfig {\n\tformat?: 'pcm16' | 'g711_ulaw' | 'g711_alaw'\n\tnoise_reduction?: NoiseReductionConfig\n\ttranscription?: AudioTranscriptionConfig\n\tturn_detection?: TurnDetectionConfig\n}\n\n/**\n * Audio output configuration (GA format)\n */\nexport interface AudioOutputConfig {\n\tformat?: 'pcm16' | 'g711_ulaw' | 'g711_alaw'\n\tvoice?: string\n}\n\n/**\n * Combined audio configuration (GA format)\n */\nexport interface AudioConfig {\n\tinput?: AudioInputConfig\n\toutput?: AudioOutputConfig\n}\n\n/**\n * GA Session configuration for /v1/realtime/calls endpoint\n *\n * Key differences from Beta:\n * - type: 'realtime' is required\n * - Audio settings are nested under audio.input and audio.output\n * - turn_detection is under audio.input, not top-level\n * - voice is under audio.output, not top-level\n */\nexport interface GASessionConfig {\n\ttype: 'realtime'\n\tmodel: string\n\tinstructions?: string\n\ttools?: OpenAITool[]\n\taudio?: AudioConfig\n}\n\n// ============================================================================\n// Client Configuration\n// ============================================================================\n\nexport interface RealtimeConfig {\n\tmodel?: string\n\tvoice?: string\n\tapiUrl?: string\n\ttokenEndpoint?: string\n\tinputDeviceId?: 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\n/**\n * Tool definition for OpenAI Realtime API\n * Uses snake_case to match the raw API format\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\n/**\n * @deprecated Use GASessionConfig for new GA API format\n * This interface is kept for backwards compatibility during migration\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 function isRealtimeMessage(data: unknown): data is RealtimeMessage {\n\treturn (\n\t\ttypeof data === 'object' &&\n\t\tdata !== null &&\n\t\ttypeof (data as { type?: unknown }).type === 'string'\n\t)\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\tisUserSpeaking: boolean\n\tisAssistantSpeaking: boolean\n\tisError: boolean\n\tconnectionState: 'disconnected' | 'connecting' | 'connected' | 'error'\n\taudioLevel?: AudioLevelData\n\ttranscript?: TranscriptData\n\ttoolCall?: ToolCallData\n\terror?: string\n\tinputDeviceId?: 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\targs?: Record<string, unknown>\n\tresult?: 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\t// At minimum must have name - args, result, error are optional\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","import { RESPONSE_REQUEST_DELAY_MS } from '../../utils/constants'\n\nimport {\n\tAUDIO_EVENT_BY_MESSAGE,\n\tREALTIME_EVENT,\n\tREALTIME_MESSAGE,\n\tTRANSCRIPT_EVENT_BY_MESSAGE,\n\ttype AudioLifecycleMessageType,\n\ttype TranscriptMessageType,\n} from './events'\nimport type { EventEmitter } from './event-emitter'\nimport type { ToolManager } from './tool-manager'\nimport { isRealtimeMessage, type FunctionCall, type 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 an executable function call.\n * We allow status to be omitted because some Realtime events (e.g. output_item.done) omit it.\n */\nfunction isExecutableFunctionCall(item: ResponseOutputItem): item is ResponseOutputItem & {\n\tname: string\n\tcall_id: string\n\targuments: string\n} {\n\tif (item.type !== 'function_call') return false\n\tif (typeof item.name !== 'string' || typeof item.call_id !== 'string') return false\n\n\tif (item.status === undefined) {\n\t\tconsole.warn('[MessageHandler] Function call has no status field, assuming completed:', item.name)\n\t} else if (item.status !== 'completed') {\n\t\treturn false\n\t}\n\n\treturn true\n}\n\nexport class MessageHandler {\n\tprivate isProcessingResponse = false\n\tprivate pendingFunctionCalls = new Set<string>()\n\tprivate processedFunctionCalls = 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\tconst parsed = JSON.parse(data) as unknown\n\t\t\tif (!isRealtimeMessage(parsed)) {\n\t\t\t\tconsole.warn('[MessageHandler] Received payload without valid message type:', parsed)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tmsg = parsed\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\tconsole.log('[MessageHandler] Received event:', msg.type)\n\n\t\t// Route message to appropriate handler\n\t\tswitch (msg.type) {\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_CREATED:\n\t\t\t\tthis.handleResponseCreated(msg)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_DONE:\n\t\t\t\tawait this.handleResponseDone(msg, dataChannel)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_FUNCTION_CALL_ARGUMENTS_DONE:\n\t\t\t\tthis.handleFunctionCallArguments()\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_FUNCTION_CALL_ARGUMENTS_DELTA:\n\t\t\t\t// Argument deltas stream until done event; no action needed here.\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_OUTPUT_ITEM_DONE:\n\t\t\t\tawait this.handleResponseOutputItemDone(msg, dataChannel)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.INPUT_AUDIO_BUFFER_SPEECH_STARTED:\n\t\t\tcase REALTIME_MESSAGE.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 REALTIME_MESSAGE.RESPONSE_OUTPUT_AUDIO_DELTA:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_OUTPUT_AUDIO_DONE:\n\t\t\t// Realtime event variants for audio start/stop\n\t\t\tcase REALTIME_MESSAGE.OUTPUT_AUDIO_BUFFER_STARTED:\n\t\t\tcase REALTIME_MESSAGE.OUTPUT_AUDIO_BUFFER_STOPPED:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_AUDIO_DONE:\n\t\t\t\tthis.handleAudioEvents(msg)\n\t\t\t\tbreak\n\n\t\t\t// Model audio transcript events (assistant speech -> text)\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_AUDIO_TRANSCRIPT_DELTA:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_AUDIO_TRANSCRIPT_DONE:\n\t\t\t// Text response events\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_TEXT_DELTA:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_TEXT_DONE:\n\t\t\t\tthis.handleTranscriptEvents(msg)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_COMPLETED:\n\t\t\t\tthis.handleUserTranscript(msg)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.ERROR:\n\t\t\t\tthis.handleError(msg)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.SESSION_CREATED:\n\t\t\tcase REALTIME_MESSAGE.SESSION_UPDATED:\n\t\t\t\tthis.handleSessionEvents(msg)\n\t\t\t\tbreak\n\n\t\t\tcase REALTIME_MESSAGE.CONVERSATION_ITEM_CREATED:\n\t\t\tcase REALTIME_MESSAGE.CONVERSATION_ITEM_TRUNCATED:\n\t\t\tcase REALTIME_MESSAGE.INPUT_AUDIO_BUFFER_COMMITTED:\n\t\t\tcase REALTIME_MESSAGE.OUTPUT_AUDIO_BUFFER_CLEARED:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_OUTPUT_ITEM_ADDED:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_CONTENT_PART_ADDED:\n\t\t\tcase REALTIME_MESSAGE.RESPONSE_CONTENT_PART_DONE:\n\t\t\tcase REALTIME_MESSAGE.CONVERSATION_ITEM_INPUT_AUDIO_TRANSCRIPTION_DELTA:\n\t\t\tcase REALTIME_MESSAGE.RATE_LIMITS_UPDATED:\n\t\t\t\t// Log only, no action needed\n\t\t\t\tbreak\n\n\t\t\tdefault:\n\t\t\t\tconsole.log('[MessageHandler] Unhandled event type:', msg.type, msg)\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(isExecutableFunctionCall)\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(isExecutableFunctionCall)\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\tawait this.executeFunctionCallIfNeeded(functionCall, dataChannel)\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\tprivate async handleResponseOutputItemDone(\n\t\tmsg: RealtimeMessage,\n\t\tdataChannel: RTCDataChannel\n\t): Promise<void> {\n\t\tconst item = msg.item\n\t\tif (!item || typeof item !== 'object') {\n\t\t\tconsole.warn('[MessageHandler] response.output_item.done missing or invalid item:', msg.type)\n\t\t\treturn\n\t\t}\n\n\t\tconst outputItem = item as ResponseOutputItem\n\t\tif (!isExecutableFunctionCall(outputItem)) return\n\n\t\tawait this.executeFunctionCallIfNeeded(\n\t\t\t{\n\t\t\t\tname: outputItem.name,\n\t\t\t\tcall_id: outputItem.call_id,\n\t\t\t\targuments: outputItem.arguments ?? '',\n\t\t\t},\n\t\t\tdataChannel\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// No-op; execution is triggered in handleResponseDone and handleResponseOutputItemDone.\n\t}\n\n\tprivate handleSpeechEvents(msg: RealtimeMessage): void {\n\t\tconst eventType =\n\t\t\tmsg.type === REALTIME_MESSAGE.INPUT_AUDIO_BUFFER_SPEECH_STARTED\n\t\t\t\t? REALTIME_EVENT.SPEECH_STARTED\n\t\t\t\t: REALTIME_EVENT.SPEECH_STOPPED\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate handleAudioEvents(msg: RealtimeMessage): void {\n\t\tif (!Object.hasOwn(AUDIO_EVENT_BY_MESSAGE, msg.type)) {\n\t\t\t// response.output_audio.delta fires per chunk; not a lifecycle event.\n\t\t\treturn\n\t\t}\n\t\tconst eventType = AUDIO_EVENT_BY_MESSAGE[msg.type as AudioLifecycleMessageType]\n\t\tconsole.log(`[MessageHandler] Assistant ${eventType}`, {\n\t\t\ttype: msg.type,\n\t\t})\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate async executeFunctionCallIfNeeded(\n\t\tfunctionCall: FunctionCall,\n\t\tdataChannel: RTCDataChannel\n\t): Promise<void> {\n\t\tif (this.processedFunctionCalls.has(functionCall.call_id)) {\n\t\t\t// Duplicate events are expected (e.g. output_item.done then response.done).\n\t\t\treturn\n\t\t}\n\t\tif (this.pendingFunctionCalls.has(functionCall.call_id)) {\n\t\t\t// Already being processed from a prior event for this call_id.\n\t\t\treturn\n\t\t}\n\n\t\tthis.pendingFunctionCalls.add(functionCall.call_id)\n\t\tthis.processedFunctionCalls.add(functionCall.call_id)\n\t\tawait this.executeFunctionCall(functionCall, dataChannel)\n\t}\n\n\tprivate handleTranscriptEvents(msg: RealtimeMessage): void {\n\t\tif (!Object.hasOwn(TRANSCRIPT_EVENT_BY_MESSAGE, msg.type)) {\n\t\t\treturn\n\t\t}\n\t\tconst eventType = TRANSCRIPT_EVENT_BY_MESSAGE[msg.type as TranscriptMessageType]\n\t\tconst delta = typeof msg.delta === 'string' ? msg.delta : undefined\n\t\tconst transcript = typeof msg.transcript === 'string' ? msg.transcript : undefined\n\t\tconsole.log('[MessageHandler] Transcript event:', msg.type, {\n\t\t\teventType,\n\t\t\tdelta,\n\t\t\ttranscript,\n\t\t})\n\t\tthis.eventEmitter.emit(eventType, msg)\n\t}\n\n\tprivate handleUserTranscript(msg: RealtimeMessage): void {\n\t\tif (typeof msg.transcript !== 'string') {\n\t\t\tconsole.warn('[MessageHandler] user transcript completion missing transcript text')\n\t\t\treturn\n\t\t}\n\t\tthis.eventEmitter.emit(REALTIME_EVENT.USER_TRANSCRIPT_DONE, { text: msg.transcript })\n\t}\n\n\tprivate handleSessionEvents(msg: RealtimeMessage): void {\n\t\t// Log session configuration for debugging\n\t\tif (!msg.session || typeof msg.session !== 'object') {\n\t\t\treturn\n\t\t}\n\t\tconst session = msg.session as Record<string, unknown>\n\t\tconst tools = Array.isArray(session.tools) ? session.tools : []\n\t\tconst toolNames = tools\n\t\t\t.slice(0, 5)\n\t\t\t.map((tool) =>\n\t\t\t\ttool && typeof tool === 'object' && typeof (tool as { name?: unknown }).name === 'string'\n\t\t\t\t\t? (tool as { name: string }).name\n\t\t\t\t\t: undefined\n\t\t\t)\n\t\t\t.filter((name): name is string => typeof name === 'string')\n\n\t\tconsole.log('[MessageHandler] Session event:', msg.type, {\n\t\t\ttoolCount: tools.length,\n\t\t\ttoolNames,\n\t\t\thasInputTranscription: !!session.input_audio_transcription,\n\t\t})\n\t}\n\n\tprivate handleError(msg: RealtimeMessage): void {\n\t\tconsole.error('Realtime API error:', msg)\n\t\tthis.eventEmitter.emit(REALTIME_EVENT.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, arguments: argsString } = functionCall\n\t\tconsole.log('[MessageHandler] Executing function call', {\n\t\t\tname,\n\t\t\tcallId: call_id,\n\t\t\targsLength: argsString?.length ?? 0,\n\t\t})\n\n\t\t// Parse args for event emission\n\t\tlet parsedArgs: Record<string, unknown> = {}\n\t\ttry {\n\t\t\tparsedArgs = argsString ? JSON.parse(argsString) : {}\n\t\t} catch (parseError) {\n\t\t\tconsole.warn(`[MessageHandler] Failed to parse function call arguments for ${name}:`, {\n\t\t\t\terror: parseError,\n\t\t\t\targsLength: argsString?.length ?? 0,\n\t\t\t\targsSample: argsString?.slice(0, 200),\n\t\t\t})\n\t\t}\n\n\t\ttry {\n\t\t\t// Emit start event\n\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.TOOL_CALL_STARTED, { name })\n\n\t\t\t// Execute tool\n\t\t\tconst result = await this.toolManager.executeToolCall(functionCall)\n\t\t\tconsole.log('[MessageHandler] Function call finished', {\n\t\t\t\tname,\n\t\t\t\tcallId: call_id,\n\t\t\t\tsuccess: result.success,\n\t\t\t\terror: result.error,\n\t\t\t})\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(REALTIME_EVENT.TOOL_CALL_COMPLETED, {\n\t\t\t\t\tname,\n\t\t\t\t\targs: parsedArgs,\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// Format result as string for both event emission and sending back\n\t\t\tconst resultString = JSON.stringify(\n\t\t\t\tresult.success\n\t\t\t\t\t? result.data\n\t\t\t\t\t: {\n\t\t\t\t\t\t\terror: result.error,\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t}\n\t\t\t)\n\n\t\t\t// Send result back\n\t\t\tconst response = {\n\t\t\t\ttype: REALTIME_MESSAGE.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: resultString,\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 with full data for backend sync\n\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.TOOL_CALL_COMPLETED, {\n\t\t\t\tname,\n\t\t\t\targs: parsedArgs,\n\t\t\t\tresult: resultString,\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\n\t\t\t// Emit completion event for backend sync (error case)\n\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.TOOL_CALL_COMPLETED, {\n\t\t\t\tname,\n\t\t\t\targs: parsedArgs,\n\t\t\t\tresult: JSON.stringify({ error: String(error), success: false }),\n\t\t\t\terror: String(error),\n\t\t\t})\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: REALTIME_MESSAGE.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: REALTIME_MESSAGE.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\t\tthis.processedFunctionCalls.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\tconsole.log(\n\t\t\t'[ToolManager] setTools called:',\n\t\t\ttools.length,\n\t\t\t'tools,',\n\t\t\t'signature:',\n\t\t\tthis.getToolSignature(tools).slice(0, 100)\n\t\t)\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\tconst changed = currentSignature !== this.lastSentToolSignature\n\t\tconsole.log('[ToolManager] hasToolsChanged:', changed, {\n\t\t\tcurrentSignatureLength: currentSignature.length,\n\t\t\tlastSentSignatureLength: this.lastSentToolSignature.length,\n\t\t\tcurrentFirst50: currentSignature.slice(0, 50),\n\t\t\tlastSentFirst50: this.lastSentToolSignature.slice(0, 50),\n\t\t})\n\t\treturn changed\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 '../../utils/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\t/**\n\t * Create a WebRTC session with OpenAI's Realtime API\n\t *\n\t * Uses the standard WebRTC endpoint with raw SDP body.\n\t * Session configuration is sent via session.update over the data channel.\n\t *\n\t * @param config - Basic configuration (model, voice, API URL)\n\t */\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\t\tconst inputDeviceId = config.inputDeviceId\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(inputDeviceId)\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\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(inputDeviceId?: string): Promise<MediaStream> {\n\t\ttry {\n\t\t\tconst deviceConstraint =\n\t\t\t\tinputDeviceId && inputDeviceId.length > 0 ? { exact: inputDeviceId } : undefined\n\n\t\t\treturn await navigator.mediaDevices.getUserMedia({\n\t\t\t\taudio: {\n\t\t\t\t\t...(deviceConstraint ? { deviceId: deviceConstraint } : {}),\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\t/**\n\t * Connect to OpenAI's Realtime API\n\t *\n\t * Uses raw SDP body with Content-Type: application/sdp\n\t * Model is passed as query parameter\n\t */\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\tdebugLog('WebRTC', 'Connecting to OpenAI Realtime API', {\n\t\t\tendpoint: `${baseUrl}?model=${model}`,\n\t\t})\n\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\tconst errorText = await response.text()\n\t\t\tconsole.error('[WebRTC] API connection failed:', response.status, errorText)\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\tREALTIME_DEFAULT_VOICE,\n} from '../../utils/constants'\nimport { AudioAnalyzer } from './audio-analyzer'\nimport { EventEmitter } from './event-emitter'\nimport { REALTIME_EVENT, REALTIME_MESSAGE } from './events'\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 } 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\tprivate pendingConfig: RealtimeConfig = {}\n\tprivate inputDeviceId: string | undefined\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\tconsole.log(\n\t\t\t'[OpenAIRealtimeService] setTools called with',\n\t\t\ttools.length,\n\t\t\t'tools:',\n\t\t\ttools.slice(0, 5).map((t) => t.name).join(', '),\n\t\t\ttools.length > 5 ? `... and ${tools.length - 5} more` : ''\n\t\t)\n\t\tthis.toolManager.setTools(tools)\n\t\tif (this.isSessionActive()) {\n\t\t\tconsole.log('[OpenAIRealtimeService] Session is active, updating tools')\n\t\t\tthis.updateSessionTools()\n\t\t} else {\n\t\t\tconsole.log('[OpenAIRealtimeService] Session not active yet, tools will be included at session start')\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\t * Session configuration is sent via session.update over the data channel\n\t * using GA format (nested audio structure)\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// Store config for use in configureSession\n\t\t\tthis.pendingConfig = {\n\t\t\t\t...config,\n\t\t\t\tinputDeviceId: config.inputDeviceId ?? this.inputDeviceId,\n\t\t\t}\n\t\t\tthis.inputDeviceId = this.pendingConfig.inputDeviceId\n\n\t\t\t// Create new WebRTC session\n\t\t\tthis.session = await this.webrtcManager.createSession(this.pendingConfig)\n\n\t\t\t// Setup data channel handlers\n\t\t\t// configureSession() is called when channel opens\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\tthis.initializeRemoteAnalyzerSafely(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\tthis.initializeRemoteAnalyzerSafely(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: REALTIME_MESSAGE.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: REALTIME_MESSAGE.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 assistant audio playback mute.\n\t * Note: this mutes the speaker (remote audio element), not the outbound microphone.\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 * Set the microphone input device.\n\t * If a session is active, replaces the outbound audio track via replaceTrack()\n\t * without reconnecting, stops the previous stream, and reinitializes the local\n\t * audio analyzer. The device ID is persisted for future sessions.\n\t */\n\tasync setInputDevice(deviceId: string): Promise<void> {\n\t\tif (!this.session) {\n\t\t\t// No active session — just store the preference for the next session.\n\t\t\tthis.inputDeviceId = deviceId\n\t\t\tthis.pendingConfig = { ...this.pendingConfig, inputDeviceId: deviceId }\n\t\t\treturn\n\t\t}\n\n\t\tconst stream = await navigator.mediaDevices.getUserMedia({\n\t\t\taudio: {\n\t\t\t\tdeviceId: { exact: deviceId },\n\t\t\t\techoCancellation: true,\n\t\t\t\tnoiseSuppression: true,\n\t\t\t\tautoGainControl: true,\n\t\t\t},\n\t\t})\n\n\t\tconst nextTrack = stream.getAudioTracks()[0]\n\t\tif (!nextTrack) {\n\t\t\tstream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t\tthrow new Error('Selected microphone did not provide an audio track')\n\t\t}\n\n\t\tconst sender = this.session.pc\n\t\t\t.getSenders()\n\t\t\t.find((s) => s.track?.kind === 'audio')\n\n\t\tif (!sender) {\n\t\t\tstream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t\tthrow new Error('No outbound audio sender available')\n\t\t}\n\n\t\ttry {\n\t\t\tawait sender.replaceTrack(nextTrack)\n\t\t} catch (error) {\n\t\t\tstream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t\tthrow new Error(`Failed to replace audio track: ${error}`)\n\t\t}\n\n\t\t// Track replacement succeeded — now commit the device ID and swap streams.\n\t\tthis.inputDeviceId = deviceId\n\t\tthis.pendingConfig = { ...this.pendingConfig, inputDeviceId: deviceId }\n\n\t\tconst oldStream = this.session.localStream\n\t\tthis.session.localStream = stream\n\t\tif (oldStream) {\n\t\t\toldStream.getTracks().forEach((track) => {\n\t\t\t\ttrack.stop()\n\t\t\t})\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.initializeLocalAnalyzer(stream)\n\t\t} catch (error) {\n\t\t\t// Non-fatal: audio still works, just visualization may be broken.\n\t\t\tconsole.error('[OpenAIRealtimeService] Failed to reinitialize audio analyzer after device switch:', error)\n\t\t}\n\t}\n\n\tgetInputDeviceId(): string | undefined {\n\t\treturn this.inputDeviceId\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 using GA format\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\tthis.messageHandler.handleMessage(event.data, dataChannel).catch((error) => {\n\t\t\t\tconsole.error('Error handling message:', error)\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(REALTIME_EVENT.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(REALTIME_EVENT.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(REALTIME_EVENT.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 initializeRemoteAnalyzerSafely(remoteStream: MediaStream): void {\n\t\tthis.initializeRemoteAnalyzer(remoteStream).catch((error) => {\n\t\t\t// Non-fatal: audio can continue even if visualization setup fails.\n\t\t\tconsole.warn('[OpenAIRealtimeService] Failed to initialize remote analyzer:', error)\n\t\t})\n\t}\n\n\t/**\n\t * Configure session using session.update over data channel\n\t *\n\t * Note: The /v1/realtime endpoint (used for browser WebRTC with ephemeral keys)\n\t * still uses the beta session.update format with top-level fields.\n\t */\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\tconsole.log(\n\t\t\t'[OpenAIRealtimeService] Configuring session:',\n\t\t\ttools.length,\n\t\t\t'tools'\n\t\t)\n\n\t\t// Beta format session config (used by /v1/realtime endpoint)\n\t\tconst sessionConfig = {\n\t\t\tmodalities: ['text', 'audio'],\n\t\t\tinstructions: this.getSessionInstructions(),\n\t\t\tvoice: this.pendingConfig.voice || REALTIME_DEFAULT_VOICE,\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.7,\n\t\t\t\tprefix_padding_ms: 200,\n\t\t\t\tsilence_duration_ms: 800,\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: REALTIME_MESSAGE.SESSION_UPDATE,\n\t\t\tsession: sessionConfig,\n\t\t}\n\n\t\tdataChannel.send(JSON.stringify(sessionUpdate))\n\t\tconsole.log('[OpenAIRealtimeService] session.update sent')\n\t}\n\n\t/**\n\t * Update session tools mid-session using session.update over data channel\n\t *\n\t * GA API Note: session.update format is the same as the initial session config\n\t * but we only send the fields we want to update (tools in this case)\n\t */\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\tconsole.log('[OpenAIRealtimeService] updateSessionTools: No changes detected, skipping update')\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\t// GA API: session.update uses the same nested structure\n\t\tconst sessionUpdate = {\n\t\t\ttype: REALTIME_MESSAGE.SESSION_UPDATE,\n\t\t\tsession: {\n\t\t\t\ttools: tools,\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(REALTIME_EVENT.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(REALTIME_EVENT.SESSION_STATE, payload)\n\n\t\tswitch (state) {\n\t\t\tcase 'connecting':\n\t\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.SESSION_CONNECTING, payload)\n\t\t\t\tbreak\n\t\t\tcase 'connected':\n\t\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.SESSION_CONNECTED, payload)\n\t\t\t\tbreak\n\t\t\tcase 'disconnected':\n\t\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.SESSION_CLOSED, payload)\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tthis.eventEmitter.emit(REALTIME_EVENT.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 * 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 '../utils/constants'\nimport {\n\tREALTIME_EVENT,\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\t/**\n\t * Callback when a tool call is completed (success or error).\n\t * Used for backend-first sync of voice tool calls.\n\t */\n\tonToolComplete?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t\tresult: string,\n\t\tisError: boolean,\n\t) => 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 assistant audio playback 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\t/** Set microphone input device */\n\tsetInputDevice: (deviceId: string) => Promise<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\tonToolComplete,\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 [isUserSpeaking, setIsUserSpeaking] = useState(false)\n\tconst [isAssistantSpeaking, setIsAssistantSpeaking] = useState(false)\n\tconst [isError, setIsError] = useState(false)\n\tconst [connectionState, setConnectionState] = useState<VoiceModeState['connectionState']>('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\tconst [inputDeviceId, setInputDeviceId] = 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\tconst onToolCompleteRef = useRef(onToolComplete)\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\tonToolCompleteRef.current = onToolComplete\n\t}, [onConnect, onDisconnect, onError, onUserTranscript, onAssistantTranscript, onToolComplete])\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\tsetIsUserSpeaking(false)\n\t\t\t\tsetIsAssistantSpeaking(false)\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// Fire callback for backend-first sync. Always emit, even if the realtime\n\t\t\t// payload omits args/result (e.g. transport edge cases), to avoid dropping\n\t\t\t// server-authoritative thread updates.\n\t\t\tconst normalizedArgs = data.args ?? {}\n\t\t\tif (!data.args) {\n\t\t\t\tconsole.warn(`[useVoiceMode] Tool call '${data.name}' completed without args, using empty object`)\n\t\t\t}\n\t\t\tconst normalizedResult =\n\t\t\t\ttypeof data.result === 'string'\n\t\t\t\t\t? data.result\n\t\t\t\t\t: JSON.stringify(\n\t\t\t\t\t\t\tdata.error\n\t\t\t\t\t\t\t\t? { error: data.error, success: false }\n\t\t\t\t\t\t\t\t: { success: true }\n\t\t\t\t\t\t)\n\t\t\tif (typeof data.result !== 'string') {\n\t\t\t\tconsole.warn(`[useVoiceMode] Tool call '${data.name}' completed without result string, synthesizing from error state`)\n\t\t\t}\n\n\t\t\tonToolCompleteRef.current?.(\n\t\t\t\tdata.name,\n\t\t\t\tnormalizedArgs,\n\t\t\t\tnormalizedResult,\n\t\t\t\t!!data.error,\n\t\t\t)\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\tconst handleUserSpeechStarted = () => {\n\t\t\tsetIsUserSpeaking(true)\n\t\t}\n\n\t\tconst handleUserSpeechStopped = () => {\n\t\t\tsetIsUserSpeaking(false)\n\t\t}\n\n\t\tconst handleAssistantAudioStarted = () => {\n\t\t\tsetIsAssistantSpeaking(true)\n\t\t}\n\n\t\tconst handleAssistantAudioStopped = () => {\n\t\t\tsetIsAssistantSpeaking(false)\n\t\t}\n\n\t\t// Register listeners\n\t\tservice.on(REALTIME_EVENT.SESSION_STATE, handleSessionState)\n\t\tservice.on(REALTIME_EVENT.AUDIO_LEVEL, handleAudioLevel)\n\t\tservice.on(REALTIME_EVENT.USER_TRANSCRIPT_DONE, handleUserTranscript)\n\t\tservice.on(REALTIME_EVENT.ASSISTANT_TRANSCRIPT, handleAssistantTranscript)\n\t\tservice.on(REALTIME_EVENT.ASSISTANT_TRANSCRIPT_DONE, handleAssistantTranscriptDone)\n\t\tservice.on(REALTIME_EVENT.TOOL_CALL_STARTED, handleToolCallStarted)\n\t\tservice.on(REALTIME_EVENT.TOOL_CALL_COMPLETED, handleToolCallCompleted)\n\t\tservice.on(REALTIME_EVENT.SPEECH_STARTED, handleUserSpeechStarted)\n\t\tservice.on(REALTIME_EVENT.SPEECH_STOPPED, handleUserSpeechStopped)\n\t\tservice.on(REALTIME_EVENT.AUDIO_STARTED, handleAssistantAudioStarted)\n\t\tservice.on(REALTIME_EVENT.AUDIO_STOPPED, handleAssistantAudioStopped)\n\t\tservice.on(REALTIME_EVENT.ERROR, handleError)\n\n\t\t// Cleanup\n\t\treturn () => {\n\t\t\tservice.off(REALTIME_EVENT.SESSION_STATE, handleSessionState)\n\t\t\tservice.off(REALTIME_EVENT.AUDIO_LEVEL, handleAudioLevel)\n\t\t\tservice.off(REALTIME_EVENT.USER_TRANSCRIPT_DONE, handleUserTranscript)\n\t\t\tservice.off(REALTIME_EVENT.ASSISTANT_TRANSCRIPT, handleAssistantTranscript)\n\t\t\tservice.off(REALTIME_EVENT.ASSISTANT_TRANSCRIPT_DONE, handleAssistantTranscriptDone)\n\t\t\tservice.off(REALTIME_EVENT.TOOL_CALL_STARTED, handleToolCallStarted)\n\t\t\tservice.off(REALTIME_EVENT.TOOL_CALL_COMPLETED, handleToolCallCompleted)\n\t\t\tservice.off(REALTIME_EVENT.SPEECH_STARTED, handleUserSpeechStarted)\n\t\t\tservice.off(REALTIME_EVENT.SPEECH_STOPPED, handleUserSpeechStopped)\n\t\t\tservice.off(REALTIME_EVENT.AUDIO_STARTED, handleAssistantAudioStarted)\n\t\t\tservice.off(REALTIME_EVENT.AUDIO_STOPPED, handleAssistantAudioStopped)\n\t\t\tservice.off(REALTIME_EVENT.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\tsetIsUserSpeaking(false)\n\t\tsetIsAssistantSpeaking(false)\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\tconst setInputDevice = useCallback(\n\t\tasync (deviceId: string) => {\n\t\t\tconst service = getService()\n\t\t\tawait service.setInputDevice(deviceId)\n\t\t\tsetInputDeviceId(deviceId)\n\t\t},\n\t\t[getService]\n\t)\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\tisUserSpeaking,\n\t\t\tisAssistantSpeaking,\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\tinputDeviceId,\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\tsetInputDevice,\n\t\t}),\n\t\t[\n\t\t\tisActive,\n\t\t\tisConnecting,\n\t\t\tisMuted,\n\t\t\tisUserSpeaking,\n\t\t\tisAssistantSpeaking,\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\tinputDeviceId,\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\tsetInputDevice,\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\t/**\n\t * Callback when a tool call is completed (success or error).\n\t * Used for backend-first sync of voice tool calls.\n\t */\n\tonToolComplete?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t\tresult: string,\n\t\tisError: boolean,\n\t) => 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\tonToolComplete,\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\tonToolComplete,\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 '../utils/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 { useThread, useThreadRuntime } from '@assistant-ui/react'\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { VOICE_TOOL_RESULT_MESSAGES } from '../utils/constants'\nimport { TOOL_DENIED_MESSAGE } from '../utils/format'\nimport {\n\tgetPendingToolCallsByName,\n\tresolveAllPendingToolCalls,\n\tresolveAllPendingToolCallsByName,\n\tresolvePendingToolCall,\n} from '../utils/thread-utils'\nimport { useThreadAgent } from './CloudflareThreadRuntimeProvider'\nimport { useOptionalMCPTools } from './MCPToolsProvider'\nimport { useOptionalToolApproval } from './ToolApprovalContext'\nimport { useOptionalVoiceModeContext, VoiceModeProvider } from './VoiceModeProvider'\nimport {\n\tuseOptionalVoiceToolApproval,\n\tVoiceToolApprovalProvider,\n} from './VoiceToolApprovalProvider'\n\nimport { isToolDestructive, type ToolCallMetadata, type ToolWithSource } from '@mcp-b/shared-types'\nimport type { FC, MutableRefObject, ReactNode, RefObject } 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 user is currently speaking */\n\tisUserSpeaking: boolean\n\t/** Whether assistant is currently speaking */\n\tisAssistantSpeaking: 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 assistant audio playback 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/** Set microphone input device */\n\tsetInputDevice: (deviceId: string) => Promise<void>\n\t/** Selected microphone input device ID */\n\tinputDeviceId?: string\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\t/**\n\t * Callback when user transcript is complete.\n\t * Used for backend-first sync to ThreadAgent DO.\n\t */\n\tonUserTranscript?: (text: string) => void\n\t/**\n\t * Callback when assistant transcript is complete.\n\t * Used for backend-first sync to ThreadAgent DO.\n\t */\n\tonAssistantTranscript?: (text: string) => void\n\t/**\n\t * Callback when tool call completes.\n\t * Used for backend-first sync to ThreadAgent DO.\n\t */\n\tonToolComplete?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t\tresult: string,\n\t\tisError: boolean,\n\t) => 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\t\tuseEffect(() => {\n\t\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\t}\n\n\t\t\t\t// Append complete tool-call message to thread\n\t\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\t\tresult: data.result,\n\t\t\t\t\t\t\tisError: data.isError,\n\t\t\t\t\t\t\tartifact: data.artifact,\n\t\t\t\t\t\t} as any,\n\t\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\t\ttimestamp: Date.now(),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t})\n\t\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\tconst metadata = {\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\tconst metadata = {\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: RefObject<AddToolCallToThread | null>\n\tonConnect?: () => void\n\tonDisconnect?: (durationSeconds: number) => void\n\tonError?: (error: string) => void\n\tonUserTranscript?: (text: string) => void\n\tonAssistantTranscript?: (text: string) => void\n\tonToolComplete?: (\n\t\ttoolName: string,\n\t\targs: Record<string, unknown>,\n\t\tresult: string,\n\t\tisError: boolean,\n\t) => void\n}> = ({\n\tchildren,\n\ttokenEndpoint,\n\tvoiceTools,\n\tsessionId,\n\tsetSessionId,\n\taddToolCallRef,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n\tonUserTranscript,\n\tonAssistantTranscript,\n\tonToolComplete,\n}) => {\n\tconst mcpTools = useOptionalMCPTools()\n\tconst toolApproval = useOptionalToolApproval()\n\tconst voiceToolApproval = useOptionalVoiceToolApproval()\n\tconst threadRuntime = useThreadRuntime()\n\tconst threadMessages = useThread((t) => t.messages)\n\tconst threadAgent = useThreadAgent()\n\n\t// Always include handoff tool alongside MCP tools\n\tconst allVoiceTools = useMemo<RegisteredTool[]>(() => {\n\t\treturn [\n\t\t\t...voiceTools,\n\t\t\t{\n\t\t\t\tname: 'start_human_handoff',\n\t\t\t\tdescription:\n\t\t\t\t\t'Hand off to a human support agent for live voice assistance. Call this when the user needs help beyond what you can provide, or when they explicitly ask to speak with a person.',\n\t\t\t\tinputSchema: { type: 'object', properties: {}, required: [] },\n\t\t\t},\n\t\t]\n\t}, [voiceTools])\n\n\t// Log warnings for missing optional contexts (fail loudly principle)\n\tif (!mcpTools) {\n\t\tconsole.warn('[ApprovalAwareVoiceBridge] mcpTools not available - voice tool execution will be disabled')\n\t}\n\tif (!toolApproval) {\n\t\tconsole.warn('[ApprovalAwareVoiceBridge] toolApproval not available - approval checks will be skipped')\n\t}\n\tif (!voiceToolApproval) {\n\t\tconsole.warn('[ApprovalAwareVoiceBridge] voiceToolApproval not available - voice approval flow disabled')\n\t}\n\n\t// Track voice approval decisions keyed by tool name with a queue of decisions\n\t// so multiple approvals for the same tool don't collide when replaying.\n\tconst pendingVoiceResolutions = useRef<Map<string, Array<{ result: string; timestamp: number }>>>(\n\t\tnew Map()\n\t)\n\tconst VOICE_RESOLUTION_TTL_MS = 30_000\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\t// Handle handoff tool — calls backend RPC to create RealtimeKit meeting\n\t\t\tif (name === 'start_human_handoff') {\n\t\t\t\tif (threadAgent.readyState !== WebSocket.OPEN) {\n\t\t\t\t\tthrow new Error('Not connected to support server')\n\t\t\t\t}\n\t\t\t\tawait threadAgent.stub.startHumanHandoff()\n\t\t\t\treturn 'Connecting to a human support agent now.'\n\t\t\t}\n\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 (v6 pattern)\n\t\t\tconst tool = mcpTools.tools.find((t) => t.name === name)\n\t\t\tconst needsApproval = tool && toolApproval\n\t\t\t\t? toolApproval.mode !== 'auto' && isToolDestructive(tool.annotations)\n\t\t\t\t: false\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\tconst resolvedNow = resolveAllPendingToolCallsByName(threadRuntime, name, resultMessage)\n\n\t\t\t\t// If nothing was resolved (pending call hasn't reached the thread yet), remember it\n\t\t\t\t// so we can auto-resolve when the pending tool-call message appears.\n\t\t\t\tif (resolvedNow === 0) {\n\t\t\t\t\tconst queue = pendingVoiceResolutions.current.get(name) ?? []\n\t\t\t\t\tqueue.push({ result: resultMessage, timestamp: Date.now() })\n\t\t\t\t\tpendingVoiceResolutions.current.set(name, queue)\n\t\t\t\t}\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, threadAgent]\n\t)\n\n\t// Apply queued voice approvals once the thread emits matching pending tool calls.\n\tuseEffect(() => {\n\t\tif (pendingVoiceResolutions.current.size === 0) return\n\n\t\tconst now = Date.now()\n\t\tfor (const [toolName, queue] of [...pendingVoiceResolutions.current.entries()]) {\n\t\t\tconst freshQueue = queue.filter(({ timestamp }) => now - timestamp <= VOICE_RESOLUTION_TTL_MS)\n\t\t\tif (freshQueue.length === 0) {\n\t\t\t\tpendingVoiceResolutions.current.delete(toolName)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst pendingCalls = getPendingToolCallsByName(threadRuntime, toolName)\n\n\t\t\t// Resolve approvals in FIFO order against pending calls\n\t\t\tlet queueIndex = 0\n\t\t\tfor (const call of pendingCalls) {\n\t\t\t\tif (queueIndex >= freshQueue.length) break\n\t\t\t\tconst { result } = freshQueue[queueIndex]\n\t\t\t\tif (resolvePendingToolCall(threadRuntime, call.messageId, call.toolCallId, result)) {\n\t\t\t\t\tqueueIndex++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (queueIndex >= freshQueue.length) {\n\t\t\t\tpendingVoiceResolutions.current.delete(toolName)\n\t\t\t} else {\n\t\t\t\tpendingVoiceResolutions.current.set(toolName, freshQueue.slice(queueIndex))\n\t\t\t}\n\t\t}\n\t}, [threadMessages, threadRuntime])\n\n\treturn (\n\t\t<VoiceModeProvider\n\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\ttools={allVoiceTools}\n\t\t\ttoolExecutor={toolExecutor}\n\t\t\tonUserTranscript={onUserTranscript}\n\t\t\tonAssistantTranscript={onAssistantTranscript}\n\t\t\tonToolComplete={onToolComplete}\n\t\t>\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\tonUserTranscript,\n\tonAssistantTranscript,\n\tonToolComplete,\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\tonUserTranscript={onUserTranscript}\n\t\t\t\tonAssistantTranscript={onAssistantTranscript}\n\t\t\t\tonToolComplete={onToolComplete}\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\tisUserSpeaking: voiceMode.isUserSpeaking,\n\t\t\tisAssistantSpeaking: voiceMode.isAssistantSpeaking,\n\t\t\tisSupported: voiceMode.isSupported,\n\t\t\terror: voiceMode.error,\n\t\t\tsessionId,\n\t\t\tinputDeviceId: voiceMode.inputDeviceId,\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\tsetInputDevice: voiceMode.setInputDevice,\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","import { Button } from '@/components/ui/button'\nimport { useVoiceThread } from '@/providers/VoiceThreadBridge'\nimport { useVoiceToolApproval } from '@/providers/VoiceToolApprovalProvider'\nimport { cn } from '@/utils/cn'\nimport { humanizeToolName } from '@/utils/format'\nimport { Check, X } from 'lucide-react'\nimport { useEffect, useMemo, useRef, type FC } from 'react'\n\ninterface VoiceToolApprovalPanelProps {\n\tvariant?: 'card' | 'composer'\n}\n\nconst VoiceToolApprovalPanel: FC<VoiceToolApprovalPanelProps> = ({ variant = 'card' }) => {\n\tconst voiceApproval = useVoiceToolApproval()\n\tconst voiceThread = useVoiceThread()\n\tconst wasWaitingRef = useRef(false)\n\n\tconst { isWaitingForApproval: isWaiting, pendingApproval, timeoutRemaining, approve, deny } =\n\t\tvoiceApproval\n\n\t// Pause assistant audio playback while the approval prompt is visible,\n\t// so the assistant's voice doesn't talk over the user's decision.\n\tuseEffect(() => {\n\t\tif (!wasWaitingRef.current && isWaiting) {\n\t\t\tvoiceThread.pauseAudio()\n\t\t} else if (wasWaitingRef.current && !isWaiting) {\n\t\t\tvoiceThread.resumeAudio()\n\t\t}\n\n\t\twasWaitingRef.current = isWaiting\n\t\treturn () => {\n\t\t\tif (wasWaitingRef.current) {\n\t\t\t\tvoiceThread.resumeAudio()\n\t\t\t}\n\t\t}\n\t}, [isWaiting, voiceThread])\n\n\t// Keyboard shortcuts: Enter approves, Escape denies.\n\t// Disabled when focus is inside text inputs to avoid accidental approval while typing.\n\tuseEffect(() => {\n\t\tif (!isWaiting) return\n\t\tif (typeof window === 'undefined') return\n\n\t\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\t\tconst target = event.target as HTMLElement | null\n\t\t\tconst isTypingTarget =\n\t\t\t\ttarget?.tagName === 'INPUT' ||\n\t\t\t\ttarget?.tagName === 'TEXTAREA' ||\n\t\t\t\ttarget?.isContentEditable\n\t\t\tif (isTypingTarget) return\n\n\t\t\tif (event.key === 'Enter') {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tapprove()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (event.key === 'Escape') {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tdeny()\n\t\t\t}\n\t\t}\n\n\t\twindow.addEventListener('keydown', handleKeyDown)\n\t\treturn () => window.removeEventListener('keydown', handleKeyDown)\n\t}, [isWaiting, approve, deny])\n\n\tconst argsPreview = useMemo(() => {\n\t\tif (!pendingApproval) return ''\n\t\ttry {\n\t\t\treturn JSON.stringify(pendingApproval.args, null, 2)\n\t\t} catch (error) {\n\t\t\tconsole.error('[VoiceToolApprovalPanel] Failed to serialize tool args:', error)\n\t\t\treturn '(unable to display arguments)'\n\t\t}\n\t}, [pendingApproval])\n\n\tif (!pendingApproval) return null\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tvariant === 'composer'\n\t\t\t\t\t? 'min-h-14 px-3 py-2'\n\t\t\t\t\t: 'rounded-xl border border-border bg-background/80 p-3'\n\t\t\t)}\n\t\t>\n\t\t\t<div className=\"flex items-center justify-between gap-2 pb-1\">\n\t\t\t\t<div className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\t\t\tApproval required\n\t\t\t\t</div>\n\t\t\t\t<span className=\"text-xs text-muted-foreground\">{timeoutRemaining}s</span>\n\t\t\t</div>\n\n\t\t\t<p className=\"text-sm\">\n\t\t\t\tAllow <strong>{humanizeToolName(pendingApproval.toolName)}</strong>?\n\t\t\t</p>\n\n\t\t\t{argsPreview !== '{}' ? (\n\t\t\t\t<pre className=\"mt-2 max-h-28 overflow-auto rounded-md border border-border/70 bg-muted/30 p-2 text-xs text-muted-foreground\">\n\t\t\t\t\t{argsPreview}\n\t\t\t\t</pre>\n\t\t\t) : null}\n\n\t\t\t<div className=\"mt-3 flex items-center gap-2\">\n\t\t\t\t<Button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tclassName=\"h-7 gap-1.5\"\n\t\t\t\t\tonClick={deny}\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 type=\"button\" size=\"sm\" className=\"h-7 gap-1.5\" onClick={approve}>\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 VoiceToolApprovalPanel\n","import { useEffect, useState } from 'react'\n\n/**\n * Hook that delays state updates by a specified duration.\n * Useful for preventing UI flash when state changes rapidly.\n *\n * @param value - The value to delay\n * @param delay - Delay in milliseconds\n * @returns The delayed value\n *\n * @example\n * ```tsx\n * // Delay showing approval UI to prevent flash\n * const hasPendingApproval = useDelayedState(hasPendingApprovalRaw, 100)\n * ```\n */\nexport function useDelayedState<T>(value: T, delay: number): T {\n\tconst [delayedValue, setDelayedValue] = useState(value)\n\n\tuseEffect(() => {\n\t\tconst timer = setTimeout(() => setDelayedValue(value), delay)\n\t\treturn () => clearTimeout(timer)\n\t}, [value, delay])\n\n\treturn delayedValue\n}\n","/**\n * Tool Exclusion Provider\n *\n * Provides a mechanism to exclude certain tools from the embedded agent's visible tool list.\n * This is useful for:\n * - Filtering out internal/development tools\n * - Creating tool scoping for different use cases\n *\n * Usage:\n * ```tsx\n * import { ToolExclusionProvider } from '@mcp-b/embedded-agent'\n *\n * // Exclude tools by prefix\n * <ToolExclusionProvider excludePrefixes={['internal_']}>\n * <AgentProvider>...</AgentProvider>\n * </ToolExclusionProvider>\n *\n * // Exclude specific tools by name\n * <ToolExclusionProvider exclude={(name) => ['tool1', 'tool2'].includes(name)}>\n * <AgentProvider>...</AgentProvider>\n * </ToolExclusionProvider>\n * ```\n */\nimport { createContext, useCallback, useContext, useMemo, type FC, type ReactNode } from 'react'\n\nimport type { ToolWithSource } from '@mcp-b/shared-types'\n\n/**\n * Filter function to determine if a tool should be excluded\n */\nexport type ToolExclusionFilter = (toolName: string, tool: ToolWithSource) => boolean\n\nexport interface ToolExclusionContextValue {\n\t/**\n\t * Check if a tool should be excluded from the agent\n\t */\n\tshouldExclude: (tool: ToolWithSource) => boolean\n\n\t/**\n\t * Filter an array of tools, removing excluded ones\n\t */\n\tfilterTools: (tools: ToolWithSource[]) => ToolWithSource[]\n}\n\nconst ToolExclusionContext = createContext<ToolExclusionContextValue | null>(null)\n\nexport interface ToolExclusionProviderProps {\n\tchildren: ReactNode\n\n\t/**\n\t * Filter function to determine which tools to exclude.\n\t * Return true to exclude the tool, false to include it.\n\t *\n\t * @example Exclude by prefix\n\t * ```tsx\n\t * exclude={(name) => name.startsWith('internal_')}\n\t * ```\n\t *\n\t * @example Exclude by list\n\t * ```tsx\n\t * exclude={(name) => ['dev_tool', 'internal_tool'].includes(name)}\n\t * ```\n\t */\n\texclude?: ToolExclusionFilter\n\n\t/**\n\t * Array of specific tool names to exclude\n\t * (convenience alternative to `exclude` function)\n\t */\n\texcludeNames?: string[]\n\n\t/**\n\t * Array of prefixes - tools starting with any of these will be excluded\n\t * (convenience alternative to `exclude` function)\n\t */\n\texcludePrefixes?: string[]\n}\n\nexport const ToolExclusionProvider: FC<ToolExclusionProviderProps> = ({\n\tchildren,\n\texclude,\n\texcludeNames,\n\texcludePrefixes,\n}) => {\n\tconst shouldExclude = useCallback(\n\t\t(tool: ToolWithSource): boolean => {\n\t\t\t// Check custom exclude function first\n\t\t\tif (exclude?.(tool.name, tool)) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Check excludeNames\n\t\t\tif (excludeNames?.includes(tool.name)) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Check excludePrefixes\n\t\t\tif (excludePrefixes?.some((prefix) => tool.name.startsWith(prefix))) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\treturn false\n\t\t},\n\t\t[exclude, excludeNames, excludePrefixes]\n\t)\n\n\tconst filterTools = useCallback(\n\t\t(tools: ToolWithSource[]): ToolWithSource[] => {\n\t\t\treturn tools.filter((tool) => !shouldExclude(tool))\n\t\t},\n\t\t[shouldExclude]\n\t)\n\n\tconst value = useMemo<ToolExclusionContextValue>(\n\t\t() => ({\n\t\t\tshouldExclude,\n\t\t\tfilterTools,\n\t\t}),\n\t\t[shouldExclude, filterTools]\n\t)\n\n\treturn <ToolExclusionContext.Provider value={value}>{children}</ToolExclusionContext.Provider>\n}\n\n/**\n * Hook to access tool exclusion context\n * Throws if used outside ToolExclusionProvider\n */\nexport function useToolExclusion(): ToolExclusionContextValue {\n\tconst context = useContext(ToolExclusionContext)\n\tif (!context) {\n\t\tthrow new Error('useToolExclusion must be used within a ToolExclusionProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access tool exclusion context\n * Returns null if used outside ToolExclusionProvider\n */\nexport function useOptionalToolExclusion(): ToolExclusionContextValue | null {\n\treturn useContext(ToolExclusionContext)\n}\n","/**\n * MCP Tool Registry Component\n *\n * Registers all MCP tools with the assistant-ui runtime as schema-only (no execute).\n *\n * Tool execution is handled by:\n * - Auto-execute tools: onToolCall in useThreadRuntime (when server provides addToolOutput)\n * - HITL tools: UnifiedToolFallback approval dialog (when server withholds addToolOutput)\n *\n * The server (ThreadAgent) is the single source of truth for approval decisions via\n * the needsApproval() callback. This component just provides tool schemas to assistant-ui.\n *\n * Supports tool exclusion when ToolExclusionProvider is present:\n * - Excluded tools are not registered with assistant-ui\n * - Useful for hiding test tools from the agent\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 { memo, useMemo } from 'react'\n\nimport { useMCPTools } from '../providers/MCPToolsProvider'\nimport { useOptionalToolExclusion } from '../providers/ToolExclusionProvider'\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { ToolWithSource } from '@mcp-b/shared-types'\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 Component\n// // ============================================================================\n\n// /**\n// * Bridge component that registers a single tool with assistant-ui.\n// *\n// * IMPORTANT: No execute function is provided!\n// * Tool execution is handled elsewhere:\n// * - Auto-execute: onToolCall in useThreadRuntime (server provides addToolOutput)\n// * - HITL: UnifiedToolFallback approval dialog (server withholds addToolOutput)\n// *\n// * The server (ThreadAgent) decides which path via needsApproval() callback.\n// * This component just provides tool schemas to assistant-ui for context.\n// *\n// * Memoized to prevent re-registration when parent re-renders.\n// */\n// const ToolBridge: FC<{\n// \ttool: ToolWithSource\n// }> = memo(({ tool }) => {\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 - execution handled by onToolCall or UnifiedToolFallback\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// *\n// * This component only provides tool schemas - no execution logic.\n// * The server (ThreadAgent) is the single source of truth for approval decisions.\n// *\n// * Respects ToolExclusionProvider to filter out excluded tools.\n// */\n// export const MCPToolRegistry: FC = () => {\n// \tconst { tools } = useMCPTools()\n// \tconst toolExclusion = useOptionalToolExclusion()\n\n// \t// Filter tools based on exclusion rules\n// \tconst visibleTools = useMemo(() => {\n// \t\tif (!toolExclusion) {\n// \t\t\tconsole.debug('[MCPToolRegistry] No exclusion provider, registering all tools:', tools.map(t => t.name))\n// \t\t\treturn tools\n// \t\t}\n// \t\tconst filtered = toolExclusion.filterTools(tools)\n// \t\tconst excluded = tools.filter(t => !filtered.includes(t))\n// \t\tif (excluded.length > 0) {\n// \t\t\tconsole.debug('[MCPToolRegistry] Excluded tools:', excluded.map(t => t.name))\n// \t\t}\n// \t\tconsole.debug('[MCPToolRegistry] Registering visible tools:', filtered.map(t => t.name))\n// \t\treturn filtered\n// \t}, [tools, toolExclusion])\n\n// \treturn (\n// \t\t<>\n// \t\t\t{visibleTools.map((tool) => (\n// \t\t\t\t<ToolBridge key={`${tool._sourceId}-${tool.name}`} tool={tool} />\n// \t\t\t))}\n// \t\t</>\n// \t)\n// }\n","/**\n * Tool Icon Mapping\n *\n * Utility to get appropriate icons for tools based on their names.\n * Shared between thread and deprecated pill components.\n */\n\nimport {\n\tCamera,\n\tFileText,\n\tMousePointer,\n\tNavigation,\n\tPenLine,\n\tSearch,\n\tTrash2,\n\tWrench,\n} from 'lucide-react'\n\nimport { normalizeToolName } from './tool-names'\n\nimport type { LucideIcon } from 'lucide-react'\n\n/**\n * Get an appropriate icon for a tool based on its name.\n * Uses canonical tool names before matching.\n * Uses pattern matching to categorize tools.\n */\nexport function getToolIcon(toolName: string): LucideIcon {\n\tconst name = normalizeToolName(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 * 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, Loader2, X } from 'lucide-react'\nimport { useCallback, useMemo, useState } from 'react'\nimport type React from 'react'\nimport { ToolResponse } from 'assistant-stream'\n\nimport { useDelayedState } from '../../hooks/useDelayedState'\nimport { useMCPTools } from '../../providers/MCPToolsProvider'\nimport { formatToolResult } from '../../providers/MCPToolRegistry'\nimport { useToolExecution } from '../../providers/ToolExecutionProvider'\nimport { cn } from '../../utils/cn'\nimport { formatArgs, humanizeToolName, TOOL_DENIED_MESSAGE } from '../../utils/format'\nimport { normalizeToolName } from '../../utils/tool-names'\nimport { getToolIcon } from '../../utils/tool-icons'\n\nimport type { ToolCallMessagePartComponent } from '@assistant-ui/react'\nimport type { ToolCallMetadata } from '@mcp-b/shared-types'\n\n// ============================================================================\n// Status Visual System (ported from extension)\n// ============================================================================\n\ntype StatusVariant = 'running' | 'success' | 'error' | 'cancelled' | 'warning'\n\nconst STATUS_BORDER: Record<StatusVariant, string> = {\n\trunning: 'ring-1 ring-blue-500/25 dark:ring-blue-400/25 bg-blue-500/5 dark:bg-blue-500/10',\n\tsuccess: 'ring-1 ring-emerald-400/30 dark:ring-emerald-500/25 bg-emerald-500/6 dark:bg-emerald-500/12',\n\terror: 'ring-1 ring-red-500/30 dark:ring-red-400/30 bg-red-500/5 dark:bg-red-500/10',\n\tcancelled: 'ring-1 ring-border/20 dark:ring-border/30 bg-muted/5',\n\twarning: 'ring-1 ring-amber-500/30 dark:ring-amber-400/30 bg-amber-500/5 dark:bg-amber-500/10',\n}\n\nconst STATUS_ACCENT: Record<StatusVariant, string> = {\n\trunning: 'text-blue-600 dark:text-blue-300',\n\tsuccess: 'text-emerald-600 dark:text-emerald-300',\n\terror: 'text-red-600 dark:text-red-300',\n\tcancelled: 'text-slate-600 dark:text-slate-300',\n\twarning: 'text-amber-600 dark:text-amber-300',\n}\n\nconst STATUS_ICON_RING: Record<StatusVariant, string> = {\n\trunning: 'bg-blue-500/10 text-blue-600 dark:text-blue-300',\n\tsuccess: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-300',\n\terror: 'bg-red-500/10 text-red-600 dark:text-red-300',\n\tcancelled: 'bg-slate-500/10 text-slate-600 dark:text-slate-300',\n\twarning: 'bg-amber-500/10 text-amber-600 dark:text-amber-300',\n}\n\n// ============================================================================\n// Progress Extraction (ported from extension)\n// ============================================================================\n\n/**\n * Extract progress percentage from tool result if available.\n * Looks for common progress field names in the result object.\n */\nconst extractProgress = (value: unknown): number | null => {\n\tif (!value || typeof value !== 'object') return null\n\tconst obj = value as Record<string, unknown>\n\tconst maybeProgress = obj.progress ?? obj.percentage ?? obj.pct\n\tif (typeof maybeProgress === 'number' && Number.isFinite(maybeProgress)) {\n\t\treturn Math.max(0, Math.min(100, maybeProgress))\n\t}\n\treturn null\n}\n\n// ============================================================================\n// Error Parsing (ported from extension)\n// ============================================================================\n\n/** MCP error code to human-readable description */\nconst getErrorCodeDescription = (code: number): string => {\n\tswitch (code) {\n\t\tcase -32700:\n\t\t\treturn 'Parse Error'\n\t\tcase -32600:\n\t\t\treturn 'Invalid Request'\n\t\tcase -32601:\n\t\t\treturn 'Method Not Found'\n\t\tcase -32602:\n\t\t\treturn 'Invalid Parameters'\n\t\tcase -32603:\n\t\t\treturn 'Internal Error'\n\t\tcase -32001:\n\t\t\treturn 'Connection Closed'\n\t\tcase -32000:\n\t\t\treturn 'Request Timeout'\n\t\tcase -32002:\n\t\t\treturn 'Resource Not Found'\n\t\tdefault:\n\t\t\tif (code >= -32099 && code <= -32000) {\n\t\t\t\treturn 'Server Error'\n\t\t\t}\n\t\t\treturn `Error ${code}`\n\t}\n}\n\ninterface ParsedError {\n\tsummary: string\n\tdetails?: unknown\n\tvalidationErrors?: ValidationError[]\n}\n\ninterface ValidationError {\n\tpath?: string[]\n\tcode?: string\n\tmessage?: string\n\texpected?: string\n\treceived?: string\n\toptions?: string[]\n}\n\n/**\n * Parse error message to extract structured information.\n * Handles MCP error format: \"MCP error -32602: Invalid arguments...\"\n */\nconst parseErrorMessage = (errorMessage: string): ParsedError => {\n\t// Match MCP error pattern\n\tconst mcpErrorMatch = errorMessage.match(/MCP error (-?\\d+): (.+)$/s)\n\tif (mcpErrorMatch) {\n\t\tconst errorCode = Number.parseInt(mcpErrorMatch[1], 10)\n\t\tconst fullMessage = mcpErrorMatch[2]\n\n\t\t// Try to extract JSON array of validation errors\n\t\tconst arrayStartIdx = fullMessage.indexOf('[')\n\t\tif (arrayStartIdx !== -1) {\n\t\t\tlet depth = 0\n\t\t\tlet arrayEndIdx = -1\n\t\t\tfor (let i = arrayStartIdx; i < fullMessage.length; i++) {\n\t\t\t\tif (fullMessage[i] === '[') depth++\n\t\t\t\telse if (fullMessage[i] === ']') {\n\t\t\t\t\tdepth--\n\t\t\t\t\tif (depth === 0) {\n\t\t\t\t\t\tarrayEndIdx = i\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (arrayEndIdx !== -1) {\n\t\t\t\tconst jsonStr = fullMessage.substring(arrayStartIdx, arrayEndIdx + 1)\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(jsonStr)\n\t\t\t\t\tif (Array.isArray(parsed) && parsed.length > 0) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tsummary: getErrorCodeDescription(errorCode),\n\t\t\t\t\t\t\tvalidationErrors: parsed as ValidationError[],\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Continue with fallback\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst cleanedMessage = fullMessage\n\t\t\t.replace(/MCP error -?\\d+: /g, '')\n\t\t\t.replace(/Invalid arguments for tool \\w+: /, '')\n\t\treturn { summary: getErrorCodeDescription(errorCode), details: cleanedMessage }\n\t}\n\n\t// Handle generic error prefix\n\tif (errorMessage.includes('Error:')) {\n\t\treturn { summary: errorMessage.replace(/^Error:\\s*/, '') }\n\t}\n\n\treturn { summary: errorMessage }\n}\n\n/**\n * Check if result contains an error pattern (ported from extension).\n * This is critical for determining if a \"complete\" status actually represents an error.\n */\nconst checkForError = (result: unknown): boolean => {\n\tif (!result) return false\n\n\t// Check for MCP error pattern in string results first\n\tif (typeof result === 'string') {\n\t\treturn (\n\t\t\tresult.includes('MCP error') ||\n\t\t\tresult.includes('Error:') ||\n\t\t\tresult.startsWith('Input validation error')\n\t\t)\n\t}\n\n\tif (typeof result !== 'object') return false\n\n\tconst obj = result as Record<string, unknown>\n\n\t// Check for tool execution error pattern (isError flag)\n\tif (obj.isError === true) return true\n\n\t// Check for error property containing a string or object\n\tif (obj.error && (typeof obj.error === 'string' || typeof obj.error === 'object')) return true\n\n\treturn false\n}\n\n/**\n * Extract error details from tool result or status.\n */\nconst extractErrorDetails = (\n\tstatus: { type: string; error?: unknown; reason?: string },\n\tresult: unknown\n): ParsedError | null => {\n\t// Check status error first\n\tif (status.type === 'incomplete' && status.error) {\n\t\tconst errorStr = typeof status.error === 'string' ? status.error : JSON.stringify(status.error)\n\t\treturn parseErrorMessage(errorStr)\n\t}\n\n\t// Check result for error patterns\n\tif (result) {\n\t\tif (typeof result === 'string') {\n\t\t\tif (result.includes('MCP error') || result.includes('Error:') || result.startsWith('Input validation error')) {\n\t\t\t\treturn parseErrorMessage(result)\n\t\t\t}\n\t\t} else if (typeof result === 'object') {\n\t\t\tconst obj = result as Record<string, unknown>\n\t\t\tif (obj.isError === true || obj.error) {\n\t\t\t\tconst errorStr =\n\t\t\t\t\ttypeof obj.error === 'string'\n\t\t\t\t\t\t? obj.error\n\t\t\t\t\t\t: typeof obj.message === 'string'\n\t\t\t\t\t\t\t? obj.message\n\t\t\t\t\t\t\t: JSON.stringify(obj.error || obj)\n\t\t\t\treturn parseErrorMessage(errorStr)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null\n}\n\n// ============================================================================\n// Status Icon Component (ported from extension)\n// ============================================================================\n\nconst StatusIcon: React.FC<{\n\tstatus: StatusVariant\n\tclassName?: string\n}> = ({ status, className }) => {\n\tconst iconMap = {\n\t\trunning: Loader2,\n\t\tsuccess: Check,\n\t\terror: AlertCircle,\n\t\tcancelled: X,\n\t\twarning: AlertTriangle,\n\t}\n\tconst Icon = iconMap[status]\n\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t'flex h-5 w-5 flex-none items-center justify-center rounded-md transition-all duration-200',\n\t\t\t\tSTATUS_ICON_RING[status],\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t<Icon className={cn('h-3 w-3', status === 'running' && 'animate-spin')} />\n\t\t</span>\n\t)\n}\n\n// ============================================================================\n// Progress Bar Component\n// ============================================================================\n\nconst ProgressBar: React.FC<{\n\tprogress: number | null\n\tclassName?: string\n}> = ({ progress, className }) => {\n\treturn (\n\t\t<div className={cn('h-1 w-full overflow-hidden rounded-full bg-muted/30', className)}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'h-full bg-blue-500/70 transition-all duration-300 ease-out',\n\t\t\t\t\tprogress == null && 'animate-pulse'\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: progress != null ? `${Math.max(5, Math.min(100, Math.round(progress)))}%` : '35%',\n\t\t\t\t}}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n\n// ============================================================================\n// Validation Error Display Component\n// ============================================================================\n\nconst ValidationErrorDisplay: React.FC<{\n\terrors: ValidationError[]\n}> = ({ errors }) => {\n\tconst getErrorCodeChip = (code?: string) => {\n\t\tswitch (code) {\n\t\t\tcase 'invalid_enum_value':\n\t\t\t\treturn 'ENUM'\n\t\t\tcase 'invalid_type':\n\t\t\t\treturn 'TYPE'\n\t\t\tcase 'too_small':\n\t\t\t\treturn 'MIN'\n\t\t\tcase 'too_big':\n\t\t\t\treturn 'MAX'\n\t\t\tcase 'invalid_string':\n\t\t\t\treturn 'STR'\n\t\t\tcase 'custom':\n\t\t\t\treturn 'CUSTOM'\n\t\t\tdefault:\n\t\t\t\treturn 'ERR'\n\t\t}\n\t}\n\n\treturn (\n\t\t<div className=\"space-y-1.5\">\n\t\t\t{errors.map((err, idx) => {\n\t\t\t\tconst fieldPath = err.path?.join('.') || 'field'\n\t\t\t\treturn (\n\t\t\t\t\t<div key={idx} className=\"rounded-md bg-red-500/5 px-2 py-1.5\">\n\t\t\t\t\t\t<div className=\"flex items-start gap-1.5\">\n\t\t\t\t\t\t\t<span className=\"inline-flex h-4 min-w-4 items-center justify-center rounded bg-red-500/10 px-1 font-mono text-[9px] text-red-600 dark:text-red-400\">\n\t\t\t\t\t\t\t\t{getErrorCodeChip(err.code)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<div className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t\t\t<div className=\"text-[11px] font-medium text-red-600 dark:text-red-400\">\n\t\t\t\t\t\t\t\t\t{fieldPath.replace(/([A-Z])/g, ' $1').replace(/_/g, ' ').trim()}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div className=\"text-[10px] text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{err.message ||\n\t\t\t\t\t\t\t\t\t\t`Expected ${err.expected || 'valid value'}, received ${err.received || 'invalid'}`}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t{err.options && err.options.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className=\"mt-1 flex flex-wrap gap-1\">\n\t\t\t\t\t\t\t\t\t\t{err.options.slice(0, 5).map((opt) => (\n\t\t\t\t\t\t\t\t\t\t\t<code\n\t\t\t\t\t\t\t\t\t\t\t\tkey={opt}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"rounded bg-muted/50 px-1 py-0.5 font-mono text-[9px] text-foreground/70\"\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{opt}\n\t\t\t\t\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t{err.options.length > 5 && (\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-[9px] text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t+{err.options.length - 5} more\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t)\n\t\t\t})}\n\t\t</div>\n\t)\n}\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\nfunction parseToolCallMetadata(artifact: unknown): ToolCallMetadata | null {\n\tif (!artifact || typeof artifact !== 'object') return null\n\tconst metadata = artifact as Partial<ToolCallMetadata>\n\tif (\n\t\ttypeof metadata.sourceId !== 'string' ||\n\t\ttypeof metadata.startedAt !== 'number' ||\n\t\ttypeof metadata.duration !== 'number'\n\t) {\n\t\treturn null\n\t}\n\treturn metadata as ToolCallMetadata\n}\n\nconst PolicySummary: React.FC<{\n\tpolicy: NonNullable<ToolCallMetadata['policy']>\n}> = ({ policy }) => {\n\tconst toneClass =\n\t\tpolicy.status === 'failure'\n\t\t\t? 'bg-red-500/15 text-red-500'\n\t\t\t: policy.status === 'notify'\n\t\t\t\t? 'bg-amber-500/15 text-amber-500'\n\t\t\t\t: 'bg-emerald-500/15 text-emerald-500'\n\n\treturn (\n\t\t<div className=\"mb-1.5 rounded bg-muted/30 p-1.5\">\n\t\t\t<div className=\"mb-1 flex items-center gap-2\">\n\t\t\t\t<span className={cn('rounded px-1.5 py-0.5 text-[10px] font-medium uppercase', toneClass)}>\n\t\t\t\t\tPolicy {policy.status}\n\t\t\t\t</span>\n\t\t\t\t<span className=\"text-[10px] text-muted-foreground\">{policy.pluginName}</span>\n\t\t\t</div>\n\t\t\t<div className=\"text-[11px] text-muted-foreground\">{policy.message}</div>\n\t\t\t{policy.violations.length > 0 ? (\n\t\t\t\t<div className=\"mt-1 text-[10px] text-muted-foreground\">\n\t\t\t\t\t{policy.violations.length} violation{policy.violations.length === 1 ? '' : 's'}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t</div>\n\t)\n}\n\n// ============================================================================\n// Sub-Components for Each State\n// ============================================================================\n\n/**\n * Running state - tool is currently executing\n * Now includes progress bar and partial output support\n */\nconst RunningToolDisplay: React.FC<{\n\ttoolName: string\n\tprogress?: number | null\n\tpartialResult?: unknown\n}> = ({ toolName, progress, partialResult }) => {\n\treturn (\n\t\t<div className={cn('my-1 overflow-hidden rounded-lg', STATUS_BORDER.running)}>\n\t\t\t<div className=\"flex items-center gap-2 px-2 py-1.5\">\n\t\t\t\t<StatusIcon status=\"running\" />\n\t\t\t\t<span className=\"flex-1 text-sm\">\n\t\t\t\t\t<strong className={cn('font-medium', STATUS_ACCENT.running)}>\n\t\t\t\t\t\t{humanizeToolName(toolName)}\n\t\t\t\t\t</strong>\n\t\t\t\t</span>\n\t\t\t\t{progress != null && (\n\t\t\t\t\t<span className=\"text-[10px] text-muted-foreground\">{Math.round(progress)}%</span>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<ProgressBar progress={progress ?? null} className=\"mx-2 mb-2\" />\n\t\t\t{partialResult !== undefined && (\n\t\t\t\t<div className=\"border-t border-border/50 px-2 py-1.5\">\n\t\t\t\t\t<div className=\"mb-0.5 text-[10px] font-medium text-muted-foreground/70\">Partial output</div>\n\t\t\t\t\t<pre className=\"max-h-20 overflow-auto whitespace-pre-wrap font-mono text-[11px] text-muted-foreground/80\">\n\t\t\t\t\t\t{typeof partialResult === 'string' ? partialResult : JSON.stringify(partialResult, null, 2)}\n\t\t\t\t\t</pre>\n\t\t\t\t</div>\n\t\t\t)}\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 <RunningToolDisplay toolName={toolName} />\n\t}\n\n\treturn (\n\t\t<div className={cn('my-1 overflow-hidden rounded-lg', 'bg-muted/50')}>\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-border\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-foreground/70\" />\n\t\t\t\t\t<AlertTriangle className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-foreground/70\" />\n\t\t\t\t</div>\n\t\t\t\t<span className=\"text-xs font-medium text-foreground\">{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 && (\n\t\t\t\t\t<div className=\"mb-2 line-clamp-3 text-xs text-muted-foreground\">{toolDescription}</div>\n\t\t\t\t)}\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-muted/50 p-1.5\">\n\t\t\t\t\t\t<pre className=\"whitespace-pre-wrap text-[11px] text-muted-foreground\">\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-border text-muted-foreground',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisHovered === 'deny' ? 'bg-muted text-foreground/80' : 'hover:bg-muted/50'\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-primary text-primary-foreground',\n\t\t\t\t\t\t\t'transition-colors duration-150',\n\t\t\t\t\t\t\tisHovered === 'approve' ? 'bg-primary/90' : 'hover:bg-primary/90'\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\tpolicy?: ToolCallMetadata['policy']\n}> = ({ toolName, argsText, result, policy }) => {\n\tconst [isExpanded, setIsExpanded] = useState(false)\n\n\treturn (\n\t\t<div className={cn('my-1 overflow-hidden rounded-lg', STATUS_BORDER.success)}>\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-2 px-2 py-1.5 text-left transition-colors hover:bg-emerald-500/5\"\n\t\t\t>\n\t\t\t\t<StatusIcon status=\"success\" />\n\t\t\t\t<span className={cn('flex-grow text-xs font-medium', STATUS_ACCENT.success)}>\n\t\t\t\t\t{humanizeToolName(toolName)}\n\t\t\t\t</span>\n\t\t\t\t<span className=\"inline-flex h-5 w-5 items-center justify-center p-0\">\n\t\t\t\t\t{isExpanded ? (\n\t\t\t\t\t\t<ChevronUpIcon className=\"h-3 w-3 text-muted-foreground/70\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<ChevronDownIcon className=\"h-3 w-3 text-muted-foreground/70\" />\n\t\t\t\t\t)}\n\t\t\t\t</span>\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-emerald-500/20 px-2 py-1.5\">\n\t\t\t\t\t{policy ? <PolicySummary policy={policy} /> : null}\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-muted-foreground/70\">\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-muted/30 p-1.5 font-mono text-[11px] text-muted-foreground\">\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-muted-foreground/70\">\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-muted/30 p-1.5 font-mono text-[11px] text-muted-foreground\">\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 - now with structured error parsing\n */\nconst ErrorToolDisplay: React.FC<{\n\ttoolName: string\n\terror?: string\n\tparsedError?: ParsedError | null\n\tpolicy?: ToolCallMetadata['policy']\n}> = ({ toolName, error, parsedError, policy }) => {\n\t// Use parsed error if available, otherwise parse the error string\n\tconst errorInfo = parsedError || (error ? parseErrorMessage(error) : null)\n\n\treturn (\n\t\t<div className={cn('my-1 overflow-hidden rounded-lg', STATUS_BORDER.error)}>\n\t\t\t<div className=\"flex items-center gap-2 px-2 py-1.5\">\n\t\t\t\t<StatusIcon status=\"error\" />\n\t\t\t\t<span className={cn('flex-1 text-xs font-medium', STATUS_ACCENT.error)}>\n\t\t\t\t\t{humanizeToolName(toolName)} failed\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t{errorInfo && (\n\t\t\t\t<div className=\"border-t border-red-500/20 px-2 py-1.5\">\n\t\t\t\t\t{policy ? <PolicySummary policy={policy} /> : null}\n\t\t\t\t\t<p className=\"mb-1 text-xs font-medium text-red-600 dark:text-red-400\">{errorInfo.summary}</p>\n\t\t\t\t\t{errorInfo.validationErrors && errorInfo.validationErrors.length > 0 ? (\n\t\t\t\t\t\t<ValidationErrorDisplay errors={errorInfo.validationErrors} />\n\t\t\t\t\t) : errorInfo.details ? (\n\t\t\t\t\t\t<pre className=\"whitespace-pre-wrap font-mono text-[11px] text-muted-foreground\">\n\t\t\t\t\t\t\t{typeof errorInfo.details === 'string'\n\t\t\t\t\t\t\t\t? errorInfo.details\n\t\t\t\t\t\t\t\t: JSON.stringify(errorInfo.details, null, 2)}\n\t\t\t\t\t\t</pre>\n\t\t\t\t\t) : null}\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\tpolicy?: ToolCallMetadata['policy']\n}> = ({ toolName, policy }) => {\n\tconst ToolIcon = getToolIcon(toolName)\n\n\treturn (\n\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-muted/50\">\n\t\t\t<div className=\"flex items-center gap-1.5 px-2 py-1.5 text-xs text-muted-foreground\">\n\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t<ToolIcon className=\"h-3.5 w-3.5 text-muted-foreground/70\" />\n\t\t\t\t\t<X className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-muted-foreground/70\" />\n\t\t\t\t</div>\n\t\t\t\t<span>\n\t\t\t\t\t<strong className=\"text-foreground/70\">{humanizeToolName(toolName)}</strong> denied\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t{policy ? (\n\t\t\t\t<div className=\"border-t border-border/60 px-2 py-1.5\">\n\t\t\t\t\t<PolicySummary policy={policy} />\n\t\t\t\t</div>\n\t\t\t) : null}\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,\n\ttoolName,\n\targsText,\n\targs,\n\tartifact,\n\tstatus,\n\tresult,\n\tisError,\n\taddResult,\n}) => {\n\tconst { callTool, tools } = useMCPTools()\n\tconst toolExecution = useToolExecution()\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// Extract progress from result (for running state)\n\tconst progress = useMemo(() => extractProgress(result), [result])\n\n\t// Extract parsed error details\n\tconst parsedError = useMemo(\n\t\t() => extractErrorDetails(status as { type: string; error?: unknown; reason?: string }, result),\n\t\t[status, result]\n\t)\n\tconst metadata = useMemo(() => parseToolCallMetadata(artifact), [artifact])\n\tconst policy = metadata?.policy\n\n\t// Get tool metadata from registry (thread-aware if available)\n\tconst normalizedToolName = normalizeToolName(toolName)\n\tconst toolMetadata = toolExecution.getToolMetadata(toolName)\n\tconst localTool = tools.find((t) => t.name === normalizedToolName)\n\tconst toolDescription = toolMetadata?.description ?? localTool?.description\n\t// Server decides approval via needsApproval callback, converter sets status.type accordingly\n\t// We don't need to re-derive from annotations on the client\n\tconst requiresApproval = status.type === 'requires-action'\n\tconst executeTool = toolExecution.executeTool\n\n\t// Handle approval - execute the tool and add result\n\t// Uses ToolResponse to properly communicate error state to both:\n\t// 1. Assistant-UI (for error display/styling)\n\t// 2. The model (so it knows the tool failed, not just sees \"Error: \" text)\n\tconst handleApprove = useCallback(async () => {\n\t\tsetIsExecuting(true)\n\t\ttry {\n\t\t\tconst toolResult = await executeTool(toolName, parsedArgs, { toolCallId })\n\t\t\tconst resultText = formatToolResult(toolResult)\n\n\t\t\t// v6 pattern: addToolOutput sends to backend via WebSocket + updates local state\n\t\t\t// Note: Do NOT call addResult() here - it triggers onAddToolResult which would\n\t\t\t// send a duplicate message to the server. chat.addToolOutput already handles\n\t\t\t// both server sync and local state update.\n\t\t\ttoolExecution.addToolOutput({\n\t\t\t\ttoolCallId,\n\t\t\t\toutput: toolResult.isError === true ? `Error: ${resultText}` : resultText,\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// v6 pattern: send error to backend + updates local state\n\t\t\ttoolExecution.addToolOutput({\n\t\t\t\ttoolCallId,\n\t\t\t\toutput: `Error: ${errorMessage}`,\n\t\t\t})\n\t\t} finally {\n\t\t\tsetIsExecuting(false)\n\t\t}\n\t}, [toolName, parsedArgs, executeTool, toolExecution, toolCallId])\n\n\t// Handle denial - add denial result using shared constant\n\tconst handleDeny = useCallback(() => {\n\t\t// v6 pattern: send denial to backend + updates local state\n\t\t// Note: Do NOT call addResult() here - it triggers onAddToolResult which would\n\t\t// send a duplicate message to the server.\n\t\ttoolExecution.addToolOutput({\n\t\t\ttoolCallId,\n\t\t\toutput: TOOL_DENIED_MESSAGE,\n\t\t})\n\t}, [toolExecution, toolCallId])\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 = result === undefined && requiresApproval\n\n\t// Delay showing approval dialog to prevent flash when state transitions quickly\n\tconst showApprovalDialog = useDelayedState(isPendingApproval, 100)\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\t// We delay showing the dialog by 100ms to prevent flash when state transitions quickly\n\tif (isPendingApproval) {\n\t\t// During the delay, show the running state to prevent a blank flash\n\t\tif (!showApprovalDialog) {\n\t\t\treturn <RunningToolDisplay toolName={toolName} progress={progress} partialResult={result} />\n\t\t}\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} policy={policy} />\n\t}\n\n\t// Case 3: Tool is currently running (has execute function)\n\tif (statusType === 'running') {\n\t\treturn <RunningToolDisplay toolName={toolName} progress={progress} partialResult={result} />\n\t}\n\n\t// Case 4: Tool completed with error (status indicates error)\n\tif (statusType === 'incomplete' || hasStatusError(status)) {\n\t\tconst errorMessage = hasStatusError(status) ? status.error : 'Tool execution failed'\n\t\treturn (\n\t\t\t<ErrorToolDisplay\n\t\t\t\ttoolName={toolName}\n\t\t\t\terror={errorMessage}\n\t\t\t\tparsedError={parsedError}\n\t\t\t\tpolicy={policy}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Case 4b: Tool result contains error (isError prop or error pattern in result)\n\t// isError prop is the authoritative MCP flag; checkForError is a fallback heuristic\n\tconst hasErrorResult = isError || checkForError(result)\n\tif (hasErrorResult) {\n\t\t// Extract error message from result for display\n\t\tconst errorMessage =\n\t\t\ttypeof result === 'string'\n\t\t\t\t? result\n\t\t\t\t: typeof (result as Record<string, unknown>)?.error === 'string'\n\t\t\t\t\t? ((result as Record<string, unknown>).error as string)\n\t\t\t\t\t: 'Tool returned an error'\n\t\treturn (\n\t\t\t<ErrorToolDisplay\n\t\t\t\ttoolName={toolName}\n\t\t\t\terror={errorMessage}\n\t\t\t\tparsedError={parsedError}\n\t\t\t\tpolicy={policy}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Case 5: Tool completed successfully\n\t// Also handle transition state where result is set but status hasn't updated yet\n\tif (statusType === 'complete' || (result !== undefined && !isDeniedResult(result))) {\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 (\n\t\t\t<CompletedToolDisplay\n\t\t\t\ttoolName={toolName}\n\t\t\t\targsText={argsText}\n\t\t\t\tresult={displayResult}\n\t\t\t\tpolicy={policy}\n\t\t\t/>\n\t\t)\n\t}\n\n\t// Fallback - show running state to prevent flash during state transitions\n\treturn <RunningToolDisplay toolName={toolName} progress={progress} partialResult={result} />\n}\n\nexport default UnifiedToolFallback\n","import {\n ComposerAddAttachment,\n ComposerAttachments,\n UserMessageAttachments,\n} from \"@/components/assistant-ui/attachment\";\nimport { MarkdownText } from \"@/components/assistant-ui/markdown-text\";\nimport { Reasoning, ReasoningGroup } from \"@/components/assistant-ui/reasoning\";\n// import { ToolFallback } from \"@/components/assistant-ui/tool-fallback\";\nimport { TooltipIconButton } from \"@/components/assistant-ui/tooltip-icon-button\";\nimport { Button } from \"@/components/ui/button\";\nimport { LiveWaveform } from \"@/components/ui/live-waveform\";\nimport { MicSelector } from \"@/components/ui/mic-selector\";\nimport { usePrompts } from \"@/hooks/usePrompts\";\nimport {\n useCloudflareThread,\n usePolicyPlugin,\n useThreadAgent,\n useVoiceSession,\n} from \"@/providers/CloudflareThreadRuntimeProvider\";\nimport { useToolApproval } from \"@/providers/ToolApprovalContext\";\nimport { useToolSelection } from \"@/providers/ToolSelectionProvider\";\nimport { useVoiceThread } from \"@/providers/VoiceThreadBridge\";\nimport { useVoiceToolApproval } from \"@/providers/VoiceToolApprovalProvider\";\nimport { cn } from \"@/utils/cn\";\nimport {\n ActionBarPrimitive,\n AssistantIf,\n ComposerPrimitive,\n ErrorPrimitive,\n MessagePrimitive,\n ThreadPrimitive,\n} from \"@assistant-ui/react\";\nimport type {\n RealtimeKitJoinResult,\n ThreadToolSelection,\n ToolSourceInfo,\n VoiceSessionState,\n} from \"@mcp-b/shared-types\";\nimport {\n ArrowDownIcon,\n ArrowUpIcon,\n CheckIcon,\n CopyIcon,\n History,\n PhoneCall,\n Plus,\n ShieldAlert,\n Shield,\n ShieldOff,\n SquareIcon,\n X,\n} from \"lucide-react\";\nimport { Suspense, lazy, useCallback, useEffect, useMemo, useState, type FC } from \"react\";\nimport VoiceToolApprovalPanel from \"@/components/voice/VoiceToolApprovalPanel\";\nimport UnifiedToolFallback from \"../shared/UnifiedToolFallback\";\n\nexport interface ThreadProps {\n /** Callback when threads/history button is clicked */\n onThreadsClick?: () => void;\n /** Callback when new thread button is clicked */\n onNewThread?: () => void;\n /** Callback when close button is clicked */\n onClose?: () => void;\n}\n\ntype HandoffStatus = VoiceSessionState[\"handoffStatus\"];\nconst AI_ONLY_HANDOFF_STATUS: HandoffStatus = \"ai_only\";\n\n/** Glassmorphic button styles (from WebMCP extension) - theme-aware */\nconst glassmorphicButtonClass =\n \"h-8 w-8 rounded-full border border-border backdrop-blur-sm shadow-lg shadow-black/20 bg-muted/50 transition-all duration-200 hover:border-border hover:bg-muted\";\n\nconst VoiceHandoffPanel = lazy(() => import(\"@/components/voice/VoiceHandoffPanel\"));\n\n/**\n * ThinkingIndicator - Shows a subtle \"Thinking\" indicator when the thread is running\n * This provides visual feedback when the model is processing (e.g., after tool calls complete)\n */\nconst ThinkingIndicator: FC = () => {\n return (\n <AssistantIf condition={({ thread }) => thread.messages.at(-1)?.parts.at(-1)?.type === 'tool-call' && !thread.messages.some((message) => message.status?.type === 'requires-action' || message.status?.type === 'incomplete')}>\n <div className=\"aui-thinking-indicator mx-auto w-full max-w-(--thread-max-width) px-2 py-2\">\n <div className=\"flex items-center gap-2 text-muted-foreground text-sm\">\n <span className=\"aui-thinking-dots flex gap-1\">\n <span className=\"aui-thinking-dot size-1.5 rounded-full bg-current animate-pulse\" />\n <span className=\"aui-thinking-dot size-1.5 rounded-full bg-current animate-pulse [animation-delay:150ms]\" />\n <span className=\"aui-thinking-dot size-1.5 rounded-full bg-current animate-pulse [animation-delay:300ms]\" />\n </span>\n <span className=\"aui-thinking-text\">Thinking</span>\n </div>\n </div>\n </AssistantIf>\n );\n};\n\nexport const Thread: FC<ThreadProps> = ({\n onThreadsClick,\n onNewThread,\n onClose,\n}) => {\n const voiceSession = useVoiceSession();\n const threadAgent = useThreadAgent();\n const { stop: stopVoice, isActive: isVoiceActive } = useVoiceThread();\n const handoffStatus = voiceSession?.handoffStatus ?? AI_ONLY_HANDOFF_STATUS;\n const isHandoffActive = handoffStatus !== AI_ONLY_HANDOFF_STATUS;\n\n // Stop AI voice session when handoff becomes active (agent called start_human_handoff tool)\n useEffect(() => {\n if (isHandoffActive && isVoiceActive) {\n stopVoice();\n }\n }, [isHandoffActive, isVoiceActive, stopVoice]);\n\n const [handoffJoin, setHandoffJoin] = useState<RealtimeKitJoinResult | null>(null);\n const [handoffError, setHandoffError] = useState<string | null>(null);\n const [isRequestingHandoff, setIsRequestingHandoff] = useState(false);\n\n const requestHandoffToken = useCallback(async () => {\n if (threadAgent.readyState !== WebSocket.OPEN) {\n setHandoffError(\"Connecting to support...\");\n return;\n }\n\n setIsRequestingHandoff(true);\n setHandoffError(null);\n try {\n const result = await threadAgent.stub.startHumanHandoff();\n setHandoffJoin(result);\n } catch (error) {\n setHandoffError(error instanceof Error ? error.message : \"Unable to start support call.\");\n } finally {\n setIsRequestingHandoff(false);\n }\n }, [threadAgent]);\n\n const endHandoff = useCallback(async () => {\n if (threadAgent.readyState !== WebSocket.OPEN) {\n setHandoffError(\"Support connection unavailable.\");\n return;\n }\n try {\n await threadAgent.stub.endHumanHandoff();\n } catch (error) {\n setHandoffError(error instanceof Error ? error.message : \"Unable to end support call.\");\n }\n }, [threadAgent]);\n\n useEffect(() => {\n if (handoffStatus !== AI_ONLY_HANDOFF_STATUS) return;\n setHandoffJoin(null);\n setHandoffError(null);\n setIsRequestingHandoff(false);\n }, [handoffStatus]);\n\n return (\n <ThreadPrimitive.Root\n className=\"aui-root aui-thread-root @container relative flex h-full min-h-0 flex-col bg-background\"\n style={{\n [\"--thread-max-width\" as string]: \"44rem\",\n }}\n >\n {/* Floating top bar */}\n <div className=\"absolute top-2 left-2 right-2 z-50 flex items-center gap-2\">\n {/* Left side - New thread and History icons */}\n <div className=\"flex gap-1\">\n {onNewThread && (\n <TooltipIconButton\n variant=\"ghost\"\n size=\"icon\"\n className={glassmorphicButtonClass}\n onClick={onNewThread}\n tooltip=\"New chat\"\n side=\"bottom\"\n >\n <Plus className=\"h-4 w-4\" />\n </TooltipIconButton>\n )}\n {onThreadsClick && (\n <TooltipIconButton\n variant=\"ghost\"\n size=\"icon\"\n className={glassmorphicButtonClass}\n onClick={onThreadsClick}\n tooltip=\"View all threads\"\n side=\"bottom\"\n >\n <History className=\"h-4 w-4\" />\n </TooltipIconButton>\n )}\n </div>\n\n {/* Right side - Close button */}\n <div className=\"ml-auto flex gap-1\">\n <TooltipIconButton\n variant=\"ghost\"\n size=\"icon\"\n className={glassmorphicButtonClass}\n onClick={(e) => {\n // Dispatch char-close event (primary mechanism for shadow DOM bubbling)\n try {\n e.currentTarget.dispatchEvent(\n new CustomEvent(\"char-close\", { bubbles: true, composed: true })\n );\n } catch (dispatchError) {\n console.error(\"[Thread] Failed to dispatch char-close event:\", dispatchError);\n }\n\n // Call onClose callback if provided (secondary mechanism)\n if (onClose) {\n try {\n onClose();\n } catch (callbackError) {\n console.error(\"[Thread] onClose callback threw:\", callbackError);\n }\n } else {\n // Warn if no callback provided - event dispatch is the only mechanism\n console.debug(\"[Thread] Close clicked - relying on char-close event listener\");\n }\n }}\n tooltip=\"Close\"\n side=\"bottom\"\n >\n <X className=\"h-4 w-4\" />\n </TooltipIconButton>\n </div>\n </div>\n\n {isHandoffActive ? (\n <ThreadPrimitive.Viewport className=\"aui-thread-viewport relative flex min-h-0 flex-1 flex-col overflow-hidden pt-14\">\n <Suspense\n fallback={\n <div className=\"flex h-full w-full items-center justify-center text-muted-foreground\">\n Loading live support…\n </div>\n }\n >\n <VoiceHandoffPanel\n handoffStatus={handoffStatus}\n joinResult={handoffJoin}\n isRequesting={isRequestingHandoff}\n error={handoffError}\n onRequestToken={requestHandoffToken}\n onEnd={endHandoff}\n />\n </Suspense>\n </ThreadPrimitive.Viewport>\n ) : (\n <ThreadPrimitive.Viewport className=\"aui-thread-viewport relative flex min-h-0 flex-1 flex-col overflow-x-hidden overflow-y-scroll scroll-smooth px-4 pt-14\">\n <AssistantIf condition={({ thread }) => thread.isEmpty}>\n <ThreadWelcome />\n </AssistantIf>\n\n <ThreadPrimitive.Messages\n components={{\n UserMessage,\n AssistantMessage,\n }}\n />\n\n <ThinkingIndicator />\n\n <ThreadPrimitive.ViewportFooter className=\"aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible bg-transparent pt-2 pb-4 md:pb-6\">\n <ThreadScrollToBottom />\n <Composer\n handoffStatus={handoffStatus}\n />\n </ThreadPrimitive.ViewportFooter>\n </ThreadPrimitive.Viewport>\n )}\n </ThreadPrimitive.Root>\n );\n};\n\nconst ThreadScrollToBottom: FC = () => {\n return (\n <ThreadPrimitive.ScrollToBottom asChild>\n <TooltipIconButton\n tooltip=\"Scroll to bottom\"\n variant=\"outline\"\n className=\"aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible border-border bg-background text-muted-foreground dark:bg-muted dark:text-foreground\"\n >\n <ArrowDownIcon className=\"size-4\" />\n </TooltipIconButton>\n </ThreadPrimitive.ScrollToBottom>\n );\n};\n\nconst ThreadWelcome: FC = () => {\n return (\n <div className=\"aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col\">\n <div className=\"aui-thread-welcome-center flex w-full grow flex-col items-center justify-center\">\n <div className=\"aui-thread-welcome-message flex size-full flex-col justify-center px-4\">\n <h1 className=\"aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-base duration-200\">\n How can I help?\n </h1>\n </div>\n </div>\n <ThreadSuggestions />\n </div>\n );\n};\n\nconst ThreadSuggestions: FC = () => {\n const { prompts, hasPrompts } = usePrompts();\n\n if (!hasPrompts) {\n return null;\n }\n\n return (\n <div className=\"aui-thread-welcome-suggestions flex w-full flex-wrap gap-2 px-4 pb-4\">\n {prompts.slice(0, 4).map((prompt, index) => (\n <div\n key={prompt.name}\n className=\"aui-thread-welcome-suggestion-display fade-in slide-in-from-bottom-2 animate-in fill-mode-both duration-200\"\n style={{ animationDelay: `${100 + index * 50}ms` }}\n >\n <ThreadPrimitive.Suggestion\n prompt={prompt.description || prompt.name}\n send\n asChild\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"aui-thread-welcome-suggestion rounded-full text-xs transition-colors\"\n aria-label={prompt.description || prompt.name}\n >\n {prompt.name}\n </Button>\n </ThreadPrimitive.Suggestion>\n </div>\n ))}\n </div>\n );\n};\n\ninterface ComposerProps {\n handoffStatus: HandoffStatus;\n}\n\nconst Composer: FC<ComposerProps> = ({\n handoffStatus,\n}) => {\n const {\n isActive: isVoiceActive,\n isConnecting: isVoiceConnecting,\n start: startVoice,\n } = useVoiceThread();\n const voiceApproval = useVoiceToolApproval();\n const { currentThreadId } = useCloudflareThread();\n\n const isVoiceMode = isVoiceActive || isVoiceConnecting;\n const isVoiceApprovalPending = isVoiceMode && !!voiceApproval.pendingApproval;\n\n return (\n <ComposerPrimitive.Root\n key={currentThreadId}\n className=\"aui-composer-root relative flex w-full flex-col\"\n >\n <ComposerPrimitive.AttachmentDropzone className=\"aui-composer-attachment-dropzone flex w-full flex-col rounded-2xl border border-composer-border bg-composer-bg shadow-none px-1 pt-2 outline-none has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-2 has-[textarea:focus-visible]:ring-ring/20 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50\">\n <ComposerAttachments />\n {/* <ComposerToolSources /> */}\n {isVoiceMode ? (\n isVoiceApprovalPending ? (\n <div className=\"px-1 pt-1 pb-1\">\n <VoiceToolApprovalPanel variant=\"composer\" />\n </div>\n ) : (\n <ComposerVoiceContent />\n )\n ) : (\n <ComposerPrimitive.Input\n placeholder=\"Send a message...\"\n className=\"aui-composer-input mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm text-composer-text outline-none placeholder:text-composer-placeholder focus-visible:ring-0\"\n rows={1}\n autoFocus\n aria-label=\"Message input\"\n />\n )}\n {!isVoiceApprovalPending ? (\n <ComposerAction\n handoffStatus={handoffStatus}\n isVoiceMode={isVoiceMode}\n onStartVoice={startVoice}\n />\n ) : null}\n </ComposerPrimitive.AttachmentDropzone>\n </ComposerPrimitive.Root>\n );\n};\n\nconst getSourceLabel = (source: ToolSourceInfo): string => {\n const title = source.title?.trim();\n if (title) return title;\n\n const fallback = source.url ?? source.origin ?? \"Tab\";\n try {\n return new URL(fallback).hostname || fallback;\n } catch {\n return fallback;\n }\n};\n\nconst getSourceKey = (source: ToolSourceInfo): string => {\n return source.sourceId;\n};\n\nconst getSelectionKey = (\n selection: ThreadToolSelection[\"selectedSources\"][number],\n): string => {\n return selection.sourceId;\n};\n\nconst buildSelection = (\n selection: ThreadToolSelection | null,\n source: ToolSourceInfo,\n): ThreadToolSelection => {\n const current = selection?.selectedSources ?? [];\n const selectedSet = new Set(current.map(getSelectionKey));\n const key = getSourceKey(source);\n const nextSelector = { sourceId: source.sourceId, tabId: source.tabId };\n\n const next =\n selectedSet.has(key)\n ? current.filter((item) => getSelectionKey(item) !== key)\n : [...current, nextSelector];\n\n return { selectedSources: next };\n};\n\nconst ComposerToolSources: FC = () => {\n const toolSelection = useToolSelection();\n const { sources, selection, currentSourceId, setSelection } = toolSelection;\n\n const selectedSources = selection?.selectedSources ?? [];\n const selectedKeys = useMemo(\n () => new Set(selectedSources.map(getSelectionKey)),\n [selectedSources],\n );\n\n const handleToggle = useCallback(\n (source: ToolSourceInfo) => {\n const nextSelection = buildSelection(selection, source);\n setSelection(nextSelection).catch(() => undefined);\n },\n [selection, setSelection],\n );\n\n if (sources.length === 0) {\n return null;\n }\n\n return (\n <div className=\"aui-composer-tool-sources flex flex-wrap gap-1 px-3 pb-1\">\n {sources.map((source) => {\n const key = getSourceKey(source);\n const isSelected = selectedKeys.has(key);\n const label = getSourceLabel(source);\n const isLocal = currentSourceId === source.sourceId;\n return (\n <button\n key={key}\n type=\"button\"\n onClick={() => handleToggle(source)}\n className={cn(\n \"flex items-center gap-1.5 rounded-full border px-2 py-1 text-[11px] transition-colors\",\n isSelected\n ? \"border-primary/50 bg-primary/10 text-primary\"\n : \"border-border/50 bg-muted/40 text-muted-foreground hover:bg-muted/60\",\n )}\n aria-pressed={isSelected}\n title={label}\n >\n {source.iconUrl ? (\n <img\n src={source.iconUrl}\n alt=\"\"\n className=\"h-3 w-3 rounded-sm\"\n loading=\"lazy\"\n />\n ) : (\n <span className=\"h-2 w-2 rounded-sm bg-muted-foreground/40\" />\n )}\n <span className=\"max-w-[140px] truncate\">{label}</span>\n {isLocal ? (\n <span className=\"text-[10px] text-primary/80\">This tab</span>\n ) : null}\n <span className=\"text-[10px] text-muted-foreground\">\n {source.toolCount}\n </span>\n </button>\n );\n })}\n </div>\n );\n};\n\n/**\n * Compact approval mode button for the composer footer.\n */\nconst ComposerApprovalButton: FC = () => {\n const { mode, setMode } = useToolApproval();\n const isAskMode = mode === \"ask\";\n\n const handleToggle = useCallback(() => {\n setMode(isAskMode ? \"auto\" : \"ask\");\n }, [isAskMode, setMode]);\n\n return (\n <TooltipIconButton\n variant=\"ghost\"\n size=\"icon\"\n className={cn(\n \"size-7 rounded-full transition-colors\",\n isAskMode\n ? \"text-amber-500 hover:text-amber-400 hover:bg-amber-500/10\"\n : \"text-muted-foreground hover:text-foreground hover:bg-muted/50\"\n )}\n onClick={handleToggle}\n tooltip={\n isAskMode\n ? \"Ask before destructive actions (click to auto-approve)\"\n : \"Auto-approve all actions (click to ask first)\"\n }\n side=\"top\"\n >\n {isAskMode ? (\n <Shield className=\"h-3.5 w-3.5\" />\n ) : (\n <ShieldOff className=\"h-3.5 w-3.5\" />\n )}\n </TooltipIconButton>\n );\n};\n\nconst ComposerPolicyButton: FC = () => {\n const { enabled, name, events, clearEvents } = usePolicyPlugin();\n const [isOpen, setIsOpen] = useState(false);\n const latestEvent = events[0];\n const hasWarning = latestEvent?.status === \"notify\";\n const hasFailure = latestEvent?.status === \"failure\";\n\n if (!enabled) return null;\n\n return (\n <div className=\"relative\">\n <TooltipIconButton\n variant=\"ghost\"\n size=\"icon\"\n className={cn(\n \"size-7 rounded-full transition-colors\",\n hasFailure\n ? \"text-red-500 hover:text-red-400 hover:bg-red-500/10\"\n : hasWarning\n ? \"text-amber-500 hover:text-amber-400 hover:bg-amber-500/10\"\n : \"text-muted-foreground hover:text-foreground hover:bg-muted/50\",\n )}\n onClick={() => setIsOpen((prev) => !prev)}\n tooltip={\n latestEvent\n ? `${name}: ${latestEvent.status} (${latestEvent.toolName})`\n : `${name}: no policy events yet`\n }\n side=\"top\"\n >\n <ShieldAlert className=\"h-3.5 w-3.5\" />\n </TooltipIconButton>\n\n {isOpen ? (\n <div className=\"absolute bottom-9 left-0 z-50 w-72 rounded-xl border border-border bg-background/95 p-3 shadow-lg backdrop-blur-sm\">\n <div className=\"mb-2 flex items-center justify-between\">\n <div className=\"font-medium text-xs\">{name}</div>\n {events.length > 0 ? (\n <button\n type=\"button\"\n className=\"text-muted-foreground text-xs hover:text-foreground\"\n onClick={() => clearEvents()}\n >\n Clear\n </button>\n ) : null}\n </div>\n {events.length === 0 ? (\n <p className=\"text-muted-foreground text-xs\">No policy decisions yet.</p>\n ) : (\n <div className=\"space-y-2\">\n {events.slice(0, 4).map((event, idx) => (\n <div\n key={`${event.callId}-${idx}`}\n className=\"rounded-md border border-border/60 bg-muted/30 p-2\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span\n className={cn(\n \"rounded px-1.5 py-0.5 font-medium text-[10px] uppercase tracking-wide\",\n event.status === \"failure\"\n ? \"bg-red-500/15 text-red-500\"\n : event.status === \"notify\"\n ? \"bg-amber-500/15 text-amber-500\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {event.status}\n </span>\n <span className=\"text-[10px] text-muted-foreground\">\n {new Date(event.timestamp).toLocaleTimeString([], {\n hour: \"2-digit\",\n minute: \"2-digit\",\n })}\n </span>\n </div>\n <div className=\"mt-1 truncate text-xs\">{event.toolName}</div>\n <div className=\"mt-1 line-clamp-2 text-muted-foreground text-xs\">\n {event.message}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n ) : null}\n </div>\n );\n};\n\n/**\n * Isolated voice UI that subscribes to high-frequency state (audioLevel,\n * speaking indicators) so the parent Composer doesn't re-render at ~30fps.\n */\nconst ComposerVoiceContent: FC = () => {\n const {\n isMuted,\n isActive,\n isConnecting,\n isUserSpeaking,\n isAssistantSpeaking,\n audioLevel,\n inputDeviceId,\n stop: stopVoice,\n toggleMute,\n setInputDevice,\n } = useVoiceThread();\n const [deviceError, setDeviceError] = useState<string | null>(null);\n\n const isVoiceMode = isActive || isConnecting;\n const voiceWaveLevel = Math.max(\n audioLevel?.micLevel ?? 0,\n audioLevel?.speakerLevel ?? 0,\n );\n const isVoiceWaveActive = isUserSpeaking || isAssistantSpeaking;\n\n const handleVoiceDeviceChange = useCallback(\n async (deviceId: string) => {\n setDeviceError(null);\n try {\n await setInputDevice(deviceId);\n } catch (error) {\n console.error(\"[Composer] Failed to switch microphone:\", error);\n setDeviceError(\n error instanceof Error ? error.message : \"Failed to switch microphone\",\n );\n }\n },\n [setInputDevice],\n );\n\n return (\n <>\n <div className=\"px-2 pt-1 pb-1\">\n <ComposerVoiceControls\n muted={isMuted}\n onMutedChange={toggleMute}\n onStop={stopVoice}\n inputDeviceId={inputDeviceId}\n onSetInputDevice={handleVoiceDeviceChange}\n />\n </div>\n {deviceError ? (\n <p className=\"px-3 text-xs text-destructive\">{deviceError}</p>\n ) : null}\n <div className=\"px-3 pt-1 pb-2\">\n <LiveWaveform\n active={isVoiceWaveActive}\n processing={isVoiceMode && !isVoiceWaveActive}\n level={voiceWaveLevel}\n mode=\"scrolling\"\n height={32}\n className=\"w-full text-muted-foreground\"\n />\n </div>\n </>\n );\n};\n\nconst ComposerVoiceControls: FC<{\n muted: boolean;\n onMutedChange: (muted: boolean) => void;\n onStop: () => void;\n inputDeviceId?: string;\n onSetInputDevice: (deviceId: string) => Promise<void>;\n}> = ({\n muted,\n onMutedChange,\n onStop,\n inputDeviceId,\n onSetInputDevice,\n}) => {\n return (\n <div className=\"flex w-full items-center gap-1.5\">\n <div className=\"min-w-0 flex-1\">\n <MicSelector\n value={inputDeviceId}\n onValueChange={onSetInputDevice}\n muted={muted}\n onMutedChange={onMutedChange}\n />\n </div>\n <TooltipIconButton\n tooltip=\"End voice session\"\n side=\"top\"\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-8 rounded-full text-muted-foreground hover:bg-muted/50 hover:text-foreground\"\n onClick={onStop}\n aria-label=\"End voice session\"\n >\n <SquareIcon className=\"size-3 fill-current\" />\n </TooltipIconButton>\n </div>\n );\n};\n\nconst ComposerHandoffButton: FC<{\n status: HandoffStatus;\n isVoiceMode: boolean;\n onStartVoice: () => Promise<void>;\n}> = ({ status, isVoiceMode, onStartVoice }) => {\n const { isError, error: voiceError } = useVoiceThread();\n const [isStarting, setIsStarting] = useState(false);\n\n const handleClick = useCallback(() => {\n setIsStarting(true);\n onStartVoice()\n .catch((error) => {\n console.error(\"[ComposerHandoffButton] Failed to start voice session:\", error);\n })\n .finally(() => setIsStarting(false));\n }, [onStartVoice]);\n\n if (status !== AI_ONLY_HANDOFF_STATUS || isVoiceMode) return null;\n\n return (\n <>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7 gap-1.5 rounded-full px-3 text-xs\"\n onClick={handleClick}\n disabled={isStarting}\n >\n <PhoneCall className=\"h-3.5 w-3.5\" />\n {isStarting ? \"Connecting...\" : \"Talk to support\"}\n </Button>\n {!isStarting && isError && voiceError ? (\n <p className=\"text-xs text-destructive\">{voiceError}</p>\n ) : null}\n </>\n );\n};\n\nconst ComposerAction: FC<{\n handoffStatus: HandoffStatus;\n isVoiceMode: boolean;\n onStartVoice: () => Promise<void>;\n}> = ({\n handoffStatus,\n isVoiceMode,\n onStartVoice,\n}) => {\n return (\n <div className=\"aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between\">\n {/* Left side - Attachments, Approval, Support */}\n <div className=\"flex items-center gap-1\">\n <ComposerAddAttachment />\n <ComposerPolicyButton />\n <ComposerHandoffButton\n status={handoffStatus}\n isVoiceMode={isVoiceMode}\n onStartVoice={onStartVoice}\n />\n <ComposerApprovalButton />\n </div>\n\n {/* Right side - Send/Cancel */}\n <div className=\"flex items-center gap-1\">\n <AssistantIf condition={({ thread }) => !thread.isRunning}>\n <ComposerPrimitive.Send asChild>\n <TooltipIconButton\n tooltip=\"Send message\"\n side=\"top\"\n type=\"submit\"\n variant=\"default\"\n size=\"icon\"\n className=\"aui-composer-send size-8 rounded-full\"\n aria-label=\"Send message\"\n >\n <ArrowUpIcon className=\"aui-composer-send-icon size-4\" />\n </TooltipIconButton>\n </ComposerPrimitive.Send>\n </AssistantIf>\n\n <AssistantIf condition={({ thread }) => thread.isRunning}>\n <ComposerPrimitive.Cancel asChild>\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"icon\"\n className=\"aui-composer-cancel size-8 rounded-full\"\n aria-label=\"Stop generating\"\n >\n <SquareIcon className=\"aui-composer-cancel-icon size-3 fill-current\" />\n </Button>\n </ComposerPrimitive.Cancel>\n </AssistantIf>\n </div>\n </div>\n );\n};\n\nconst MessageError: FC = () => {\n return (\n <MessagePrimitive.Error>\n <ErrorPrimitive.Root className=\"aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200\">\n <ErrorPrimitive.Message className=\"aui-message-error-message line-clamp-2\" />\n </ErrorPrimitive.Root>\n </MessagePrimitive.Error>\n );\n};\n\nconst AssistantMessage: FC = () => {\n return (\n <MessagePrimitive.Root\n className=\"aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150\"\n data-role=\"assistant\"\n >\n <div className=\"aui-assistant-message-content wrap-break-word px-2 text-assistant-bubble-text leading-relaxed\">\n <MessagePrimitive.Parts\n components={{\n Text: MarkdownText,\n Reasoning: Reasoning,\n ReasoningGroup: ReasoningGroup,\n tools: { Fallback: UnifiedToolFallback },\n }}\n />\n <MessageError />\n </div>\n\n <div className=\"aui-assistant-message-footer mt-1 ml-2 flex\">\n <AssistantActionBar />\n </div>\n </MessagePrimitive.Root>\n );\n};\n\nconst AssistantActionBar: FC = () => {\n return (\n <ActionBarPrimitive.Root\n hideWhenRunning\n autohide=\"not-last\"\n autohideFloat=\"single-branch\"\n className=\"aui-assistant-action-bar-root col-start-3 row-start-2 -ml-1 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm\"\n >\n <ActionBarPrimitive.Copy asChild>\n <TooltipIconButton tooltip=\"Copy\">\n <AssistantIf condition={({ message }) => message.isCopied}>\n <CheckIcon className=\"size-4\" />\n </AssistantIf>\n <AssistantIf condition={({ message }) => !message.isCopied}>\n <CopyIcon className=\"size-4\" />\n </AssistantIf>\n </TooltipIconButton>\n </ActionBarPrimitive.Copy>\n </ActionBarPrimitive.Root>\n );\n};\n\nconst UserMessage: FC = () => {\n return (\n <MessagePrimitive.Root\n className=\"aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] justify-items-end content-start gap-y-2 px-2 py-3 duration-150 [&:where(>*)]:col-start-2\"\n data-role=\"user\"\n >\n <UserMessageAttachments />\n\n <div className=\"aui-user-message-content-wrapper relative col-start-2 min-w-0\">\n <div className=\"aui-user-message-content wrap-break-word rounded-2xl bg-user-bubble-bg px-4 py-2.5 text-user-bubble-text\">\n <MessagePrimitive.Parts\n components={{\n Text: ({ text }) => <span>{text}</span>,\n }}\n />\n </div>\n </div>\n </MessagePrimitive.Root>\n );\n};\n","'use client'\n\nimport { ThreadListPrimitive } from '@assistant-ui/react'\nimport { Archive, Plus } from 'lucide-react'\n\nimport { cn } from '../../utils/cn'\n\nimport type { FC } from 'react'\nimport { useCloudflareThread } from '../../providers/CloudflareThreadRuntimeProvider'\n\nexport interface AgentThreadListProps {\n\tclassName?: string\n\tonSelectThread?: () => void\n}\n\nexport const AgentThreadList: FC<AgentThreadListProps> = ({ className, onSelectThread }) => {\n\tconst { threads, isLoading, currentThreadId, setCurrentThreadId, archiveThread } = useCloudflareThread()\n\n\treturn (\n\t\t<ThreadListPrimitive.Root className={cn('flex flex-col gap-2', className)}>\n\t\t\t<ThreadListNew />\n\t\t\t{isLoading && threads.length === 0 ? (\n\t\t\t\t<ThreadListSkeleton />\n\t\t\t) : (\n\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t{threads.map((thread) => (\n\t\t\t\t\t\t<ThreadListItem\n\t\t\t\t\t\t\tkey={thread.id}\n\t\t\t\t\t\t\ttitle={thread.title}\n\t\t\t\t\t\t\tisActive={thread.id === currentThreadId}\n\t\t\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t\t\tsetCurrentThreadId(thread.id)\n\t\t\t\t\t\t\t\tonSelectThread?.()\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonArchive={() => {\n\t\t\t\t\t\t\t\tarchiveThread(thread.id).catch((error) => {\n\t\t\t\t\t\t\t\t\tconsole.error('[AgentThreadList] Failed to archive thread:', error)\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</ThreadListPrimitive.Root>\n\t)\n}\n\nconst ThreadListNew: FC = () => {\n\treturn (\n\t\t<ThreadListPrimitive.New asChild>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'flex h-9 w-full items-center justify-start gap-2 rounded-md px-3 text-sm',\n\t\t\t\t\t'border border-border bg-muted/50 text-foreground/80',\n\t\t\t\t\t'transition-colors hover:bg-muted hover:text-foreground',\n\t\t\t\t\t'data-[active=true]:bg-muted'\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<Plus className=\"size-4\" />\n\t\t\t\tNew thread\n\t\t\t</button>\n\t\t</ThreadListPrimitive.New>\n\t)\n}\n\nconst ThreadListSkeleton: FC = () => {\n\treturn (\n\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t{Array.from({ length: 6 }, (_, idx) => (\n\t\t\t\t<div\n\t\t\t\t\tkey={`thread-skeleton-${idx}`}\n\t\t\t\t\tclassName=\"h-8 rounded-md bg-muted/50 animate-pulse\"\n\t\t\t\t/>\n\t\t\t))}\n\t\t</div>\n\t)\n}\n\ninterface ThreadListItemProps {\n\ttitle: string | undefined\n\tisActive: boolean\n\tonSelect: () => void\n\tonArchive: () => void\n}\n\nconst ThreadListItem: FC<ThreadListItemProps> = ({\n\ttitle,\n\tisActive,\n\tonSelect,\n\tonArchive,\n}) => {\n\treturn (\n\t\t<div\n\t\t\tdata-active={isActive}\n\t\t\tclassName={cn(\n\t\t\t\t'group flex h-9 items-center rounded-lg transition-colors',\n\t\t\t\t'hover:bg-muted focus-visible:bg-muted focus-visible:outline-none',\n\t\t\t\t'data-[active=true]:bg-muted'\n\t\t\t)}\n\t\t>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={onSelect}\n\t\t\t\tclassName=\"flex h-full flex-1 items-center gap-2 truncate px-3 text-start text-sm text-foreground/80\"\n\t\t\t>\n\t\t\t\t<span className=\"truncate\">\n\t\t\t\t\t{title || 'New chat'}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t\t<div className=\"flex items-center pr-2\">\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttitle=\"Archive thread\"\n\t\t\t\t\taria-label=\"Archive thread\"\n\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\te.stopPropagation()\n\t\t\t\t\t\tonArchive()\n\t\t\t\t\t}}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'inline-flex size-7 items-center justify-center rounded-md p-0',\n\t\t\t\t\t\t'text-muted-foreground hover:text-foreground',\n\t\t\t\t\t\t'opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Archive className=\"size-4\" />\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n","import { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { humanizeToolName } from '../utils/format'\n\nimport type { ToolCallMetadata } from '@mcp-b/shared-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","'use client'\n\nimport { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\ninterface TextPart {\n\ttype: 'text'\n\ttext: string\n}\n\n/**\n * Returns the last text part from the most recent assistant message (if any).\n */\nexport function useLatestSummary(): string | null {\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\t\tif (!lastAssistantMessage) return null\n\n\t\tconst textParts = lastAssistantMessage.content.filter((c): c is TextPart => c.type === 'text')\n\t\treturn textParts.at(-1)?.text ?? null\n\t}, [messages])\n}\n\n","/**\n * ThreadControlProvider\n *\n * Provides thread control operations (reset, startNew) to child components.\n * This bridges the active runtime's reset/startNew functions to the UI layer.\n *\n * Thread controls allow consumers to:\n * - Reset the current conversation (clear all messages)\n * - Start a new conversation (alias for reset in single-thread model)\n *\n * @example Basic usage\n * ```tsx\n * import { useThreadControl } from '@mcp-b/embedded-agent'\n *\n * function ChatControls() {\n * const { reset } = useThreadControl()\n *\n * return (\n * <button onClick={reset}>\n * New Conversation\n * </button>\n * )\n * }\n * ```\n */\n\nimport { createContext, useContext, useMemo } from 'react'\n\nimport type { FC, ReactNode } from 'react'\n\n/**\n * Thread control context value\n */\nexport interface ThreadControlContextValue {\n\t/** Reset the conversation - clears all messages on frontend and backend */\n\treset: () => Promise<void>\n\t/** Start a new conversation (multi-thread aware) */\n\tstartNew: () => Promise<void>\n}\n\nconst ThreadControlContext = createContext<ThreadControlContextValue | null>(null)\n\nexport interface ThreadControlProviderProps {\n\tchildren: ReactNode\n\t/** Reset function from the active runtime */\n\treset: () => Promise<void>\n\t/** Start-new function (defaults to reset) */\n\tstartNew?: () => Promise<void>\n}\n\n/**\n * Provider for thread control operations.\n *\n * This provider is used internally by AgentProvider to expose\n * the reset/startNew functions from the active runtime to child components.\n */\nexport const ThreadControlProvider: FC<ThreadControlProviderProps> = ({\n\tchildren,\n\treset,\n\tstartNew,\n}) => {\n\tconst value = useMemo<ThreadControlContextValue>(\n\t\t() => ({\n\t\t\treset,\n\t\t\tstartNew: startNew ?? reset,\n\t\t}),\n\t\t[reset, startNew]\n\t)\n\n\treturn <ThreadControlContext.Provider value={value}>{children}</ThreadControlContext.Provider>\n}\n\n/**\n * Hook to access thread control operations\n * @throws Error if used outside ThreadControlProvider\n */\nexport function useThreadControl(): ThreadControlContextValue {\n\tconst context = useContext(ThreadControlContext)\n\tif (!context) {\n\t\tthrow new Error('useThreadControl must be used within a ThreadControlProvider')\n\t}\n\treturn context\n}\n\n/**\n * Hook to optionally access thread control operations (returns null if not in provider)\n */\nexport function useOptionalThreadControl(): ThreadControlContextValue | null {\n\treturn useContext(ThreadControlContext)\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 * @example Thread controls (clear/new conversation)\n * ```tsx\n * function ChatControls() {\n * const agent = useAgent()\n *\n * return (\n * <button onClick={() => agent.thread?.startNew()}>\n * New Conversation\n * </button>\n * )\n * }\n * ```\n */\n\nimport { useThread } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport { useActions } from './useActions'\nimport { useLatestSummary } from './useLatestSummary'\nimport { useMCPTools } from '../providers/MCPToolsProvider'\nimport { useVoiceThread } from '../providers/VoiceThreadBridge'\nimport { useThreadControl } from '../providers/ThreadControlProvider'\n\nimport type { CallToolResult, GetPromptResult, Prompt } from '@modelcontextprotocol/sdk/types.js'\nimport type { ToolWithSource } from '@mcp-b/shared-types'\nimport type { Action } from './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 user is currently speaking */\n\tisUserSpeaking: boolean\n\t/** Whether assistant is currently speaking */\n\tisAssistantSpeaking: 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 assistant audio playback mute */\n\ttoggleMute: (muted?: boolean) => void\n\t/** Send text message while in voice mode */\n\tsendMessage: (text: string) => void\n\t/** Set microphone input device */\n\tsetInputDevice: (deviceId: string) => Promise<void>\n\t/** Selected microphone input device ID */\n\tinputDeviceId?: string\n}\n\n/**\n * Thread controls for conversation management\n */\nexport interface AgentThread {\n\t/** Reset the conversation - clears all messages on frontend and backend */\n\treset: () => Promise<void>\n\t/** Start a new conversation (alias for reset in single-thread model) */\n\tstartNew: () => Promise<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\tmetadata?: Record<string, unknown>\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\n\tvoice: AgentVoice\n\n\t// MCP tools\n\ttools: AgentTools\n\n\t// Thread controls\n\t/** Thread controls for conversation management */\n\tthread: AgentThread\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\n\t// Derive action states inline (previously separate hooks)\n\tconst currentAction = useMemo(\n\t\t() => actions.find((a) => a.status === 'running') ?? null,\n\t\t[actions]\n\t)\n\tconst recentActions = useMemo(\n\t\t() => actions.filter((a) => a.status === 'success' || a.status === 'error').slice(-3),\n\t\t[actions]\n\t)\n\tconst lastCompletedAction = useMemo(() => {\n\t\tconst completed = actions.filter((a) => a.status === 'success' || a.status === 'error')\n\t\treturn completed.at(-1) ?? null\n\t}, [actions])\n\n\t// Summary from last assistant message\n\tconst summary = useLatestSummary()\n\n\t// Voice controls from VoiceThreadBridge\n\tconst voiceThread = useVoiceThread()\n\n\t// MCP tools\n\tconst mcpContext = useMCPTools()\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 = useMemo(() => ({\n\t\tisActive: voiceThread.isActive,\n\t\tisConnecting: voiceThread.isConnecting,\n\t\tisError: voiceThread.isError,\n\t\tisMuted: voiceThread.isMuted,\n\t\tisUserSpeaking: voiceThread.isUserSpeaking,\n\t\tisAssistantSpeaking: voiceThread.isAssistantSpeaking,\n\t\tisSupported: voiceThread.isSupported,\n\t\terror: voiceThread.error,\n\t\tsessionId: voiceThread.sessionId,\n\t\taudioLevel: voiceThread.audioLevel,\n\t\ttranscript: voiceThread.transcript,\n\t\tstart: voiceThread.start,\n\t\tstop: voiceThread.stop,\n\t\ttoggleMute: voiceThread.toggleMute,\n\t\tsendMessage: voiceThread.sendMessage,\n\t\tsetInputDevice: voiceThread.setInputDevice,\n\t\tinputDeviceId: voiceThread.inputDeviceId,\n\t}), [voiceThread])\n\n\t// Build tools interface\n\tconst tools: AgentTools = useMemo(() => ({\n\t\tlist: mcpContext.tools,\n\t\tcall: mcpContext.callTool,\n\t\tprompts: mcpContext.prompts ?? [],\n\t\tgetPrompt: mcpContext.getPrompt,\n\t}), [mcpContext])\n\n\t// Thread controls from ThreadControlProvider\n\tconst threadControl = useThreadControl()\n\n\t// Build thread interface\n\tconst thread: AgentThread = useMemo(() => ({\n\t\treset: threadControl.reset,\n\t\tstartNew: threadControl.startNew,\n\t}), [threadControl])\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// Thread controls\n\t\t\tthread,\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\tthread,\n\t\t\tisVoiceActive,\n\t\t]\n\t)\n}\n","/**\n * useAgentThreads\n *\n * Facade for assistant-ui thread list state + actions.\n *\n * Why this exists:\n * - Keep embedded-agent UI components from depending directly on assistant-ui internals.\n * - Provide a stable API surface for swapping UIs (pill, sidebar, mobile takeover).\n *\n * Note: In anonymous mode, threads are tied to a localStorage session ID and are\n * limited to the current browser (no cross-device sync).\n */\n\nimport { useAssistantApi, useAssistantState } from '@assistant-ui/react'\nimport { useCallback, useMemo } from 'react'\n\nexport type AgentThreadStatus = 'regular' | 'archived'\n\nexport interface AgentThreadListItem {\n\tid: string\n\ttitle?: string\n\tstatus: AgentThreadStatus\n\tremoteId?: string\n\texternalId?: string\n}\n\nexport interface AgentThreadsState {\n\tisLoading: boolean\n\tcurrentThreadId: string\n\tthreadIds: readonly string[]\n\tarchivedThreadIds: readonly string[]\n\titemsById: Readonly<Record<string, AgentThreadListItem>>\n\n\tswitchToThread: (threadId: string) => void\n\tswitchToNewThread: () => void\n\trename: (threadId: string, title: string) => void\n\tarchive: (threadId: string) => void\n}\n\nexport function useAgentThreads(): AgentThreadsState {\n\tconst api = useAssistantApi()\n\n\tconst isLoading = useAssistantState(({ threads }) => threads.isLoading)\n\tconst currentThreadId = useAssistantState(({ threads }) => threads.mainThreadId)\n\tconst threadIds = useAssistantState(({ threads }) => threads.threadIds)\n\tconst archivedThreadIds = useAssistantState(({ threads }) => threads.archivedThreadIds)\n\tconst threadItems = useAssistantState(({ threads }) => threads.threadItems)\n\n\tconst itemsById = useMemo(() => {\n\t\tconst entries = threadItems.map((item) => {\n\t\t\tconst normalized: AgentThreadListItem = {\n\t\t\t\tid: item.id,\n\t\t\t\ttitle: item.title,\n\t\t\t\tstatus: item.status as AgentThreadStatus,\n\t\t\t\tremoteId: item.remoteId,\n\t\t\t\texternalId: item.externalId,\n\t\t\t}\n\t\t\treturn [item.id, normalized] as const\n\t\t})\n\t\treturn Object.fromEntries(entries) as Readonly<Record<string, AgentThreadListItem>>\n\t}, [threadItems])\n\n\tconst switchToThread = useCallback(\n\t\t(threadId: string) => {\n\t\t\tapi.threads().switchToThread(threadId)\n\t\t},\n\t\t[api],\n\t)\n\n\tconst switchToNewThread = useCallback(() => {\n\t\tapi.threads().switchToNewThread()\n\t}, [api])\n\n\tconst rename = useCallback(\n\t\t(threadId: string, title: string) => {\n\t\t\tapi.threads().item({ id: threadId }).rename(title)\n\t\t},\n\t\t[api],\n\t)\n\n\tconst archive = useCallback(\n\t\t(threadId: string) => {\n\t\t\tapi.threads().item({ id: threadId }).archive()\n\t\t},\n\t\t[api],\n\t)\n\n\treturn useMemo(\n\t\t() => ({\n\t\t\tisLoading,\n\t\t\tcurrentThreadId,\n\t\t\tthreadIds,\n\t\t\tarchivedThreadIds,\n\t\t\titemsById,\n\t\t\tswitchToThread,\n\t\t\tswitchToNewThread,\n\t\t\trename,\n\t\t\tarchive,\n\t\t}),\n\t\t[\n\t\t\tisLoading,\n\t\t\tcurrentThreadId,\n\t\t\tthreadIds,\n\t\t\tarchivedThreadIds,\n\t\t\titemsById,\n\t\t\tswitchToThread,\n\t\t\tswitchToNewThread,\n\t\t\trename,\n\t\t\tarchive,\n\t\t],\n\t)\n}\n","/**\n * ErrorScreen Component\n *\n * Full-screen blocking error display for critical authentication failures.\n * Rendered inside the widget's shadow DOM, replaces entire widget content.\n * Used for configuration errors, unauthorized domains, and non-recoverable issues.\n *\n * Design: Professional, spacious, responsive. Works in sidebars and various UI contexts.\n */\n\nimport { X } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { TooltipIconButton } from \"@/components/assistant-ui/tooltip-icon-button\";\nimport { cn } from \"@/utils/cn\";\nimport type { AuthError } from \"@/utils/auth-errors\";\n\n/** Glassmorphic button styles (consistent with thread.tsx) */\nconst glassmorphicButtonClass =\n \"h-8 w-8 rounded-full border border-border backdrop-blur-sm shadow-lg shadow-black/20 bg-muted/50 transition-all duration-200 hover:border-border hover:bg-muted\";\n\nexport interface ErrorScreenProps {\n /** Authentication error with educational content */\n error: AuthError;\n /** Base URL for dashboard (e.g., \"https://app.usechar.ai\") */\n dashboardBaseUrl?: string;\n /** Base URL for documentation (e.g., \"https://docs.usechar.ai\") */\n docsBaseUrl?: string;\n /** Retry handler */\n onRetry?: () => void;\n /** Contact support handler */\n onContact?: () => void;\n /**\n * Close handler callback (secondary mechanism).\n * The close button also dispatches a 'char-close' CustomEvent\n * that bubbles through shadow DOM as the primary close mechanism.\n */\n onClose?: () => void;\n /** Show debug info (dev mode) */\n showDebug?: boolean;\n /** Additional className */\n className?: string;\n}\n\nexport function ErrorScreen({\n error,\n dashboardBaseUrl = \"\",\n docsBaseUrl = \"\",\n onRetry,\n onContact,\n onClose,\n showDebug = false,\n className,\n}: ErrorScreenProps) {\n const [isDebugExpanded, setIsDebugExpanded] = React.useState(false);\n\n const dashboardUrl = error.dashboardLink && dashboardBaseUrl\n ? `${dashboardBaseUrl}${error.dashboardLink}`\n : undefined;\n\n const docsUrl = error.docsLink\n ? error.docsLink.startsWith(\"http\")\n ? error.docsLink\n : `${docsBaseUrl}${error.docsLink}`\n : undefined;\n\n return (\n <div\n className={cn(\n \"relative flex flex-col items-center justify-center h-full w-full p-4\",\n className\n )}\n data-error-screen\n data-error-code={error.code}\n >\n {/* Floating close button */}\n <div className=\"absolute top-2 right-2 z-50\">\n <TooltipIconButton\n variant=\"ghost\"\n size=\"icon\"\n className={glassmorphicButtonClass}\n onClick={(e) => {\n // Dispatch char-close event (primary mechanism for shadow DOM bubbling)\n try {\n e.currentTarget.dispatchEvent(\n new CustomEvent(\"char-close\", { bubbles: true, composed: true })\n );\n } catch (dispatchError) {\n console.error(\"[ErrorScreen] Failed to dispatch char-close event:\", dispatchError);\n }\n\n // Call onClose callback if provided (secondary mechanism)\n if (onClose) {\n try {\n onClose();\n } catch (callbackError) {\n console.error(\"[ErrorScreen] onClose callback threw:\", callbackError);\n }\n } else {\n // Warn if no callback provided - event dispatch is the only mechanism\n // If no listener is registered, the close button will appear non-functional\n console.debug(\"[ErrorScreen] Close clicked - relying on char-close event listener\");\n }\n }}\n tooltip=\"Close\"\n side=\"bottom\"\n >\n <X className=\"h-4 w-4\" />\n </TooltipIconButton>\n </div>\n\n {/* Error Card */}\n <div className=\"w-full max-w-lg bg-background border border-border rounded-xl shadow-xl overflow-hidden flex flex-col max-h-[90vh]\">\n {/* Content Container */}\n <div className=\"flex-1 overflow-y-auto px-6 py-8 space-y-6\">\n {/* Title and message */}\n <div className=\"space-y-3\">\n <h1 className=\"text-lg font-semibold text-foreground\">\n {error.title}\n </h1>\n <p className=\"text-xs text-muted-foreground/70 font-mono\">\n {error.code}\n </p>\n <p className=\"text-sm text-muted-foreground leading-relaxed\">\n {error.message}\n </p>\n </div>\n\n {/* Context information */}\n {error.context && Object.keys(error.context).length > 0 && (\n <div className=\"rounded-lg bg-muted/50 p-4 space-y-4 border border-border/50\">\n {error.context.currentDomain && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Current Domain\n </p>\n <code className=\"block text-xs bg-background px-3 py-2 rounded font-mono break-all\">\n {error.context.currentDomain}\n </code>\n </div>\n )}\n {error.context.missingField && (\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Missing Configuration\n </p>\n <p className=\"text-sm text-foreground\">{error.context.missingField}</p>\n </div>\n )}\n {error.context.expectedIssuer && error.context.actualIssuer && (\n <>\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Expected Issuer\n </p>\n <code className=\"block text-xs bg-background px-3 py-2 rounded font-mono break-all\">\n {error.context.expectedIssuer}\n </code>\n </div>\n <div>\n <p className=\"text-xs font-medium text-muted-foreground mb-2\">\n Token Issuer\n </p>\n <code className=\"block text-xs bg-background px-3 py-2 rounded font-mono break-all\">\n {error.context.actualIssuer}\n </code>\n </div>\n </>\n )}\n </div>\n )}\n\n {/* Call to action steps */}\n {error.callToAction && error.callToAction.steps.length > 0 && (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n How to Fix\n </h2>\n <ol className=\"space-y-2.5 text-sm text-foreground list-decimal list-inside leading-relaxed\">\n {error.callToAction.steps.map((step, index) => (\n <li key={index} className=\"leading-relaxed\">\n {step}\n </li>\n ))}\n </ol>\n </div>\n )}\n\n {/* Examples */}\n {error.callToAction?.examples && error.callToAction.examples.length > 0 && (\n <div className=\"rounded-lg bg-muted/50 p-4 border border-border/50 space-y-2\">\n <p className=\"text-xs font-medium text-muted-foreground\">\n Examples\n </p>\n <div className=\"space-y-2\">\n {error.callToAction.examples.map((example, index) => (\n <code\n key={index}\n className=\"block text-xs bg-background px-3 py-2 rounded font-mono break-all\"\n >\n {example}\n </code>\n ))}\n </div>\n </div>\n )}\n\n {/* Debug info */}\n {showDebug && error.debugInfo && (\n <details\n className=\"rounded-lg bg-muted/50 border border-border/50 overflow-hidden\"\n open={isDebugExpanded}\n onToggle={(e) => setIsDebugExpanded(e.currentTarget.open)}\n >\n <summary className=\"cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground hover:bg-muted/70\">\n Debug Information\n </summary>\n <pre className=\"text-xs whitespace-pre-wrap bg-background p-3 font-mono leading-normal\">\n {error.debugInfo}\n </pre>\n </details>\n )}\n </div>\n\n {/* Actions */}\n <div className=\"border-t border-border p-4 space-y-2\">\n {dashboardUrl && (\n <Button\n asChild\n className=\"w-full\"\n size=\"sm\"\n >\n <a href={dashboardUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Open Dashboard\n </a>\n </Button>\n )}\n\n {error.recoverable && onRetry && !dashboardUrl && (\n <Button\n onClick={onRetry}\n className=\"w-full\"\n size=\"sm\"\n >\n Retry\n </Button>\n )}\n\n <div className=\"flex flex-col sm:flex-row gap-2\">\n {docsUrl && (\n <Button\n asChild\n variant=\"outline\"\n size=\"sm\"\n className=\"flex-1\"\n >\n <a href={docsUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n View Guide\n </a>\n </Button>\n )}\n {onContact && (\n <Button\n onClick={onContact}\n variant=\"outline\"\n size=\"sm\"\n className=\"flex-1\"\n >\n Contact Support\n </Button>\n )}\n {error.recoverable && onRetry && dashboardUrl && (\n <Button\n onClick={onRetry}\n variant=\"outline\"\n size=\"sm\"\n className=\"flex-1\"\n >\n Retry\n </Button>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/**\n * AuthErrorBoundary Component\n *\n * React Error Boundary that catches all errors within the widget.\n * Prevents errors from propagating past the shadow DOM boundary to the host page.\n * Displays ErrorScreen for caught errors instead of crashing the widget.\n */\n\nimport * as React from \"react\";\nimport { APP_ERROR_CODES } from \"@char-ai/auth\";\nimport { ErrorScreen } from \"./ErrorScreen\";\nimport type { AuthError } from \"@/utils/auth-errors\";\n\nexport interface AuthErrorBoundaryProps {\n /** Child components to protect */\n children: React.ReactNode;\n /** Base URL for dashboard */\n dashboardBaseUrl?: string;\n /** Base URL for documentation */\n docsBaseUrl?: string;\n /** Fallback UI (optional, defaults to ErrorScreen) */\n fallback?: React.ComponentType<{ error: AuthError; reset: () => void }>;\n /** Callback when error is caught (for logging/analytics) */\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n /**\n * Callback to clear the underlying auth error state before retrying.\n * This enables the retry button to actually work by clearing the state\n * that would cause the error to be re-thrown on re-render.\n */\n onRetryAuth?: () => void;\n /**\n * Close handler callback (passed to ErrorScreen).\n * The ErrorScreen also dispatches a 'char-close' CustomEvent\n * that bubbles through shadow DOM as the primary close mechanism.\n */\n onClose?: () => void;\n /** Show debug info */\n showDebug?: boolean;\n}\n\ninterface AuthErrorBoundaryState {\n hasError: boolean;\n error: AuthError | null;\n retryFailed: boolean;\n retryErrorMessage: string | null;\n}\n\n/**\n * Error boundary for authentication errors.\n * Catches all errors and displays ErrorScreen instead of crashing.\n */\nexport class AuthErrorBoundary extends React.Component<\n AuthErrorBoundaryProps,\n AuthErrorBoundaryState\n> {\n constructor(props: AuthErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n retryFailed: false,\n retryErrorMessage: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<AuthErrorBoundaryState> {\n // Convert generic Error to AuthError\n const authError: AuthError = isAuthError(error)\n ? error\n : {\n code: APP_ERROR_CODES.INTERNAL_ERROR,\n title: \"Something Went Wrong\",\n message: \"An unexpected error occurred. Please try refreshing the page.\",\n recoverable: true,\n debugInfo: error.message,\n };\n\n return {\n hasError: true,\n error: authError,\n retryFailed: false,\n retryErrorMessage: null,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n // Log error but don't let it propagate to host page\n console.error(\"[Widget Error Boundary] Caught error:\", error, errorInfo);\n\n // Call optional error handler\n if (this.props.onError) {\n try {\n this.props.onError(error, errorInfo);\n } catch (handlerError) {\n console.error(\"[Widget Error Boundary] Error in onError handler:\", handlerError);\n }\n }\n }\n\n handleReset = () => {\n // Clear the underlying auth error state first (if callback provided)\n // This prevents the error from being immediately re-thrown on re-render\n if (this.props.onRetryAuth) {\n try {\n this.props.onRetryAuth();\n } catch (retryError) {\n console.error(\"[Widget Error Boundary] Error in onRetryAuth callback:\", retryError);\n // Don't proceed with reset - show retry failure instead\n this.setState({\n retryFailed: true,\n retryErrorMessage: retryError instanceof Error ? retryError.message : 'Retry failed',\n });\n return;\n }\n }\n\n // Only reset if retry succeeded or no callback\n this.setState({\n hasError: false,\n error: null,\n retryFailed: false,\n retryErrorMessage: null,\n });\n };\n\n handleContact = () => {\n // Open support email or contact page\n // This can be customized based on your support system\n window.open(\"mailto:alex@mcp-b.ai?subject=Widget%20Error\", \"_blank\");\n };\n\n render() {\n if (this.state.hasError && this.state.error) {\n const { fallback: FallbackComponent, dashboardBaseUrl, docsBaseUrl, onClose, showDebug } = this.props;\n\n // Show modified error if retry failed\n const displayError: AuthError = this.state.retryFailed\n ? {\n ...this.state.error,\n title: \"Retry Failed\",\n message: this.state.retryErrorMessage || \"Unable to retry. Please refresh the page.\",\n }\n : this.state.error;\n\n // Use custom fallback if provided\n if (FallbackComponent) {\n return <FallbackComponent error={displayError} reset={this.handleReset} />;\n }\n\n // Default to ErrorScreen\n return (\n <ErrorScreen\n error={displayError}\n dashboardBaseUrl={dashboardBaseUrl}\n docsBaseUrl={docsBaseUrl}\n onRetry={this.handleReset}\n onContact={this.handleContact}\n onClose={onClose}\n showDebug={showDebug}\n />\n );\n }\n\n return this.props.children;\n }\n}\n\n/**\n * Type guard to check if an error is an AuthError\n */\nfunction isAuthError(error: unknown): error is AuthError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n \"title\" in error &&\n \"message\" in error &&\n \"recoverable\" in error &&\n // Check for AuthErrorException class\n (error instanceof Error && error.name === \"AuthErrorException\" ||\n // Check for plain AuthError object\n typeof (error as any).code === \"string\")\n );\n}\n","'use client'\n\nimport { makeAssistantToolUI } from '@assistant-ui/react'\nimport { ArrowRight, Check } from 'lucide-react'\n\n/**\n * Args passed from the model when calling the done tool\n */\ntype DoneArgs = {\n\tsummary: string\n\tactions?: string[]\n\tnextSteps?: string[]\n}\n\n/**\n * DoneToolUI - Renders task completion as readable content\n *\n * Design Goals:\n * - Should NOT look like a tool or a card - just readable content\n * - Always fully expanded, no collapsing\n * - Clearly communicate what was accomplished\n * - Actions shown as checkmarked accomplishments\n * - Next steps as helpful suggestions\n */\nexport const DoneToolUI = makeAssistantToolUI<DoneArgs, string>({\n\ttoolName: 'done',\n\trender: ({ args }) => {\n\t\tconst summary = args.summary ?? 'Task completed'\n\t\tconst hasActions = args.actions && args.actions.length > 0\n\t\tconst hasNextSteps = args.nextSteps && args.nextSteps.length > 0\n\n\t\treturn (\n\t\t\t<div className=\"my-3 space-y-3\">\n\t\t\t\t{/* Summary - the main message, prominent */}\n\t\t\t\t<p className=\"text-sm text-foreground leading-relaxed\">{summary}</p>\n\n\t\t\t\t{/* What was accomplished - with checkmarks */}\n\t\t\t\t{hasActions && (\n\t\t\t\t\t<div className=\"space-y-1.5\">\n\t\t\t\t\t\t{args.actions!.map((action, i) => (\n\t\t\t\t\t\t\t<div key={i} className=\"flex items-start gap-2 text-sm\">\n\t\t\t\t\t\t\t\t<Check className=\"mt-0.5 h-4 w-4 shrink-0 text-primary\" />\n\t\t\t\t\t\t\t\t<span className=\"text-foreground/80\">{action}</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t{/* Suggested next steps */}\n\t\t\t\t{hasNextSteps && (\n\t\t\t\t\t<div className=\"space-y-1.5 pt-1\">\n\t\t\t\t\t\t<p className=\"text-xs font-medium text-muted-foreground\">You might want to:</p>\n\t\t\t\t\t\t{args.nextSteps!.map((step, i) => (\n\t\t\t\t\t\t\t<div key={i} className=\"flex items-start gap-2 text-sm\">\n\t\t\t\t\t\t\t\t<ArrowRight className=\"mt-0.5 h-4 w-4 shrink-0 text-muted-foreground\" />\n\t\t\t\t\t\t\t\t<span className=\"text-foreground/70\">{step}</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t)\n\t},\n})\n\nexport default DoneToolUI\n","\"use client\"\n\nimport * as React from \"react\"\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\"\nimport {\n DayPicker,\n getDefaultClassNames,\n type DayButton,\n} from \"react-day-picker\"\n\nimport { cn } from \"@/utils/cn\"\nimport { Button, buttonVariants } from \"@/components/ui/button\"\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n buttonVariant = \"ghost\",\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>[\"variant\"]\n}) {\n const defaultClassNames = getDefaultClassNames()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n \"bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent\",\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(\"default\", { month: \"short\" }),\n ...formatters,\n }}\n classNames={{\n root: cn(\"w-fit\", defaultClassNames.root),\n months: cn(\n \"flex gap-4 flex-col md:flex-row relative\",\n defaultClassNames.months\n ),\n month: cn(\"flex flex-col w-full gap-4\", defaultClassNames.month),\n nav: cn(\n \"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n dropdowns: cn(\n \"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute bg-popover inset-0 opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"select-none font-medium\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5\",\n defaultClassNames.caption_label\n ),\n table: \"w-full border-collapse\",\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none\",\n defaultClassNames.weekday\n ),\n week: cn(\"flex w-full mt-2\", defaultClassNames.week),\n week_number_header: cn(\n \"select-none w-(--cell-size)\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"text-[0.8rem] select-none text-muted-foreground\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-md\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-md\",\n defaultClassNames.day\n ),\n range_start: cn(\n \"rounded-l-md bg-accent\",\n defaultClassNames.range_start\n ),\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\n range_end: cn(\"rounded-r-md bg-accent\", defaultClassNames.range_end),\n today: cn(\n \"bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none\",\n defaultClassNames.today\n ),\n outside: cn(\n \"text-muted-foreground aria-selected:text-muted-foreground\",\n defaultClassNames.outside\n ),\n disabled: cn(\n \"text-muted-foreground opacity-50\",\n defaultClassNames.disabled\n ),\n hidden: cn(\"invisible\", defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n )\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === \"left\") {\n return (\n <ChevronLeftIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <ChevronRightIcon\n className={cn(\"size-4\", className)}\n {...props}\n />\n )\n }\n\n return (\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\n )\n },\n DayButton: CalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\n {children}\n </div>\n </td>\n )\n },\n ...components,\n }}\n {...props}\n />\n )\n}\n\nfunction CalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames()\n\n const ref = React.useRef<HTMLButtonElement>(null)\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus()\n }, [modifiers.focused])\n\n return (\n <Button\n ref={ref}\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n \"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Calendar, CalendarDayButton }\n","import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"@/utils/cn\"\nimport { usePortalContainer } from \"@/providers/PortalContainerProvider\"\n\nfunction Popover({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Root>) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />\n}\n\nfunction PopoverTrigger({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />\n}\n\nfunction PopoverContent({\n className,\n align = \"center\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Content>) {\n const container = usePortalContainer()\n\n return (\n <PopoverPrimitive.Portal container={container}>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n \"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden\",\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n )\n}\n\nfunction PopoverAnchor({\n ...props\n}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {\n return <PopoverPrimitive.Anchor data-slot=\"popover-anchor\" {...props} />\n}\n\nfunction PopoverHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"popover-header\"\n className={cn(\"flex flex-col gap-1 text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverTitle({ className, ...props }: React.ComponentProps<\"h2\">) {\n return (\n <div\n data-slot=\"popover-title\"\n className={cn(\"font-medium\", className)}\n {...props}\n />\n )\n}\n\nfunction PopoverDescription({\n className,\n ...props\n}: React.ComponentProps<\"p\">) {\n return (\n <p\n data-slot=\"popover-description\"\n className={cn(\"text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n PopoverAnchor,\n PopoverHeader,\n PopoverTitle,\n PopoverDescription,\n}\n","'use client'\n\nimport { useCallback } from 'react'\nimport { format, parseISO } from 'date-fns'\nimport { CalendarIcon } from 'lucide-react'\nimport type { WidgetProps } from '@rjsf/utils'\n\nimport { cn } from '@/utils/cn'\nimport { Button } from '@/components/ui/button'\nimport { Calendar } from '@/components/ui/calendar'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'\n\n/**\n * Custom DateWidget using shadcn Calendar + Popover\n * Renders for schema fields with format: \"date\"\n * Value format: YYYY-MM-DD (ISO date string)\n */\nexport function DateWidget({\n\tid,\n\tvalue,\n\tonChange,\n\tdisabled,\n\treadonly,\n\tplaceholder,\n\trawErrors = [],\n}: WidgetProps) {\n\t// Parse the ISO date string to a Date object\n\tconst dateValue = value ? parseISO(value) : undefined\n\n\tconst handleSelect = useCallback(\n\t\t(date: Date | undefined) => {\n\t\t\t// Format as YYYY-MM-DD for JSON Schema date format\n\t\t\tonChange(date ? format(date, 'yyyy-MM-dd') : undefined)\n\t\t},\n\t\t[onChange]\n\t)\n\n\tconst hasError = rawErrors.length > 0\n\n\treturn (\n\t\t<Popover>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\tid={id}\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tdisabled={disabled || readonly}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'w-full justify-start text-left font-normal h-9',\n\t\t\t\t\t\t!value && 'text-muted-foreground',\n\t\t\t\t\t\thasError && 'border-destructive focus-visible:ring-destructive/50'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<CalendarIcon className=\"mr-2 h-4 w-4\" />\n\t\t\t\t\t{dateValue ? format(dateValue, 'PPP') : <span>{placeholder || 'Pick a date'}</span>}\n\t\t\t\t</Button>\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-auto p-0\" align=\"start\">\n\t\t\t\t<Calendar\n\t\t\t\t\tmode=\"single\"\n\t\t\t\t\tselected={dateValue}\n\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\tdisabled={disabled || readonly}\n\t\t\t\t\tinitialFocus\n\t\t\t\t/>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t)\n}\n\nexport default DateWidget\n","'use client'\n\nimport { useCallback, useMemo } from 'react'\nimport { ClockIcon } from 'lucide-react'\nimport type { WidgetProps } from '@rjsf/utils'\n\nimport { cn } from '@/utils/cn'\nimport { Button } from '@/components/ui/button'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from '@/components/ui/select'\n\n/**\n * Custom TimeWidget using shadcn Select components\n * Renders for schema fields with format: \"time\"\n * Value format: HH:MM (24-hour format)\n */\nexport function TimeWidget({\n\tid,\n\tvalue,\n\tonChange,\n\tdisabled,\n\treadonly,\n\tplaceholder,\n\trawErrors = [],\n}: WidgetProps) {\n\t// Parse HH:MM string\n\tconst [hours, minutes] = useMemo(() => {\n\t\tif (!value || typeof value !== 'string') return ['', '']\n\t\tconst parts = value.split(':')\n\t\treturn [parts[0] || '', parts[1] || '']\n\t}, [value])\n\n\tconst handleHourChange = useCallback(\n\t\t(newHour: string) => {\n\t\t\tconst mins = minutes || '00'\n\t\t\tonChange(`${newHour}:${mins}:00`)\n\t\t},\n\t\t[minutes, onChange]\n\t)\n\n\tconst handleMinuteChange = useCallback(\n\t\t(newMinute: string) => {\n\t\t\tconst hrs = hours || '00'\n\t\t\tonChange(`${hrs}:${newMinute}:00`)\n\t\t},\n\t\t[hours, onChange]\n\t)\n\n\tconst hasError = rawErrors.length > 0\n\n\t// Generate hour options (00-23)\n\tconst hourOptions = useMemo(\n\t\t() => Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0')),\n\t\t[]\n\t)\n\n\t// Generate minute options (00-59, step by 5)\n\tconst minuteOptions = useMemo(\n\t\t() => Array.from({ length: 12 }, (_, i) => (i * 5).toString().padStart(2, '0')),\n\t\t[]\n\t)\n\n\tconst formatDisplayTime = () => {\n\t\tif (!hours && !minutes) return null\n\t\tconst h = parseInt(hours || '0', 10)\n\t\tconst m = minutes || '00'\n\t\tconst ampm = h >= 12 ? 'PM' : 'AM'\n\t\tconst displayHour = h === 0 ? 12 : h > 12 ? h - 12 : h\n\t\treturn `${displayHour}:${m} ${ampm}`\n\t}\n\n\treturn (\n\t\t<Popover>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\tid={id}\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tdisabled={disabled || readonly}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'w-full justify-start text-left font-normal h-9',\n\t\t\t\t\t\t!value && 'text-muted-foreground',\n\t\t\t\t\t\thasError && 'border-destructive focus-visible:ring-destructive/50'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<ClockIcon className=\"mr-2 h-4 w-4\" />\n\t\t\t\t\t{formatDisplayTime() || <span>{placeholder || 'Pick a time'}</span>}\n\t\t\t\t</Button>\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-auto p-3\" align=\"start\">\n\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">Hour</span>\n\t\t\t\t\t\t<Select value={hours} onValueChange={handleHourChange} disabled={disabled || readonly}>\n\t\t\t\t\t\t\t<SelectTrigger className=\"w-[70px]\">\n\t\t\t\t\t\t\t\t<SelectValue placeholder=\"HH\" />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t{hourOptions.map((hour) => (\n\t\t\t\t\t\t\t\t\t<SelectItem key={hour} value={hour}>\n\t\t\t\t\t\t\t\t\t\t{hour}\n\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t\t<span className=\"text-lg font-medium mt-5\">:</span>\n\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">Minute</span>\n\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\tvalue={minutes}\n\t\t\t\t\t\t\tonValueChange={handleMinuteChange}\n\t\t\t\t\t\t\tdisabled={disabled || readonly}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<SelectTrigger className=\"w-[70px]\">\n\t\t\t\t\t\t\t\t<SelectValue placeholder=\"MM\" />\n\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t{minuteOptions.map((minute) => (\n\t\t\t\t\t\t\t\t\t<SelectItem key={minute} value={minute}>\n\t\t\t\t\t\t\t\t\t\t{minute}\n\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t</Select>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t)\n}\n\nexport default TimeWidget\n","'use client'\n\nimport { useCallback, useMemo } from 'react'\nimport { format, parseISO } from 'date-fns'\nimport { CalendarIcon, ClockIcon } from 'lucide-react'\nimport type { WidgetProps } from '@rjsf/utils'\n\nimport { cn } from '@/utils/cn'\nimport { Button } from '@/components/ui/button'\nimport { Calendar } from '@/components/ui/calendar'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'\nimport {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from '@/components/ui/select'\n\n/**\n * Custom DateTimeWidget using shadcn Calendar + Time Select\n * Renders for schema fields with format: \"date-time\"\n * Value format: ISO 8601 datetime string (YYYY-MM-DDTHH:MM:SS)\n */\nexport function DateTimeWidget({\n\tid,\n\tvalue,\n\tonChange,\n\tdisabled,\n\treadonly,\n\tplaceholder,\n\trawErrors = [],\n}: WidgetProps) {\n\t// Parse the ISO datetime string\n\tconst { dateValue, hours, minutes } = useMemo(() => {\n\t\tif (!value || typeof value !== 'string') {\n\t\t\treturn { dateValue: undefined, hours: '', minutes: '' }\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = parseISO(value)\n\t\t\treturn {\n\t\t\t\tdateValue: parsed,\n\t\t\t\thours: parsed.getHours().toString().padStart(2, '0'),\n\t\t\t\tminutes: parsed.getMinutes().toString().padStart(2, '0'),\n\t\t\t}\n\t\t} catch {\n\t\t\treturn { dateValue: undefined, hours: '', minutes: '' }\n\t\t}\n\t}, [value])\n\n\tconst updateDateTime = useCallback(\n\t\t(date: Date | undefined, h: string, m: string) => {\n\t\t\tif (!date) {\n\t\t\t\tonChange(undefined)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst hrs = parseInt(h || '0', 10)\n\t\t\tconst mins = parseInt(m || '0', 10)\n\t\t\tconst newDate = new Date(date)\n\t\t\tnewDate.setHours(hrs, mins, 0, 0)\n\t\t\t// Format as ISO 8601 local datetime\n\t\t\tonChange(format(newDate, \"yyyy-MM-dd'T'HH:mm:ss\"))\n\t\t},\n\t\t[onChange]\n\t)\n\n\tconst handleDateSelect = useCallback(\n\t\t(date: Date | undefined) => {\n\t\t\tupdateDateTime(date, hours || '12', minutes || '00')\n\t\t},\n\t\t[hours, minutes, updateDateTime]\n\t)\n\n\tconst handleHourChange = useCallback(\n\t\t(newHour: string) => {\n\t\t\tif (dateValue) {\n\t\t\t\tupdateDateTime(dateValue, newHour, minutes || '00')\n\t\t\t}\n\t\t},\n\t\t[dateValue, minutes, updateDateTime]\n\t)\n\n\tconst handleMinuteChange = useCallback(\n\t\t(newMinute: string) => {\n\t\t\tif (dateValue) {\n\t\t\t\tupdateDateTime(dateValue, hours || '12', newMinute)\n\t\t\t}\n\t\t},\n\t\t[dateValue, hours, updateDateTime]\n\t)\n\n\tconst hasError = rawErrors.length > 0\n\n\t// Generate hour options (00-23)\n\tconst hourOptions = useMemo(\n\t\t() => Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0')),\n\t\t[]\n\t)\n\n\t// Generate minute options (00-59, step by 5)\n\tconst minuteOptions = useMemo(\n\t\t() => Array.from({ length: 12 }, (_, i) => (i * 5).toString().padStart(2, '0')),\n\t\t[]\n\t)\n\n\tconst formatDisplayDateTime = () => {\n\t\tif (!dateValue) return null\n\t\tconst h = parseInt(hours || '0', 10)\n\t\tconst m = minutes || '00'\n\t\tconst ampm = h >= 12 ? 'PM' : 'AM'\n\t\tconst displayHour = h === 0 ? 12 : h > 12 ? h - 12 : h\n\t\treturn `${format(dateValue, 'PPP')} at ${displayHour}:${m} ${ampm}`\n\t}\n\n\treturn (\n\t\t<Popover>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<Button\n\t\t\t\t\tid={id}\n\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\tdisabled={disabled || readonly}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'w-full justify-start text-left font-normal h-9',\n\t\t\t\t\t\t!value && 'text-muted-foreground',\n\t\t\t\t\t\thasError && 'border-destructive focus-visible:ring-destructive/50'\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<CalendarIcon className=\"mr-2 h-4 w-4\" />\n\t\t\t\t\t{formatDisplayDateTime() || <span>{placeholder || 'Pick date and time'}</span>}\n\t\t\t\t</Button>\n\t\t\t</PopoverTrigger>\n\t\t\t<PopoverContent className=\"w-auto p-0\" align=\"start\">\n\t\t\t\t<Calendar\n\t\t\t\t\tmode=\"single\"\n\t\t\t\t\tselected={dateValue}\n\t\t\t\t\tonSelect={handleDateSelect}\n\t\t\t\t\tdisabled={disabled || readonly}\n\t\t\t\t\tinitialFocus\n\t\t\t\t/>\n\t\t\t\t<div className=\"border-t p-3\">\n\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t<ClockIcon className=\"h-4 w-4 text-muted-foreground\" />\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tvalue={hours}\n\t\t\t\t\t\t\t\tonValueChange={handleHourChange}\n\t\t\t\t\t\t\t\tdisabled={disabled || readonly || !dateValue}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-[70px]\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"HH\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t{hourOptions.map((hour) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={hour} value={hour}>\n\t\t\t\t\t\t\t\t\t\t\t{hour}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t\t<span className=\"text-lg font-medium\">:</span>\n\t\t\t\t\t\t\t<Select\n\t\t\t\t\t\t\t\tvalue={minutes}\n\t\t\t\t\t\t\t\tonValueChange={handleMinuteChange}\n\t\t\t\t\t\t\t\tdisabled={disabled || readonly || !dateValue}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<SelectTrigger className=\"w-[70px]\">\n\t\t\t\t\t\t\t\t\t<SelectValue placeholder=\"MM\" />\n\t\t\t\t\t\t\t\t</SelectTrigger>\n\t\t\t\t\t\t\t\t<SelectContent>\n\t\t\t\t\t\t\t\t\t{minuteOptions.map((minute) => (\n\t\t\t\t\t\t\t\t\t\t<SelectItem key={minute} value={minute}>\n\t\t\t\t\t\t\t\t\t\t\t{minute}\n\t\t\t\t\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SelectContent>\n\t\t\t\t\t\t\t</Select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</PopoverContent>\n\t\t</Popover>\n\t)\n}\n\nexport default DateTimeWidget\n","'use client'\n\nimport Ajv from 'ajv'\nimport { makeAssistantToolUI } from '@assistant-ui/react'\nimport { withTheme } from '@rjsf/core'\nimport { Theme as ShadcnTheme } from '@rjsf/shadcn'\nimport validator from '@rjsf/validator-ajv8'\nimport { AlertCircle, AlertTriangle, Check, ChevronDownIcon, ChevronUpIcon, FileText, X } from 'lucide-react'\nimport { useEffect, useRef, useState } from 'react'\n\nimport type { JSONSchema7 } from 'json-schema'\n\nimport { Button } from '../components/ui/button'\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../components/ui/collapsible'\nimport { useToolExecution } from '../providers/ToolExecutionProvider'\nimport { FORM_CANCELLED_MESSAGE } from '../utils/format'\n\n// Custom widgets for date/time inputs (using our shadcn components)\nimport { DateWidget, TimeWidget, DateTimeWidget } from './widgets'\n\n// Create themed form component\nconst Form = withTheme(ShadcnTheme)\n\n// AJV instance for schema validation\nconst ajv = new Ajv()\n\n/**\n * Normalize a JSON Schema to handle common model mistakes.\n * - Converts uppercase types (Gemini format) to lowercase (JSON Schema format)\n * - Recursively processes nested schemas\n */\nfunction normalizeSchema(schema: unknown): JSONSchema7 {\n\tif (!schema || typeof schema !== 'object') {\n\t\treturn schema as JSONSchema7\n\t}\n\n\tconst obj = { ...(schema as Record<string, unknown>) }\n\n\t// Lowercase the type if it's a string (handles OBJECT -> object, STRING -> string, etc.)\n\tif (typeof obj.type === 'string') {\n\t\tobj.type = obj.type.toLowerCase()\n\t}\n\n\t// Recursively normalize properties\n\tif (obj.properties && typeof obj.properties === 'object') {\n\t\tobj.properties = Object.fromEntries(\n\t\t\tObject.entries(obj.properties as Record<string, unknown>).map(([key, value]) => [\n\t\t\t\tkey,\n\t\t\t\tnormalizeSchema(value),\n\t\t\t])\n\t\t)\n\t}\n\n\t// Handle items for arrays\n\tif (obj.items) {\n\t\tif (Array.isArray(obj.items)) {\n\t\t\tobj.items = obj.items.map(normalizeSchema)\n\t\t} else {\n\t\t\tobj.items = normalizeSchema(obj.items)\n\t\t}\n\t}\n\n\t// Handle additionalProperties\n\tif (obj.additionalProperties && typeof obj.additionalProperties === 'object') {\n\t\tobj.additionalProperties = normalizeSchema(obj.additionalProperties)\n\t}\n\n\t// Handle allOf, anyOf, oneOf\n\tfor (const keyword of ['allOf', 'anyOf', 'oneOf'] as const) {\n\t\tif (Array.isArray(obj[keyword])) {\n\t\t\tobj[keyword] = (obj[keyword] as unknown[]).map(normalizeSchema)\n\t\t}\n\t}\n\n\t// Handle not\n\tif (obj.not && typeof obj.not === 'object') {\n\t\tobj.not = normalizeSchema(obj.not)\n\t}\n\n\treturn obj as JSONSchema7\n}\n\n/**\n * Validate a JSON Schema using AJV's meta-schema validation.\n * Returns null if valid, or an error message string if invalid.\n */\nfunction validateSchema(schema: JSONSchema7): string | null {\n\tconst isValid = ajv.validateSchema(schema)\n\tif (isValid) return null\n\n\t// Format AJV errors into a readable message\n\tconst errors = ajv.errors ?? []\n\tconst errorMessages = errors.map((err) => {\n\t\tconst path = err.instancePath || 'root'\n\t\treturn `- ${path}: ${err.message}`\n\t})\n\n\treturn [\n\t\t'Invalid JSON Schema:',\n\t\t...errorMessages,\n\t\t'',\n\t\t'Please fix the schema and try again.',\n\t].join('\\n')\n}\n\n/**\n * Display component for schema validation errors\n */\nfunction SchemaErrorDisplay({ title, error }: { title: string; error: string }) {\n\tconst [isOpen, setIsOpen] = useState(true)\n\n\treturn (\n\t\t<Collapsible open={isOpen} onOpenChange={setIsOpen}>\n\t\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-destructive/10 border border-destructive/20\">\n\t\t\t\t<CollapsibleTrigger asChild>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"flex w-full items-center gap-1.5 px-2 py-1.5 text-left transition-colors hover:bg-destructive/15\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t\t<FileText className=\"h-3.5 w-3.5 text-destructive\" />\n\t\t\t\t\t\t\t<AlertCircle className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-destructive\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<span className=\"flex-grow text-xs font-medium text-destructive\">\n\t\t\t\t\t\t\t{title} - Invalid Schema\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"inline-flex h-5 w-5 items-center justify-center p-0\">\n\t\t\t\t\t\t\t{isOpen ? (\n\t\t\t\t\t\t\t\t<ChevronUpIcon className=\"h-3 w-3 text-destructive/70\" />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<ChevronDownIcon className=\"h-3 w-3 text-destructive/70\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t</CollapsibleTrigger>\n\n\t\t\t\t<CollapsibleContent>\n\t\t\t\t\t<div className=\"border-t border-destructive/20 px-2 py-1.5\">\n\t\t\t\t\t\t<pre className=\"whitespace-pre-wrap text-[11px] text-foreground/70\">{error}</pre>\n\t\t\t\t\t</div>\n\t\t\t\t</CollapsibleContent>\n\t\t\t</div>\n\t\t</Collapsible>\n\t)\n}\n\n/**\n * Args passed from the model when calling the form tool\n */\ntype FormArgs = {\n\ttitle: string\n\tdescription?: string\n\tschema: JSONSchema7\n\tsubmitLabel?: string\n}\n\n/**\n * Result is the form data submitted by the user\n */\ntype FormResult = Record<string, unknown>\n\n/**\n * Parse form result data, handling cases where it may be stringified\n */\nfunction parseFormData(data: FormResult | string): Record<string, unknown> {\n\t// If it's already an object with non-numeric keys, return as-is\n\tif (typeof data === 'object' && data !== null) {\n\t\tconst keys = Object.keys(data)\n\t\t// Check if keys are numeric (which means it's iterating over a string)\n\t\tconst hasNonNumericKeys = keys.some((key) => isNaN(Number(key)))\n\t\tif (hasNonNumericKeys) {\n\t\t\treturn data\n\t\t}\n\t}\n\n\t// If it's a string, try to parse it\n\tif (typeof data === 'string') {\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(data)\n\t\t\tif (typeof parsed === 'object' && parsed !== null) {\n\t\t\t\treturn parsed\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// If parsing fails, log and return as a single \"value\" entry\n\t\t\tconsole.warn('[FormToolUI] Failed to parse form data as JSON:', {\n\t\t\t\tdata: data.substring(0, 100),\n\t\t\t\terror: error instanceof Error ? error.message : 'Unknown parse error',\n\t\t\t})\n\t\t\treturn { value: data }\n\t\t}\n\t}\n\n\t// Fallback: return as-is or wrap in an object\n\treturn typeof data === 'object' && data !== null ? data : { value: String(data) }\n}\n\n/**\n * Format a value for display\n */\nfunction formatValue(value: unknown): string {\n\tif (value === null || value === undefined) return '—'\n\tif (typeof value === 'boolean') return value ? 'Yes' : 'No'\n\tif (typeof value === 'object') return JSON.stringify(value)\n\treturn String(value)\n}\n\n/**\n * Display component for submitted form data - matches UnifiedToolFallback pattern\n */\nfunction FormResultDisplay({ title, data }: { title: string; data: FormResult }) {\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst parsedData = parseFormData(data)\n\tconst entries = Object.entries(parsedData)\n\n\treturn (\n\t\t<Collapsible open={isOpen} onOpenChange={setIsOpen}>\n\t\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-muted/50\">\n\t\t\t\t<CollapsibleTrigger asChild>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"flex w-full items-center gap-1.5 px-2 py-1.5 text-left transition-colors hover:bg-muted/70\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t\t<FileText className=\"h-3.5 w-3.5 text-muted-foreground\" />\n\t\t\t\t\t\t\t<Check className=\"absolute -bottom-0.5 -right-0.5 h-2 w-2 text-muted-foreground\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<span className=\"flex-grow text-xs font-medium text-foreground/80\">\n\t\t\t\t\t\t\t{title}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span className=\"inline-flex h-5 w-5 items-center justify-center p-0\">\n\t\t\t\t\t\t\t{isOpen ? (\n\t\t\t\t\t\t\t\t<ChevronUpIcon className=\"h-3 w-3 text-muted-foreground/70\" />\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<ChevronDownIcon className=\"h-3 w-3 text-muted-foreground/70\" />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</button>\n\t\t\t\t</CollapsibleTrigger>\n\n\t\t\t\t<CollapsibleContent>\n\t\t\t\t\t<div className=\"border-t border-border px-2 py-1.5\">\n\t\t\t\t\t\t<div className=\"mb-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70\">\n\t\t\t\t\t\t\tSubmitted data\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"rounded bg-muted/50 p-1.5 space-y-0.5\">\n\t\t\t\t\t\t\t{entries.map(([key, value]) => (\n\t\t\t\t\t\t\t\t<div key={key} className=\"flex gap-2 text-[11px]\">\n\t\t\t\t\t\t\t\t\t<span className=\"font-medium text-muted-foreground\">{key}:</span>\n\t\t\t\t\t\t\t\t\t<span className=\"text-foreground/70\">{formatValue(value)}</span>\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</div>\n\t\t\t\t\t</div>\n\t\t\t\t</CollapsibleContent>\n\t\t\t</div>\n\t\t</Collapsible>\n\t)\n}\n\n/**\n * FormToolUI - Renders a dynamic form from JSON Schema\n *\n * HITL Pattern (AI SDK v6):\n * - Model calls `form` tool with JSON Schema\n * - This UI renders the form using @rjsf/shadcn\n * - User fills out and submits form\n * - addToolOutput() sends data to backend via WebSocket + updates local UI state\n *\n * Schema Handling:\n * - Normalizes uppercase types (Gemini format) to lowercase (JSON Schema)\n * - Validates schema with AJV and sends errors back to model if invalid\n */\nexport const FormToolUI = makeAssistantToolUI<FormArgs, FormResult>({\n\ttoolName: 'form',\n\trender: ({ args, result, status, addResult, toolCallId }) => {\n\t\t// Get addToolOutput from context (v6 pattern - sends via WebSocket + updates local state)\n\t\tconst toolExecution = useToolExecution()\n\t\t// Track if we've already sent an error to prevent duplicate sends\n\t\tconst errorSentRef = useRef(false)\n\t\t// Track validation error for display\n\t\tconst [schemaError, setSchemaError] = useState<string | null>(null)\n\t\t// Track latest form data without causing re-renders\n\t\tconst formDataRef = useRef<Record<string, unknown>>({})\n\t\t// True after RJSF validation failure (shows Force Submit button)\n\t\tconst [hasValidationError, setHasValidationError] = useState(false)\n\n\t\tconst isWaiting = status.type === 'requires-action'\n\n\t\t// Normalize and validate schema when ready\n\t\tconst normalizedSchema = args.schema && typeof args.schema === 'object'\n\t\t\t? normalizeSchema(args.schema)\n\t\t\t: null\n\n\t\t// Validate schema and send error to model if invalid\n\t\tuseEffect(() => {\n\t\t\tif (!normalizedSchema || !isWaiting || errorSentRef.current || result) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst validationError = validateSchema(normalizedSchema)\n\t\t\tif (validationError) {\n\t\t\t\terrorSentRef.current = true\n\t\t\t\tsetSchemaError(validationError)\n\n\t\t\t\t// Send via WebSocket to backend + updates local state\n\t\t\t\t// Note: Do NOT call addResult() here - it triggers onAddToolResult which would\n\t\t\t\t// send a duplicate message to the server. chat.addToolOutput already handles\n\t\t\t\t// both server sync and local state update.\n\t\t\t\ttoolExecution.addToolOutput({\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\toutput: `Error: ${validationError}`,\n\t\t\t\t})\n\t\t\t}\n\t\t}, [normalizedSchema, isWaiting, result, toolExecution, toolCallId])\n\n\t\t// Show error UI if schema validation failed\n\t\tif (schemaError) {\n\t\t\treturn <SchemaErrorDisplay title={args.title ?? 'Form'} error={schemaError} />\n\t\t}\n\n\t\t// If form was already submitted, show the result\n\t\tif (result) {\n\t\t\treturn <FormResultDisplay title={args.title ?? 'Form'} data={result} />\n\t\t}\n\n\t\t// Handle form submission\n\t\tconst handleSubmit = ({ formData }: { formData?: FormResult }) => {\n\t\t\tif (!formData) return\n\n\t\t\t// Stringify object results for the wire format\n\t\t\tconst outputValue =\n\t\t\t\ttypeof formData === 'object'\n\t\t\t\t\t? JSON.stringify(formData)\n\t\t\t\t\t: String(formData)\n\n\t\t\t// v6 pattern: addToolOutput sends to backend + updates local state\n\t\t\t// Note: Do NOT call addResult() here - it triggers onAddToolResult which would\n\t\t\t// send a duplicate message to the server. chat.addToolOutput already handles\n\t\t\t// both server sync and local state update.\n\t\t\ttoolExecution.addToolOutput({\n\t\t\t\ttoolCallId,\n\t\t\t\toutput: outputValue,\n\t\t\t})\n\t\t}\n\n\t\t// Force submit: sends current form data as-is, bypassing validation\n\t\tconst handleForceSubmit = () => {\n\t\t\tconst outputValue = JSON.stringify(formDataRef.current)\n\t\t\ttoolExecution.addToolOutput({\n\t\t\t\ttoolCallId,\n\t\t\t\toutput: outputValue,\n\t\t\t})\n\t\t}\n\n\t\t// Cancel: sends cancellation message to model\n\t\tconst handleCancel = () => {\n\t\t\ttoolExecution.addToolOutput({\n\t\t\t\ttoolCallId,\n\t\t\t\toutput: FORM_CANCELLED_MESSAGE,\n\t\t\t})\n\t\t}\n\n\t\t// Guard against undefined schema (can happen during streaming when args are being parsed)\n\t\tif (!normalizedSchema) {\n\t\t\treturn (\n\t\t\t\t<div className=\"my-1 flex items-center gap-1.5 rounded-lg bg-muted/50 px-2 py-1.5 text-sm text-foreground/70\">\n\t\t\t\t\t<FileText className=\"h-3.5 w-3.5 animate-pulse text-muted-foreground\" />\n\t\t\t\t\t<span className=\"text-xs\">Loading form...</span>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\n\t\treturn (\n\t\t\t<div className=\"my-1 overflow-hidden rounded-lg bg-muted/50\">\n\t\t\t\t{/* Header */}\n\t\t\t\t<div className=\"flex items-center gap-1.5 px-2 py-1.5 border-b border-border\">\n\t\t\t\t\t<FileText className=\"h-3.5 w-3.5 text-foreground/70\" />\n\t\t\t\t\t<span className=\"text-xs font-medium text-foreground\">{args.title ?? 'Form'}</span>\n\t\t\t\t</div>\n\n\t\t\t\t{/* Content */}\n\t\t\t\t<div className=\"px-2 py-2\">\n\t\t\t\t\t{/* Description */}\n\t\t\t\t\t{args.description && (\n\t\t\t\t\t\t<p className=\"text-xs text-muted-foreground mb-3\">{args.description}</p>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* RJSF Form - uses @rjsf/shadcn theme with custom date/time widgets */}\n\t\t\t\t\t<Form\n\t\t\t\t\t\tschema={normalizedSchema}\n\t\t\t\t\t\tvalidator={validator}\n\t\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\t\tonChange={({ formData }) => {\n\t\t\t\t\t\t\tformDataRef.current = formData ?? {}\n\t\t\t\t\t\t\tsetHasValidationError(false)\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonError={() => setHasValidationError(true)}\n\t\t\t\t\t\tdisabled={!isWaiting}\n\t\t\t\t\t\tclassName=\"space-y-3\"\n\t\t\t\t\t\t// Only override date/time widgets (the rest use @rjsf/shadcn defaults)\n\t\t\t\t\t\twidgets={{\n\t\t\t\t\t\t\tDateWidget,\n\t\t\t\t\t\t\tTimeWidget,\n\t\t\t\t\t\t\tDateTimeWidget,\n\t\t\t\t\t\t}}\n\t\t\t\t\t\t// Hide default submit button, we'll add our own\n\t\t\t\t\t\tuiSchema={{\n\t\t\t\t\t\t\t'ui:submitButtonOptions': {\n\t\t\t\t\t\t\t\tnorender: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{/* Action buttons */}\n\t\t\t\t\t\t<div className=\"flex justify-end gap-2 pt-1\">\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\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tdisabled={!isWaiting}\n\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\tclassName=\"h-7 px-3 text-xs\"\n\t\t\t\t\t\t\t\tonClick={handleCancel}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<X className=\"h-3 w-3 mr-1\" />\n\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t{hasValidationError && (\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\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tdisabled={!isWaiting}\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tclassName=\"h-7 px-3 text-xs border-destructive/50 text-destructive hover:bg-destructive/10\"\n\t\t\t\t\t\t\t\t\tonClick={handleForceSubmit}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<AlertTriangle className=\"h-3 w-3 mr-1\" />\n\t\t\t\t\t\t\t\t\tForce Submit\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<Button type=\"submit\" disabled={!isWaiting} size=\"sm\" className=\"h-7 px-3 text-xs\">\n\t\t\t\t\t\t\t\t<Check className=\"h-3 w-3 mr-1\" />\n\t\t\t\t\t\t\t\t{args.submitLabel || 'Submit'}\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</Form>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t},\n})\n\nexport default FormToolUI\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/**\n\t * Controlled open state. When provided, the component is controlled.\n\t * Use with `onOpenChange` to handle state changes.\n\t */\n\topen?: boolean\n\n\t/** Initial open state for uncontrolled usage (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 *\n * Supports both controlled (with `open` prop) and uncontrolled (with `defaultOpen`) usage.\n */\nexport const AgentUIProvider: FC<AgentUIProviderProps> = ({\n\tchildren,\n\topen: controlledOpen,\n\tdefaultOpen = false,\n\tdefaultMode = 'collapsed',\n\tonOpenChange,\n\tonModeChange,\n}) => {\n\t// Determine if we're in controlled mode\n\tconst isControlled = controlledOpen !== undefined\n\n\t// Core UI state - use controlled value if provided, otherwise internal state\n\tconst [internalOpen, setInternalOpen] = useState(defaultOpen)\n\tconst isOpen = isControlled ? controlledOpen : internalOpen\n\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\t// Always update internal state (for uncontrolled mode)\n\t\tsetInternalOpen(open)\n\t\t// Always call callback (for controlled mode to sync)\n\t\tonOpenChangeRef.current?.(open)\n\t}, [])\n\n\tconst toggleOpen = useCallback(() => {\n\t\tconst next = !isOpen\n\t\tsetInternalOpen(next)\n\t\tonOpenChangeRef.current?.(next)\n\t}, [isOpen])\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","/**\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 utils/thread-utils.ts\n */\nimport { useThread, useThreadRuntime } from '@assistant-ui/react'\nimport { useMemo } from 'react'\n\nimport type { ThreadAssistantMessage } from '@assistant-ui/react'\nimport type { PendingToolCallInfo } from '../utils/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 utils/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 get the thread runtime for calling addToolResult.\n * Re-exported for convenience.\n */\nexport { useThreadRuntime }\n","/**\n * Debug Tools V2 for Embedded Agent\n *\n * Provides 4 powerful debug tools for browser automation and testing:\n * - debug_state: Complete application state snapshot (READ)\n * - debug_ui: UI and composer control (ACTION)\n * - debug_tools: Tool approval and source management (ACTION)\n * - debug_session: Thread and voice control (ACTION)\n *\n * All tools are prefixed with `debug_` and should be excluded from production.\n *\n * @example Usage in Storybook or development\n * ```tsx\n * <DebugToolsProvider enabled={isDevelopment}>\n * {children}\n * </DebugToolsProvider>\n * ```\n */\n\nimport { useAssistantApi, useAssistantState, useThread, useThreadRuntime } from '@assistant-ui/react'\nimport { useWebMCP } from '@mcp-b/react-webmcp'\nimport { useCallback, useRef } from 'react'\nimport { z } from 'zod'\n\nimport { useOptionalAgentUI } from '../providers/AgentUIProvider'\nimport { useOptionalMCPTools } from '../providers/MCPToolsProvider'\nimport { useOptionalToolApproval } from '../providers/ToolApprovalContext'\nimport { useOptionalToolSelection } from '../providers/ToolSelectionProvider'\nimport { useOptionalVoiceThread } from '../providers/VoiceThreadBridge'\nimport { usePendingToolCalls } from './usePendingToolCalls'\nimport { resolvePendingToolCall } from '../utils/thread-utils'\n\nimport type { ToolApprovalMode, ToolSourceSelector } from '@mcp-b/shared-types'\nimport type { PillMode } from '../providers/AgentUIProvider'\n\n/**\n * Prefix for debug tools - these should be excluded from production\n */\nexport const DEBUG_TOOL_PREFIX = 'debug_'\n\n// =============================================================================\n// STABLE SCHEMA DEFINITIONS\n// These must be defined outside the hook to prevent re-registration loops.\n// useWebMCP compares inputSchema by reference, so inline objects cause issues.\n// =============================================================================\n\n/** Schema for debug_state tool - no inputs needed */\nconst DEBUG_STATE_SCHEMA = {} as const\n\n/** Schema for debug_ui tool */\nconst DEBUG_UI_SCHEMA = {\n\taction: z.enum(['setMode', 'expand', 'collapse', 'toggleFullScreen', 'resetPosition', 'markRead', 'sendMessage', 'setText', 'clearComposer'])\n\t\t.describe('The action to perform'),\n\tmode: z.enum(['collapsed', 'hovered', 'composing', 'active', 'expanded']).optional()\n\t\t.describe('Required for setMode action. The pill mode to set.'),\n\ttext: z.string().optional()\n\t\t.describe('Required for sendMessage and setText actions. The message or text to use.'),\n} as const\n\n/** Schema for debug_tools tool */\nconst DEBUG_TOOLS_SCHEMA = {\n\taction: z.enum(['approve', 'deny', 'setApprovalMode', 'selectSources', 'deselectSources', 'selectAllSources', 'deselectAllSources'])\n\t\t.describe('The action to perform'),\n\ttoolCallId: z.string().optional()\n\t\t.describe('For approve/deny: specific tool call ID. If omitted, uses the first pending approval.'),\n\treason: z.string().optional()\n\t\t.describe('For deny: feedback explaining why the tool was denied.'),\n\tmode: z.enum(['ask', 'auto']).optional()\n\t\t.describe('For setApprovalMode: \"ask\" requires approval for destructive tools, \"auto\" approves all.'),\n\tsourceIds: z.array(z.string()).optional()\n\t\t.describe('For selectSources/deselectSources: array of source IDs to select or deselect.'),\n} as const\n\n/** Schema for debug_session tool */\nconst DEBUG_SESSION_SCHEMA = {\n\taction: z.enum(['startNewThread', 'switchThread', 'listThreads', 'voiceStart', 'voiceStop', 'voiceToggleMute'])\n\t\t.describe('The action to perform'),\n\tthreadId: z.string().optional()\n\t\t.describe('For switchThread: the ID of the thread to switch to.'),\n} as const\n\n/** Description for debug_state tool */\nconst DEBUG_STATE_DESCRIPTION = `Get a complete snapshot of the embedded agent's current state. Returns everything in one call: UI state (pill mode, fullscreen, position), thread state (messages, running status, pending approvals), voice state (active, muted, transcript), tool state (approval mode, local/remote sources, connections), and WebSocket connection status. Call this first to understand the current application state before taking actions.`\n\n/** Description for debug_ui tool */\nconst DEBUG_UI_DESCRIPTION = `Control the embedded agent's UI and composer.\n\nActions:\n• setMode - Change pill mode. Requires 'mode' param: 'collapsed' | 'hovered' | 'composing' | 'active' | 'expanded'\n• expand - Expand the pill (equivalent to setMode with 'expanded')\n• collapse - Collapse the pill immediately\n• toggleFullScreen - Enter or exit full-screen mode\n• resetPosition - Reset pill to default position\n• markRead - Clear the unread indicator\n• sendMessage - Send a message to the agent. Requires 'text' param with the message content\n• setText - Set composer text without sending. Requires 'text' param\n• clearComposer - Clear the composer input\n\nExamples:\n { action: 'sendMessage', text: 'What tools do you have?' }\n { action: 'setMode', mode: 'expanded' }\n { action: 'collapse' }`\n\n/** Description for debug_tools tool */\nconst DEBUG_TOOLS_DESCRIPTION = `Manage tool approvals and tool source selection.\n\nActions:\n• approve - Approve a pending tool call. Optional 'toolCallId' param (defaults to first pending)\n• deny - Deny a pending tool call. Optional 'toolCallId' and 'reason' params\n• setApprovalMode - Change approval mode. Requires 'mode' param: 'ask' | 'auto'\n• selectSources - Select specific tool sources. Requires 'sourceIds' array\n• deselectSources - Deselect specific tool sources. Requires 'sourceIds' array\n• selectAllSources - Select all available tool sources\n• deselectAllSources - Deselect all tool sources (use only local tools)\n\nExamples:\n { action: 'approve' }\n { action: 'deny', reason: 'Try a different approach' }\n { action: 'setApprovalMode', mode: 'auto' }\n { action: 'selectSources', sourceIds: ['source-abc', 'source-xyz'] }`\n\n/** Description for debug_session tool */\nconst DEBUG_SESSION_DESCRIPTION = `Control thread and voice session.\n\nActions:\n• startNewThread - Clear the current conversation and start fresh\n• switchThread - Switch to a different thread. Requires 'threadId' param\n• listThreads - List all available threads and current thread ID\n• voiceStart - Start a voice session (requires microphone access)\n• voiceStop - End the current voice session\n• voiceToggleMute - Toggle microphone mute state\n\nExamples:\n { action: 'startNewThread' }\n { action: 'switchThread', threadId: 'thread-abc123' }\n { action: 'listThreads' }\n { action: 'voiceStart' }`\n\n/**\n * Options for the debug tools hook\n */\nexport interface UseWebMCPDebugToolsOptions {\n\t/**\n\t * Additional state to include in debug output.\n\t * Useful for exposing provider-level state not accessible via hooks.\n\t */\n\tadditionalState?: {\n\t\t/** CloudflareThread context values */\n\t\tcloudflareThread?: {\n\t\t\tisInitialized: boolean\n\t\t\tisReady: boolean\n\t\t\tcurrentThreadId: string | undefined\n\t\t\tendUserId: string | null\n\t\t\torganizationId: string | null\n\t\t}\n\t\t/** ThreadManager WebSocket state */\n\t\tmanagerState?: {\n\t\t\treadyState: number\n\t\t\treadyStateLabel: string\n\t\t}\n\t}\n}\n\n// Tool denied message constant\nconst TOOL_DENIED_MESSAGE = 'Tool execution was denied by the user.'\n\n/**\n * Hook that registers debug tools for the embedded agent.\n *\n * Tools provided:\n * - `debug_state`: Complete application state snapshot\n * - `debug_ui`: Control UI and composer\n * - `debug_tools`: Manage tool approvals and sources\n * - `debug_session`: Control thread and voice\n */\nexport function useWebMCPDebugTools(options?: UseWebMCPDebugToolsOptions) {\n\t// Get all contexts (using optional versions where available)\n\tconst agentUI = useOptionalAgentUI()\n\tconst mcpTools = useOptionalMCPTools()\n\tconst toolApproval = useOptionalToolApproval()\n\tconst toolSelection = useOptionalToolSelection()\n\tconst voiceThread = useOptionalVoiceThread()\n\tconst pendingToolCalls = usePendingToolCalls()\n\tconst threadRuntime = useThreadRuntime()\n\tconst additionalState = options?.additionalState\n\n\t// Get assistant-ui API for composer and threads\n\tconst assistantApi = useAssistantApi()\n\n\t// Thread state\n\tconst threadMessages = useThread((t) => t.messages)\n\tconst isRunning = useThread((t) => t.isRunning)\n\n\t// Thread list state\n\tconst threadsLoading = useAssistantState(({ threads }) => threads.isLoading)\n\tconst currentThreadId = useAssistantState(({ threads }) => threads.mainThreadId)\n\tconst threadIds = useAssistantState(({ threads }) => threads.threadIds)\n\n\t// Use refs to avoid recreating handlers when state changes\n\t// This prevents infinite re-registration loops in useWebMCP\n\tconst stateRef = useRef({\n\t\tagentUI,\n\t\tmcpTools,\n\t\ttoolApproval,\n\t\ttoolSelection,\n\t\tvoiceThread,\n\t\tpendingToolCalls,\n\t\tthreadRuntime,\n\t\tadditionalState,\n\t\tassistantApi,\n\t\tthreadMessages,\n\t\tisRunning,\n\t\tthreadsLoading,\n\t\tcurrentThreadId,\n\t\tthreadIds,\n\t})\n\t// Update ref on each render\n\tstateRef.current = {\n\t\tagentUI,\n\t\tmcpTools,\n\t\ttoolApproval,\n\t\ttoolSelection,\n\t\tvoiceThread,\n\t\tpendingToolCalls,\n\t\tthreadRuntime,\n\t\tadditionalState,\n\t\tassistantApi,\n\t\tthreadMessages,\n\t\tisRunning,\n\t\tthreadsLoading,\n\t\tcurrentThreadId,\n\t\tthreadIds,\n\t}\n\n\t// =========================================================================\n\t// Tool 1: debug_state - Complete application state snapshot\n\t// =========================================================================\n\tconst handleDebugState = useCallback(async () => {\n\t\tconst state = stateRef.current\n\t\tconst cloudflareThread = state.additionalState?.cloudflareThread\n\t\tconst managerState = state.additionalState?.managerState\n\n\t\t// Build UI state\n\t\tconst ui = state.agentUI\n\t\t\t? {\n\t\t\t\t\tmode: state.agentUI.userMode,\n\t\t\t\t\tisFullScreen: state.agentUI.isFullScreen,\n\t\t\t\t\thasUnread: state.agentUI.hasUnread,\n\t\t\t\t\tposition: state.agentUI.position,\n\t\t\t\t}\n\t\t\t: { error: 'AgentUI context not available' }\n\n\t\t// Build thread state with messages\n\t\tconst messages = (state.threadMessages ?? []).map((msg) => {\n\t\t\t// Get content preview\n\t\t\tlet contentPreview = ''\n\t\t\tfor (const part of msg.content) {\n\t\t\t\tif (part.type === 'text' && 'text' in part && typeof part.text === 'string') {\n\t\t\t\t\tcontentPreview = part.text.slice(0, 500)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Get tool calls\n\t\t\tconst toolCalls = msg.content\n\t\t\t\t.filter((part) => part.type === 'tool-call')\n\t\t\t\t.map((tc) => {\n\t\t\t\t\tconst toolCallPart = tc as { type: 'tool-call'; toolName: string; result?: unknown }\n\t\t\t\t\treturn {\n\t\t\t\t\t\tname: toolCallPart.toolName,\n\t\t\t\t\t\tstatus: toolCallPart.result !== undefined ? 'completed' : 'pending',\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\treturn {\n\t\t\t\tid: msg.id,\n\t\t\t\trole: msg.role,\n\t\t\t\tcontent: contentPreview,\n\t\t\t\ttoolCalls,\n\t\t\t}\n\t\t})\n\n\t\t// Get selected source IDs from selection\n\t\tconst selectedSourceIds = state.toolSelection?.selection?.selectedSources?.map((s) => s.sourceId) ?? []\n\n\t\tconst thread = {\n\t\t\tid: state.currentThreadId ?? null,\n\t\t\tisRunning: state.isRunning,\n\t\t\tisEmpty: messages.length === 0,\n\t\t\tmessageCount: messages.length,\n\t\t\tmessages,\n\t\t\tpendingApprovals: state.pendingToolCalls.map((tc) => ({\n\t\t\t\tmessageId: tc.messageId,\n\t\t\t\ttoolCallId: tc.toolCallId,\n\t\t\t\ttoolName: tc.toolName,\n\t\t\t\targs: tc.args,\n\t\t\t})),\n\t\t\tcurrentAction: state.isRunning && state.pendingToolCalls.length > 0\n\t\t\t\t? { toolName: state.pendingToolCalls[0].toolName, status: 'pending' }\n\t\t\t\t: null,\n\t\t}\n\n\t\t// Build voice state\n\t\tconst voice = state.voiceThread\n\t\t\t? {\n\t\t\t\t\tisActive: state.voiceThread.isActive,\n\t\t\t\t\tisConnecting: state.voiceThread.isConnecting,\n\t\t\t\t\tisMuted: state.voiceThread.isMuted,\n\t\t\t\t\tisSupported: state.voiceThread.isSupported,\n\t\t\t\t\ttranscript: state.voiceThread.transcript ?? null,\n\t\t\t\t\terror: state.voiceThread.error ?? null,\n\t\t\t\t}\n\t\t\t: { error: 'Voice context not available' }\n\n\t\t// Build tools state\n\t\tconst tools = {\n\t\t\tapprovalMode: state.toolApproval?.mode ?? 'ask',\n\t\t\tlocalTools: (state.mcpTools?.tools ?? []).map((t) => ({\n\t\t\t\tname: t.name,\n\t\t\t\tdescription: t.description?.slice(0, 100) ?? '',\n\t\t\t\tsourceId: t._sourceId ?? 'unknown',\n\t\t\t})),\n\t\t\tmcpSources: state.mcpTools\n\t\t\t\t? Array.from(state.mcpTools.sources.entries()).map(([id, source]) => ({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tstate: source.state,\n\t\t\t\t\t\ttoolCount: source.tools.length,\n\t\t\t\t\t\terror: source.error ?? null,\n\t\t\t\t\t}))\n\t\t\t\t: [],\n\t\t\tremoteSources: state.toolSelection\n\t\t\t\t? state.toolSelection.sources.map((s) => ({\n\t\t\t\t\t\tsourceId: s.sourceId,\n\t\t\t\t\t\ttabId: s.tabId,\n\t\t\t\t\t\ttitle: s.title ?? 'Unknown',\n\t\t\t\t\t\turl: s.url ?? '',\n\t\t\t\t\t\ttoolCount: s.toolCount,\n\t\t\t\t\t\tisSelected: selectedSourceIds.includes(s.sourceId),\n\t\t\t\t\t}))\n\t\t\t\t: [],\n\t\t\tcurrentSourceId: state.toolSelection?.currentSourceId ?? null,\n\t\t}\n\n\t\t// Build connection state\n\t\tconst connection = {\n\t\t\tmanagerReadyState: managerState?.readyState ?? -1,\n\t\t\tmanagerReadyStateLabel: managerState?.readyStateLabel ?? 'UNKNOWN',\n\t\t\tcloudflareThread: cloudflareThread ?? { error: 'CloudflareThread context not provided' },\n\t\t}\n\n\t\treturn { ui, thread, voice, tools, connection }\n\t}, [])\n\n\tuseWebMCP({\n\t\tname: `${DEBUG_TOOL_PREFIX}state`,\n\t\tdescription: DEBUG_STATE_DESCRIPTION,\n\t\tinputSchema: DEBUG_STATE_SCHEMA,\n\t\thandler: handleDebugState,\n\t})\n\n\t// =========================================================================\n\t// Tool 2: debug_ui - UI and Composer Control\n\t// =========================================================================\n\tconst handleDebugUi = useCallback(async (args: { action: string; mode?: string; text?: string }) => {\n\t\tconst { action, mode, text } = args\n\t\tconst state = stateRef.current\n\n\t\tswitch (action) {\n\t\t\tcase 'setMode':\n\t\t\t\tif (!mode) {\n\t\t\t\t\treturn { success: false, error: 'mode parameter required for setMode action' }\n\t\t\t\t}\n\t\t\t\tif (!state.agentUI) {\n\t\t\t\t\treturn { success: false, error: 'AgentUI context not available' }\n\t\t\t\t}\n\t\t\t\tstate.agentUI.setUserMode(mode as PillMode)\n\t\t\t\treturn { success: true, mode }\n\n\t\t\tcase 'expand':\n\t\t\t\tif (!state.agentUI) {\n\t\t\t\t\treturn { success: false, error: 'AgentUI context not available' }\n\t\t\t\t}\n\t\t\t\tstate.agentUI.expand()\n\t\t\t\treturn { success: true, mode: 'composing' }\n\n\t\t\tcase 'collapse':\n\t\t\t\tif (!state.agentUI) {\n\t\t\t\t\treturn { success: false, error: 'AgentUI context not available' }\n\t\t\t\t}\n\t\t\t\tstate.agentUI.collapse()\n\t\t\t\treturn { success: true, mode: 'collapsed' }\n\n\t\t\tcase 'toggleFullScreen':\n\t\t\t\tif (!state.agentUI) {\n\t\t\t\t\treturn { success: false, error: 'AgentUI context not available' }\n\t\t\t\t}\n\t\t\t\tstate.agentUI.toggleFullScreen()\n\t\t\t\treturn { success: true, isFullScreen: !state.agentUI.isFullScreen }\n\n\t\t\tcase 'resetPosition':\n\t\t\t\tif (!state.agentUI) {\n\t\t\t\t\treturn { success: false, error: 'AgentUI context not available' }\n\t\t\t\t}\n\t\t\t\tstate.agentUI.resetPosition()\n\t\t\t\treturn { success: true, position: { x: 0, y: 0 } }\n\n\t\t\tcase 'markRead':\n\t\t\t\tif (!state.agentUI) {\n\t\t\t\t\treturn { success: false, error: 'AgentUI context not available' }\n\t\t\t\t}\n\t\t\t\tstate.agentUI.markRead()\n\t\t\t\treturn { success: true, hasUnread: false }\n\n\t\t\tcase 'sendMessage':\n\t\t\t\tif (!text) {\n\t\t\t\t\treturn { success: false, error: 'text parameter required for sendMessage action' }\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tconst composer = state.assistantApi.composer()\n\t\t\t\t\tcomposer.setText(text)\n\t\t\t\t\tcomposer.send()\n\t\t\t\t\treturn { success: true, message: text }\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn { success: false, error: e instanceof Error ? e.message : 'Failed to send message' }\n\t\t\t\t}\n\n\t\t\tcase 'setText':\n\t\t\t\tif (text === undefined) {\n\t\t\t\t\treturn { success: false, error: 'text parameter required for setText action' }\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tstate.assistantApi.composer().setText(text)\n\t\t\t\t\treturn { success: true, text }\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn { success: false, error: e instanceof Error ? e.message : 'Failed to set text' }\n\t\t\t\t}\n\n\t\t\tcase 'clearComposer':\n\t\t\t\ttry {\n\t\t\t\t\tstate.assistantApi.composer().reset()\n\t\t\t\t\treturn { success: true }\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn { success: false, error: e instanceof Error ? e.message : 'Failed to clear composer' }\n\t\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\treturn { success: false, error: `Unknown action: ${action}` }\n\t\t}\n\t}, [])\n\n\tuseWebMCP({\n\t\tname: `${DEBUG_TOOL_PREFIX}ui`,\n\t\tdescription: DEBUG_UI_DESCRIPTION,\n\t\tinputSchema: DEBUG_UI_SCHEMA,\n\t\thandler: handleDebugUi,\n\t})\n\n\t// =========================================================================\n\t// Tool 3: debug_tools - Tool Approval and Source Management\n\t// =========================================================================\n\tconst handleDebugTools = useCallback(async (args: {\n\t\taction: string\n\t\ttoolCallId?: string\n\t\treason?: string\n\t\tmode?: string\n\t\tsourceIds?: string[]\n\t}) => {\n\t\tconst { action, toolCallId, reason, mode, sourceIds } = args\n\t\tconst state = stateRef.current\n\n\t\tswitch (action) {\n\t\t\tcase 'approve': {\n\t\t\t\tif (state.pendingToolCalls.length === 0) {\n\t\t\t\t\treturn { success: false, error: 'No pending tool calls to approve' }\n\t\t\t\t}\n\n\t\t\t\tconst target = toolCallId\n\t\t\t\t\t? state.pendingToolCalls.find((tc) => tc.toolCallId === toolCallId)\n\t\t\t\t\t: state.pendingToolCalls[0]\n\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn { success: false, error: `Tool call not found: ${toolCallId}` }\n\t\t\t\t}\n\n\t\t\t\t// Execute the tool via MCP and add result\n\t\t\t\tif (!state.mcpTools) {\n\t\t\t\t\treturn { success: false, error: 'MCP tools context not available' }\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await state.mcpTools.callTool(target.toolName, target.args)\n\t\t\t\t\tconst resultString = JSON.stringify(result.content ?? result)\n\t\t\t\t\tresolvePendingToolCall(state.threadRuntime, target.messageId, target.toolCallId, resultString)\n\t\t\t\t\treturn { success: true, toolName: target.toolName, result: resultString }\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconst errorMsg = e instanceof Error ? e.message : 'Tool execution failed'\n\t\t\t\t\tresolvePendingToolCall(state.threadRuntime, target.messageId, target.toolCallId, `Error: ${errorMsg}`)\n\t\t\t\t\treturn { success: false, error: errorMsg }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcase 'deny': {\n\t\t\t\tif (state.pendingToolCalls.length === 0) {\n\t\t\t\t\treturn { success: false, error: 'No pending tool calls to deny' }\n\t\t\t\t}\n\n\t\t\t\tconst target = toolCallId\n\t\t\t\t\t? state.pendingToolCalls.find((tc) => tc.toolCallId === toolCallId)\n\t\t\t\t\t: state.pendingToolCalls[0]\n\n\t\t\t\tif (!target) {\n\t\t\t\t\treturn { success: false, error: `Tool call not found: ${toolCallId}` }\n\t\t\t\t}\n\n\t\t\t\tconst denyMessage = reason\n\t\t\t\t\t? `${TOOL_DENIED_MESSAGE} Reason: ${reason}`\n\t\t\t\t\t: TOOL_DENIED_MESSAGE\n\n\t\t\t\tresolvePendingToolCall(state.threadRuntime, target.messageId, target.toolCallId, denyMessage)\n\t\t\t\treturn { success: true, toolName: target.toolName, denied: true, reason }\n\t\t\t}\n\n\t\t\tcase 'setApprovalMode':\n\t\t\t\tif (!mode) {\n\t\t\t\t\treturn { success: false, error: 'mode parameter required for setApprovalMode action' }\n\t\t\t\t}\n\t\t\t\tif (!state.toolApproval) {\n\t\t\t\t\treturn { success: false, error: 'ToolApproval context not available' }\n\t\t\t\t}\n\t\t\t\tstate.toolApproval.setMode(mode as ToolApprovalMode)\n\t\t\t\treturn { success: true, mode }\n\n\t\t\tcase 'selectSources': {\n\t\t\t\tif (!sourceIds || sourceIds.length === 0) {\n\t\t\t\t\treturn { success: false, error: 'sourceIds parameter required for selectSources action' }\n\t\t\t\t}\n\t\t\t\tif (!state.toolSelection) {\n\t\t\t\t\treturn { success: false, error: 'ToolSelection context not available' }\n\t\t\t\t}\n\n\t\t\t\t// Build ToolSourceSelector array from source IDs\n\t\t\t\tconst selectedSources: ToolSourceSelector[] = sourceIds\n\t\t\t\t\t.map((sourceId) => {\n\t\t\t\t\t\tconst source = state.toolSelection!.sources.find((s) => s.sourceId === sourceId)\n\t\t\t\t\t\tif (!source) return null\n\t\t\t\t\t\treturn { sourceId: source.sourceId, tabId: source.tabId }\n\t\t\t\t\t})\n\t\t\t\t\t.filter((s): s is ToolSourceSelector => s !== null)\n\n\t\t\t\tawait state.toolSelection.setSelection({ selectedSources })\n\t\t\t\treturn { success: true, selectedSourceIds: selectedSources.map((s) => s.sourceId) }\n\t\t\t}\n\n\t\t\tcase 'deselectSources': {\n\t\t\t\tif (!sourceIds || sourceIds.length === 0) {\n\t\t\t\t\treturn { success: false, error: 'sourceIds parameter required for deselectSources action' }\n\t\t\t\t}\n\t\t\t\tif (!state.toolSelection) {\n\t\t\t\t\treturn { success: false, error: 'ToolSelection context not available' }\n\t\t\t\t}\n\n\t\t\t\tconst currentSelected = state.toolSelection.selection?.selectedSources ?? []\n\t\t\t\tconst newSelected = currentSelected.filter((s) => !sourceIds.includes(s.sourceId))\n\t\t\t\tawait state.toolSelection.setSelection({ selectedSources: newSelected })\n\t\t\t\treturn { success: true, selectedSourceIds: newSelected.map((s) => s.sourceId) }\n\t\t\t}\n\n\t\t\tcase 'selectAllSources': {\n\t\t\t\tif (!state.toolSelection) {\n\t\t\t\t\treturn { success: false, error: 'ToolSelection context not available' }\n\t\t\t\t}\n\n\t\t\t\tconst allSources: ToolSourceSelector[] = state.toolSelection.sources.map((s) => ({\n\t\t\t\t\tsourceId: s.sourceId,\n\t\t\t\t\ttabId: s.tabId,\n\t\t\t\t}))\n\t\t\t\tawait state.toolSelection.setSelection({ selectedSources: allSources })\n\t\t\t\treturn { success: true, selectedSourceIds: allSources.map((s) => s.sourceId) }\n\t\t\t}\n\n\t\t\tcase 'deselectAllSources': {\n\t\t\t\tif (!state.toolSelection) {\n\t\t\t\t\treturn { success: false, error: 'ToolSelection context not available' }\n\t\t\t\t}\n\n\t\t\t\tawait state.toolSelection.setSelection({ selectedSources: [] })\n\t\t\t\treturn { success: true, selectedSourceIds: [] }\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\treturn { success: false, error: `Unknown action: ${action}` }\n\t\t}\n\t}, [])\n\n\tuseWebMCP({\n\t\tname: `${DEBUG_TOOL_PREFIX}tools`,\n\t\tdescription: DEBUG_TOOLS_DESCRIPTION,\n\t\tinputSchema: DEBUG_TOOLS_SCHEMA,\n\t\thandler: handleDebugTools,\n\t})\n\n\t// =========================================================================\n\t// Tool 4: debug_session - Thread and Voice Control\n\t// =========================================================================\n\tconst handleDebugSession = useCallback(async (args: { action: string; threadId?: string }) => {\n\t\tconst { action, threadId } = args\n\t\tconst state = stateRef.current\n\n\t\tswitch (action) {\n\t\t\tcase 'startNewThread':\n\t\t\t\ttry {\n\t\t\t\t\tstate.assistantApi.threads().switchToNewThread()\n\t\t\t\t\treturn { success: true, message: 'Started new thread' }\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn { success: false, error: e instanceof Error ? e.message : 'Failed to start new thread' }\n\t\t\t\t}\n\n\t\t\tcase 'switchThread':\n\t\t\t\tif (!threadId) {\n\t\t\t\t\treturn { success: false, error: 'threadId parameter required for switchThread action' }\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tstate.assistantApi.threads().switchToThread(threadId)\n\t\t\t\t\treturn { success: true, threadId }\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn { success: false, error: e instanceof Error ? e.message : 'Failed to switch thread' }\n\t\t\t\t}\n\n\t\t\tcase 'listThreads':\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tisLoading: state.threadsLoading,\n\t\t\t\t\tcurrentThreadId: state.currentThreadId,\n\t\t\t\t\tthreadIds: [...state.threadIds],\n\t\t\t\t}\n\n\t\t\tcase 'voiceStart':\n\t\t\t\tif (!state.voiceThread) {\n\t\t\t\t\treturn { success: false, error: 'Voice context not available' }\n\t\t\t\t}\n\t\t\t\tif (!state.voiceThread.isSupported) {\n\t\t\t\t\treturn { success: false, error: 'Voice mode not supported in this browser' }\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait state.voiceThread.start()\n\t\t\t\t\treturn { success: true, message: 'Voice session started' }\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn { success: false, error: e instanceof Error ? e.message : 'Failed to start voice session' }\n\t\t\t\t}\n\n\t\t\tcase 'voiceStop':\n\t\t\t\tif (!state.voiceThread) {\n\t\t\t\t\treturn { success: false, error: 'Voice context not available' }\n\t\t\t\t}\n\t\t\t\tstate.voiceThread.stop()\n\t\t\t\treturn { success: true, message: 'Voice session stopped' }\n\n\t\t\tcase 'voiceToggleMute':\n\t\t\t\tif (!state.voiceThread) {\n\t\t\t\t\treturn { success: false, error: 'Voice context not available' }\n\t\t\t\t}\n\t\t\t\tstate.voiceThread.toggleMute()\n\t\t\t\treturn { success: true, isMuted: !state.voiceThread.isMuted }\n\n\t\t\tdefault:\n\t\t\t\treturn { success: false, error: `Unknown action: ${action}` }\n\t\t}\n\t}, [])\n\n\tuseWebMCP({\n\t\tname: `${DEBUG_TOOL_PREFIX}session`,\n\t\tdescription: DEBUG_SESSION_DESCRIPTION,\n\t\tinputSchema: DEBUG_SESSION_SCHEMA,\n\t\thandler: handleDebugSession,\n\t})\n}\n\n/**\n * Check if a tool name is a debug tool based on prefix\n */\nexport function isDebugTool(toolName: string): boolean {\n\treturn toolName.startsWith(DEBUG_TOOL_PREFIX)\n}\n","/**\n * TicketExchangeGate\n *\n * HTTP authentication gate that performs ticket exchange BEFORE any WebSocket connection.\n *\n * This component ensures proper authentication flow:\n * 1. Ticket Exchange (HTTP) ← BEFORE any WebSocket\n * 2. Connect to ThreadManager DO (with org ID known upfront)\n * 3. Connect to ThreadAgent DO (after ThreadManager provides thread ID)\n *\n * Modes:\n * - Anonymous: anthropicApiKey provided, no authToken → pass through immediately\n * - SSR: ticketAuth already provided → pass through immediately\n * - SPA: authToken provided → exchange for ticket first, then render children\n *\n * Following Vercel React best practices:\n * - Early returns for clear state machine\n * - Functional setState to prevent stale closures\n * - Narrow effect dependencies (primitives, not objects)\n * - Ref for deduplication of concurrent exchanges\n * - Throws for error boundary (errors bubble up to AuthErrorBoundary)\n */\n\nimport { useEffect, useRef, useState, type ReactNode } from 'react'\n\nimport type { TicketAuth, TicketExchangeResponse } from '@char-ai/auth'\nimport type { AuthErrorJsonPayload, ErrorCallToAction } from '@char-ai/auth/errors'\nimport { buildAuthError } from '@char-ai/auth/errors'\n\nimport { AuthErrorException } from '../utils/convert-init-error'\nimport type { AuthError, AuthErrorCode } from '../utils/auth-errors'\n\n/**\n * Resolved authentication state passed to children.\n */\nexport interface ResolvedAuth {\n\tmode: 'authenticated' | 'anonymous'\n\t/** For authenticated mode: ticket data with userId, orgId, and ticket string */\n\tticketAuth?: TicketAuth\n\t/** For anonymous mode: API key for direct Anthropic calls */\n\tanthropicApiKey?: string\n}\n\n/**\n * Props for TicketExchangeGate component.\n */\nexport interface TicketExchangeGateProps {\n\t/** Render prop that receives resolved auth state */\n\tchildren: (auth: ResolvedAuth) => ReactNode\n\t/** API base URL for ticket exchange endpoint */\n\tapiBase: string\n\t/** IDP token for SPA authentication (will be exchanged for ticket) */\n\tauthToken?: string\n\t/** OIDC client ID for audience validation (required with authToken) */\n\tclientId?: string\n\t/** Pre-fetched ticket for SSR authentication (takes precedence over authToken) */\n\tticketAuth?: TicketAuth\n\t/** Anthropic API key for anonymous/development mode */\n\tanthropicApiKey?: string\n}\n\n/**\n * Result of ticket exchange - either success with ticket or failure with full error details.\n */\ntype TicketExchangeResult =\n\t| { success: true; ticketAuth: TicketAuth }\n\t| {\n\t\t\tsuccess: false\n\t\t\tcode: string\n\t\t\ttitle: string\n\t\t\tmessage: string\n\t\t\tcallToAction?: ErrorCallToAction\n\t\t\tdashboardLink?: string\n\t\t\tdocsLink?: string\n\t\t\trecoverable: boolean\n\t }\n\n/**\n * Exchange an IDP token for a short-lived ticket.\n *\n * This unifies SPA and SSR authentication:\n * - SPA: Embedded agent calls this internally\n * - SSR: Customer's server calls this, passes ticket to embedded agent\n *\n * Both paths end up using initContextWithTicket for WebSocket auth.\n *\n * @param authToken - The IDP token to exchange\n * @param clientId - The OIDC client ID for audience validation\n * @param apiBase - The API base URL\n */\nasync function exchangeTokenForTicket(\n\tauthToken: string,\n\tclientId: string,\n\tapiBase: string,\n): Promise<TicketExchangeResult> {\n\ttry {\n\t\t// Note: Origin header is automatically set by the browser for cross-origin requests\n\t\t// The backend uses it for origin binding (tickets are bound to the origin that created them)\n\t\tconst response = await fetch(`${apiBase}/api/auth/ticket`, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t},\n\t\t\tbody: JSON.stringify({ client_id: clientId }),\n\t\t})\n\n\t\tif (!response.ok) {\n\t\t\ttry {\n\t\t\t\t// Type the response using the shared payload type from @char-ai/auth\n\t\t\t\tconst data = (await response.json()) as AuthErrorJsonPayload\n\t\t\t\tconst err = data.error\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcode: err.code,\n\t\t\t\t\ttitle: err.title,\n\t\t\t\t\tmessage: err.message,\n\t\t\t\t\tcallToAction: err.callToAction,\n\t\t\t\t\tdashboardLink: err.dashboardLink,\n\t\t\t\t\tdocsLink: err.docsLink,\n\t\t\t\t\trecoverable: err.recoverable,\n\t\t\t\t}\n\t\t\t} catch (parseError) {\n\t\t\t\t// Non-JSON response fallback (e.g., HTML error page)\n\t\t\t\tconsole.error('[TicketExchangeGate] Failed to parse error response:', {\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t\tstatusText: response.statusText,\n\t\t\t\t\tparseError: parseError instanceof Error ? parseError.message : String(parseError),\n\t\t\t\t\tcontentType: response.headers.get('content-type'),\n\t\t\t\t})\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tcode: 'UNKNOWN',\n\t\t\t\t\ttitle: 'Authentication Failed',\n\t\t\t\t\tmessage: `Server returned status ${response.status}`,\n\t\t\t\t\trecoverable: false,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst data = (await response.json()) as TicketExchangeResponse\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tticketAuth: {\n\t\t\t\tticket: data.ticket,\n\t\t\t\tuserId: data.userId,\n\t\t\t\torgId: data.orgId,\n\t\t\t},\n\t\t}\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\t\tconst errorName = error instanceof Error ? error.name : 'Unknown'\n\n\t\t// Distinguish network errors from other failures (e.g., JSON parse errors)\n\t\tconst isNetworkError =\n\t\t\t(error instanceof TypeError && errorMessage.includes('fetch')) ||\n\t\t\t(error instanceof DOMException && error.name === 'AbortError')\n\n\t\tconsole.error('[TicketExchangeGate] Error:', {\n\t\t\ttype: isNetworkError ? 'NETWORK_ERROR' : 'TOKEN_EXCHANGE_ERROR',\n\t\t\terror: errorMessage,\n\t\t\tname: errorName,\n\t\t})\n\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\tcode: isNetworkError ? 'NETWORK_ERROR' : 'TOKEN_EXCHANGE_ERROR',\n\t\t\ttitle: isNetworkError ? 'Network Error' : 'Authentication Failed',\n\t\t\tmessage: isNetworkError\n\t\t\t\t? 'Unable to reach authentication server. Please check your connection.'\n\t\t\t\t: `Authentication failed: ${errorMessage}`,\n\t\t\trecoverable: isNetworkError,\n\t\t}\n\t}\n}\n\n/**\n * Loading spinner shown during ticket exchange.\n */\nfunction AuthLoadingSpinner() {\n\treturn (\n\t\t<div\n\t\t\tclassName=\"flex items-center justify-center h-full min-h-40\"\n\t\t\taria-label=\"Authenticating\"\n\t\t>\n\t\t\t<div className=\"animate-spin rounded-full h-6 w-6 border-2 border-muted-foreground/20 border-t-muted-foreground/60\" />\n\t\t</div>\n\t)\n}\n\n/**\n * TicketExchangeGate performs HTTP authentication before rendering children.\n *\n * This ensures proper auth flow:\n * 1. Ticket exchange happens BEFORE any WebSocket connection\n * 2. Children receive resolved auth state (ticket or API key)\n * 3. Errors bubble up to AuthErrorBoundary\n */\nexport function TicketExchangeGate({\n\tchildren,\n\tapiBase,\n\tauthToken,\n\tclientId,\n\tticketAuth: providedTicket,\n\tanthropicApiKey,\n}: TicketExchangeGateProps): ReactNode {\n\t// State for SPA ticket exchange\n\tconst [exchangedTicket, setExchangedTicket] = useState<TicketAuth | null>(null)\n\tconst [error, setError] = useState<AuthError | null>(null)\n\tconst [isExchanging, setIsExchanging] = useState(false)\n\n\t// Dedup concurrent exchange attempts\n\tconst exchangePromiseRef = useRef<Promise<TicketExchangeResult> | null>(null)\n\n\t// Track component mount state to prevent state updates after unmount\n\tconst isMountedRef = useRef(true)\n\tuseEffect(() => {\n\t\tisMountedRef.current = true\n\t\treturn () => {\n\t\t\tisMountedRef.current = false\n\t\t}\n\t}, [])\n\n\t// Reset state when auth inputs change\n\tconst prevAuthTokenRef = useRef<string | undefined>(authToken)\n\tconst prevProvidedTicketRef = useRef<string | undefined>(providedTicket?.ticket)\n\n\tuseEffect(() => {\n\t\tconst authTokenChanged = authToken !== prevAuthTokenRef.current\n\t\tconst providedTicketChanged = providedTicket?.ticket !== prevProvidedTicketRef.current\n\n\t\tif (!authTokenChanged && !providedTicketChanged) return\n\n\t\tprevAuthTokenRef.current = authToken\n\t\tprevProvidedTicketRef.current = providedTicket?.ticket\n\n\t\t// Reset all exchange state\n\t\tsetExchangedTicket(null)\n\t\tsetError(null)\n\t\tsetIsExchanging(false)\n\t\texchangePromiseRef.current = null\n\t}, [authToken, providedTicket?.ticket])\n\n\t// === EFFECT: Trigger ticket exchange (SPA mode) ===\n\t// This effect runs when we have authToken + clientId but no ticket yet\n\t// MUST be called unconditionally (before early returns) to follow Rules of Hooks\n\tuseEffect(() => {\n\t\tif (!authToken || !clientId) return // Missing required props\n\t\tif (exchangedTicket || error) return // Already done\n\t\tif (exchangePromiseRef.current) return // Already in progress\n\n\t\tsetIsExchanging(true)\n\t\texchangePromiseRef.current = exchangeTokenForTicket(authToken, clientId, apiBase)\n\n\t\texchangePromiseRef.current\n\t\t\t.then((result) => {\n\t\t\t\tif (!isMountedRef.current) return\n\n\t\t\t\tif (result.success) {\n\t\t\t\t\tsetExchangedTicket(result.ticketAuth)\n\t\t\t\t} else {\n\t\t\t\t\t// Pass through all error fields from the server response\n\t\t\t\t\tsetError({\n\t\t\t\t\t\tcode: result.code as AuthErrorCode,\n\t\t\t\t\t\ttitle: result.title,\n\t\t\t\t\t\tmessage: result.message,\n\t\t\t\t\t\tcallToAction: result.callToAction,\n\t\t\t\t\t\tdashboardLink: result.dashboardLink,\n\t\t\t\t\t\tdocsLink: result.docsLink,\n\t\t\t\t\t\trecoverable: result.recoverable,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((err) => {\n\t\t\t\tif (!isMountedRef.current) return\n\n\t\t\t\t// This catch should rarely be hit since exchangeTokenForTicket handles errors internally.\n\t\t\t\t// If we get here, it's an unexpected error (bug in our code, not network issues).\n\t\t\t\tconst errorType = err instanceof Error ? err.constructor.name : typeof err\n\t\t\t\tconst errorMessage = err instanceof Error ? err.message : String(err)\n\n\t\t\t\tconsole.error('[TicketExchangeGate] Unexpected error in ticket exchange:', {\n\t\t\t\t\terrorType,\n\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\tstack: err instanceof Error ? err.stack : undefined,\n\t\t\t\t})\n\n\t\t\t\tsetError({\n\t\t\t\t\tcode: 'INTERNAL_ERROR' as AuthErrorCode,\n\t\t\t\t\ttitle: 'Unexpected Error',\n\t\t\t\t\tmessage: `An unexpected error occurred during authentication (${errorType}). Please refresh the page.`,\n\t\t\t\t\tdebugInfo: `${errorType}: ${errorMessage}`,\n\t\t\t\t\trecoverable: false,\n\t\t\t\t})\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (isMountedRef.current) {\n\t\t\t\t\tsetIsExchanging(false)\n\t\t\t\t}\n\t\t\t})\n\t}, [authToken, clientId, apiBase, exchangedTicket, error])\n\n\t// ═══════════════════════════════════════════════════════════════════════════\n\t// EARLY RETURNS - After all hooks have been called\n\t// ═══════════════════════════════════════════════════════════════════════════\n\n\t// 1. Anonymous mode: Pass through immediately (no ticket needed)\n\tif (!authToken && anthropicApiKey) {\n\t\treturn children({ mode: 'anonymous', anthropicApiKey })\n\t}\n\n\t// 2. SSR mode: Ticket already provided\n\tif (providedTicket) {\n\t\treturn children({ mode: 'authenticated', ticketAuth: providedTicket })\n\t}\n\n\t// 3. SPA mode with successful exchange\n\tif (exchangedTicket) {\n\t\treturn children({ mode: 'authenticated', ticketAuth: exchangedTicket })\n\t}\n\n\t// 4. Error state: Throw for boundary\n\tif (error) {\n\t\tthrow new AuthErrorException(error)\n\t}\n\n\t// 5. Missing required props (validation)\n\tif (authToken && !clientId) {\n\t\tconst err = buildAuthError({ errorCode: 'MISSING_CLIENT_ID' })\n\t\tthrow new AuthErrorException({\n\t\t\tcode: err.errorCode,\n\t\t\ttitle: err.errorTitle,\n\t\t\tmessage: err.message,\n\t\t\tcallToAction: err.callToAction,\n\t\t\tdashboardLink: err.dashboardLink,\n\t\t\tdocsLink: err.docsLink,\n\t\t\trecoverable: err.recoverable,\n\t\t})\n\t}\n\n\t// 6. Loading state - covers both:\n\t// - \"waiting for connect()\" (no auth provided yet)\n\t// - \"ticket exchange in progress\" (isExchanging === true)\n\t// DO NOT THROW HERE - the web component pattern requires time for\n\t// connect({ idToken, clientId }) to be called after mount.\n\treturn <AuthLoadingSpinner />\n}\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 * - TicketExchangeGate (HTTP auth before WebSocket connection)\n * - CloudflareThreadRuntimeProvider (chat runtime via Durable Objects)\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 * AuthErrorBoundary (catches auth errors from children)\n * └── AgentUIProvider (UI state - persists across threads)\n * └── MCPToolsProvider (tools - shared across threads)\n * └── TicketExchangeGate (HTTP ticket exchange BEFORE WebSocket)\n * ├── [Loading] while exchanging ticket\n * ├── [Error] throws to AuthErrorBoundary\n * └── [Success] renders children with resolved auth\n * └── CloudflareThreadRuntimeProvider (DO-backed thread state)\n * └── VoiceThreadBridge (voice → thread integration)\n * └── children\n * ```\n *\n * Runtime Modes (both use Durable Objects for persistence):\n * - Authenticated: authToken provided (SSO-first - IDP token validates user/org)\n * - Anonymous: anthropicApiKey provided, no authToken (localhost-only dev mode)\n *\n * Tool sync: MCP tools are synced directly to the CF agent backend via\n * the ThreadManager + ThreadAgent runtimes, similar to how voice mode syncs\n * tools to the OpenAI Realtime service.\n *\n * @example Authenticated usage (SSO-first)\n * ```tsx\n * import { AgentProvider, AgentPill } from '@mcp-b/embedded-agent'\n * import { useOktaAuth } from '@okta/okta-react'\n *\n * function App() {\n * const { authState } = useOktaAuth()\n * return (\n * <AgentProvider\n * apiBase=\"https://your-worker.workers.dev\"\n * authToken={authState?.idToken?.idToken ?? ''}\n * >\n * <AgentPill />\n * </AgentProvider>\n * )\n * }\n * ```\n *\n * @example Anonymous usage (localhost dev mode)\n * ```tsx\n * import { AgentProvider, AgentPill } from '@mcp-b/embedded-agent'\n *\n * function App() {\n * return (\n * <AgentProvider\n * apiBase=\"http://localhost:8787\"\n * anthropicApiKey={import.meta.env.VITE_ANTHROPIC_API_KEY}\n * >\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 type { ToolWithSource } from '@mcp-b/shared-types'\nimport * as React from 'react'\nimport { useCallback, useEffect, useState, type FC, type ReactNode } from 'react'\n\nimport { WEBMCP_PRODUCTION_API_BASE } from '../utils/constants'\nimport { resolveDevMode } from '../utils/dev-mode'\nimport { AuthErrorBoundary } from '../components/errors/AuthErrorBoundary'\n// import { MCPToolRegistry } from './MCPToolRegistry'\nimport { DoneToolUI, FormToolUI } from '../tools'\nimport { MCPToolsProvider, useMCPTools } from './MCPToolsProvider'\nimport {\n\tToolExclusionProvider,\n\ttype ToolExclusionFilter,\n} from './ToolExclusionProvider'\nimport { VoiceThreadBridge } from './VoiceThreadBridge'\nimport { AgentUIProvider, type PillMode } from './AgentUIProvider'\nimport {\n\tCloudflareThreadRuntimeProvider,\n\tuseCloudflareThread,\n\tuseOptionalVoiceSync,\n} from './CloudflareThreadRuntimeProvider'\nimport { ThreadControlProvider } from './ThreadControlProvider'\nimport { useWebMCPDebugTools } from '../hooks/use-webmcp-debug-tools'\nimport { TicketExchangeGate, type ResolvedAuth } from './TicketExchangeGate'\n\nexport interface AgentProviderConfig {\n\t/** API base URL for chat and token endpoints (defaults to production WebMCP API) */\n\tapiBase?: string\n\n\t/**\n\t * IDP token for SSO-first authentication.\n\t *\n\t * When provided:\n\t * - Uses WebSocket connection to Cloudflare Durable Object\n\t * - Messages are persisted and survive page refresh\n\t * - Supports refresh-safe streaming\n\t * - Backend validates token against org's configured IDP\n\t * - User ID extracted from token's sub claim\n\t *\n\t * When NOT provided:\n\t * - Uses anonymous mode with Durable Objects\n\t * - Requires anthropicApiKey for AI calls\n\t * - Localhost-only for security\n\t * - Good for development/testing\n\t *\n\t * Benefits:\n\t * - No API keys needed (for authenticated mode)\n\t * - Zero backend code for OIDC customers\n\t * - Users don't need to log in again (already authenticated)\n\t *\n\t * @example\n\t * ```tsx\n\t * // Customer's existing auth (unchanged)\n\t * const { session } = useOktaAuth()\n\t *\n\t * // Pass the token they already have\n\t * <AgentProvider authToken={session.idToken} clientId=\"your-client-id\" />\n\t * ```\n\t *\n\t * Note: If `ticketAuth` is provided, it takes precedence over `authToken`.\n\t */\n\tauthToken?: string\n\n\t/**\n\t * OIDC client ID for audience validation.\n\t * Required when using `authToken` authentication.\n\t *\n\t * This must match the token's `aud` claim and be in the organization's\n\t * `allowed_audiences` list (configured in the Char dashboard).\n\t */\n\tclientId?: string\n\n\t/**\n\t * Pre-fetched ticket for SSR-friendly authentication.\n\t * Use this when your server has already exchanged the IDP token for a ticket.\n\t *\n\t * Benefits:\n\t * - IDP token never exposed to browser (in SSR mode)\n\t * - No JWKS fetch on every connection (validation done once)\n\t * - Ticket is short-lived (30s default) and single-use\n\t *\n\t * To use: Call POST /api/auth/ticket from your server, then pass the response here.\n\t *\n\t * Takes precedence over `authToken` if both are provided.\n\t */\n\tticketAuth?: {\n\t\tticket: string\n\t\tuserId: string\n\t\torgId: string\n\t}\n\n\t/**\n\t * Anthropic API key for anonymous/development mode.\n\t *\n\t * When provided WITHOUT authToken:\n\t * - Uses anonymous mode with Durable Objects\n\t * - User's API key is passed to backend and stored in DO state\n\t * - Localhost-only for security\n\t * - Good for development/testing without SSO setup\n\t *\n\t * When authToken is provided, this is ignored (uses authenticated mode).\n\t */\n\tanthropicApiKey?: string\n\n\t/**\n\t * Development mode configuration (alternative to anthropicApiKey).\n\t * When provided, anthropicApiKey is extracted from devMode.anthropicApiKey.\n\t */\n\tdevMode?: {\n\t\tanthropicApiKey?: string\n\t\topenaiApiKey?: string\n\t\tuseLocalApi?: boolean\n\t}\n\n\t/** Host for the Cloudflare Agent WebSocket connection (defaults to apiBase hostname or localhost:8787) */\n\thost?: string\n\n\t/** Agent binding name to connect to (defaults to 'ChatAgent') */\n\tagent?: 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/**\n\t * Controlled open state. When provided, the host controls whether the UI is open.\n\t * Use with `onOpenChange` to handle state changes.\n\t */\n\topen?: boolean\n\n\t/** Initial open state for uncontrolled usage (default: false) */\n\tdefaultOpen?: boolean\n\n\t/** Initial pill mode (default: 'collapsed') */\n\tdefaultMode?: PillMode\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/**\n\t * Custom filter function to exclude tools from the agent.\n\t * Return true to exclude the tool, false to include it.\n\t *\n\t * @example Exclude by prefix\n\t * ```tsx\n\t * excludeTools={(name) => name.startsWith('internal_')}\n\t * ```\n\t */\n\texcludeTools?: ToolExclusionFilter\n\n\t/**\n\t * Array of specific tool names to exclude from the agent.\n\t */\n\texcludeToolNames?: string[]\n\n\t/**\n\t * Array of prefixes - tools starting with any of these will be excluded.\n\t */\n\texcludeToolPrefixes?: string[]\n\n\t/**\n\t * Enable debug tools for inspecting embedded agent internal state.\n\t * Debug tools are prefixed with `debug_` and expose:\n\t * - Agent connection state\n\t * - Tool sources from ThreadManager\n\t * - Local MCP tools\n\t * - Cross-site tool calling diagnostics\n\t *\n\t * @default false\n\t */\n\tenableDebugTools?: boolean\n\n\t/**\n\t * Base URL for dashboard (for error screen links).\n\t * @example \"https://app.usechar.ai\"\n\t */\n\tdashboardBaseUrl?: string\n\n\t/**\n\t * Base URL for documentation (for error screen links).\n\t * @example \"https://docs.usechar.ai\"\n\t */\n\tdocsBaseUrl?: string\n\n\t/**\n\t * Callback when an authentication error occurs.\n\t * Useful for logging/analytics.\n\t */\n\tonAuthError?: (error: Error, errorInfo?: React.ErrorInfo) => void\n\n\t/**\n\t * Show debug info in error screens (dev mode).\n\t * @default false\n\t */\n\tshowErrorDebug?: boolean\n\n\t/**\n\t * Close handler callback (passed to error screens).\n\t * When the close button on an error screen is clicked,\n\t * a 'char-close' CustomEvent is dispatched as the primary mechanism,\n\t * and this callback is invoked as a secondary mechanism.\n\t */\n\tonClose?: () => void\n}\n\nexport interface AgentProviderProps extends AgentProviderConfig {\n\tchildren: ReactNode\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 * Receives resolvedAuth from TicketExchangeGate (auth is already complete).\n */\ninterface AgentRuntimeProps {\n\tchildren: ReactNode\n\t/** Resolved authentication from TicketExchangeGate */\n\tresolvedAuth: ResolvedAuth\n\t/** WebSocket host (derived from apiBase) */\n\thost: string\n\t/** Voice mode token endpoint */\n\ttokenEndpoint: string\n\tenableDebugTools?: boolean\n\tonVoiceError?: (error: string) => void\n\tonVoiceConnect?: () => void\n\tonVoiceDisconnect?: (duration: number) => void\n}\n\n/**\n * Component that registers debug tools when enabled.\n * Renders inside CloudflareThreadRuntimeProvider to access thread context.\n */\nconst DebugToolsRegistrar: FC = () => {\n\tconst cloudflareThread = useCloudflareThread()\n\tconst { refreshTools } = useMCPTools()\n\n\tuseWebMCPDebugTools({\n\t\tadditionalState: {\n\t\t\tcloudflareThread: {\n\t\t\t\tisInitialized: cloudflareThread.isInitialized,\n\t\t\t\tisReady: cloudflareThread.isReady,\n\t\t\t\tcurrentThreadId: cloudflareThread.currentThreadId,\n\t\t\t\tendUserId: cloudflareThread.endUserId,\n\t\t\t\torganizationId: cloudflareThread.organizationId,\n\t\t\t},\n\t\t},\n\t})\n\n\t// Trigger a refresh after a short delay to allow useWebMCP to register tools.\n\t// This ensures debug tools are discovered even if registered after the initial\n\t// MCP connection. The delay accounts for the useWebMCP effects running.\n\tuseEffect(() => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tvoid refreshTools()\n\t\t}, 200)\n\t\treturn () => clearTimeout(timer)\n\t}, [refreshTools])\n\n\treturn null\n}\n\ninterface StatefulRuntimeBridgeProps {\n\tchildren: ReactNode\n\ttokenEndpoint: string\n\tenableDebugTools?: boolean\n\tonVoiceError?: (error: string) => void\n\tonVoiceConnect?: () => void\n\tonVoiceDisconnect?: (duration: number) => void\n}\n\nconst StatefulRuntimeBridge: FC<StatefulRuntimeBridgeProps> = ({\n\tchildren,\n\ttokenEndpoint,\n\tenableDebugTools,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n}) => {\n\tconst { reset, startNew } = useCloudflareThread()\n\tconst voiceSync = useOptionalVoiceSync()\n\n\treturn (\n\t\t<ThreadControlProvider reset={reset} startNew={startNew}>\n\t\t\t<VoiceThreadBridge\n\t\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\t\tonError={onVoiceError}\n\t\t\t\tonConnect={onVoiceConnect}\n\t\t\t\tonDisconnect={onVoiceDisconnect}\n\t\t\t\tonUserTranscript={voiceSync?.appendUserMessage}\n\t\t\t\tonAssistantTranscript={voiceSync?.appendAssistantMessage}\n\t\t\t\tonToolComplete={voiceSync?.appendToolCall}\n\t\t\t>\n\t\t\t\t{/* <MCPToolRegistry /> */}\n\t\t\t\t{/* Client-side UI tools (HITL pattern) */}\n\t\t\t\t<DoneToolUI />\n\t\t\t\t<FormToolUI />\n\t\t\t\t{enableDebugTools && <DebugToolsRegistrar />}\n\t\t\t\t{children}\n\t\t\t</VoiceThreadBridge>\n\t\t</ThreadControlProvider>\n\t)\n}\n\n/**\n * Unified runtime using Cloudflare Durable Objects.\n * Messages are persisted and streaming is refresh-safe.\n *\n * Receives resolvedAuth from TicketExchangeGate - authentication is already complete.\n * This means we can connect directly to the org-scoped DO without any two-phase init.\n *\n * Note: Tool approval mode is now managed by ThreadAgent state (synced across clients).\n */\nconst UnifiedRuntime: FC<AgentRuntimeProps> = ({\n\tchildren,\n\tresolvedAuth,\n\thost,\n\ttokenEndpoint,\n\tenableDebugTools,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n}) => {\n\t// Get MCP tools and execution function\n\tconst { tools: mcpTools, callTool } = useMCPTools()\n\n\treturn (\n\t\t<CloudflareThreadRuntimeProvider\n\t\t\thost={host}\n\t\t\tresolvedAuth={resolvedAuth}\n\t\t\tmcpTools={mcpTools}\n\t\t\texecuteMCPTool={callTool}\n\t\t>\n\t\t\t<StatefulRuntimeBridge\n\t\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\t\tenableDebugTools={enableDebugTools}\n\t\t\t\tonVoiceError={onVoiceError}\n\t\t\t\tonVoiceConnect={onVoiceConnect}\n\t\t\t\tonVoiceDisconnect={onVoiceDisconnect}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</StatefulRuntimeBridge>\n\t\t</CloudflareThreadRuntimeProvider>\n\t)\n}\n\n/**\n * Unified runtime - always uses Cloudflare Durable Objects.\n *\n * Two modes (both use DOs for persistence):\n * - Authenticated: ticketAuth from TicketExchangeGate (SSO-first)\n * - Anonymous: anthropicApiKey provided (localhost dev mode)\n *\n * Note: Authentication is resolved by TicketExchangeGate before this component mounts.\n */\nconst AgentRuntime: FC<AgentRuntimeProps> = ({\n\tchildren,\n\tresolvedAuth,\n\thost,\n\ttokenEndpoint,\n\tenableDebugTools,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n}) => {\n\treturn (\n\t\t<UnifiedRuntime\n\t\t\tresolvedAuth={resolvedAuth}\n\t\t\thost={host}\n\t\t\ttokenEndpoint={tokenEndpoint}\n\t\t\tenableDebugTools={enableDebugTools}\n\t\t\tonVoiceError={onVoiceError}\n\t\t\tonVoiceConnect={onVoiceConnect}\n\t\t\tonVoiceDisconnect={onVoiceDisconnect}\n\t\t>\n\t\t\t{children}\n\t\t</UnifiedRuntime>\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 ToolApprovalContext (synced from ThreadAgent state)\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 *\n * Note: Tool approval mode is now managed by ThreadAgent state and synced\n * across all connected clients. The defaultApprovalMode prop has been removed.\n */\nexport const AgentProvider: FC<AgentProviderProps> = ({\n\tchildren,\n\tapiBase,\n\tauthToken,\n\tclientId,\n\tticketAuth,\n\tanthropicApiKey: anthropicApiKeyProp,\n\tdevMode,\n\thost,\n\ttokenEndpoint,\n\tautoConnectLocal = true,\n\topen,\n\tdefaultOpen = false,\n\tdefaultMode = 'collapsed',\n\texcludeTools,\n\texcludeToolNames,\n\texcludeToolPrefixes,\n\tenableDebugTools = false,\n\tdashboardBaseUrl,\n\tdocsBaseUrl,\n\tonAuthError,\n\tshowErrorDebug = false,\n\tonClose,\n\tonToolsChange,\n\tonVoiceError,\n\tonVoiceConnect,\n\tonVoiceDisconnect,\n\tonOpenChange,\n\tonModeChange,\n}) => {\n\tconst { devMode: resolvedDevMode, isEmpty } = resolveDevMode(devMode)\n\n\tif (devMode && isEmpty) {\n\t\tthrow new Error(\n\t\t\t'[Char] devMode was provided but contains no usable values. ' +\n\t\t\t'Remove the devMode prop or provide a valid API key (anthropicApiKey/openaiApiKey) ' +\n\t\t\t'or set useLocalApi: true.'\n\t\t)\n\t}\n\n\t// Merge anthropic API key from both sources (devMode takes precedence)\n\tconst anthropicApiKey = resolvedDevMode?.anthropicApiKey ?? anthropicApiKeyProp\n\n\t// Determine if we need tool exclusion\n\tconst hasExclusions = excludeTools || excludeToolNames || excludeToolPrefixes\n\n\t// Retry key forces remount of TicketExchangeGate on retry, resetting all auth state.\n\t// When an auth error occurs, AuthErrorBoundary catches it.\n\t// On retry, incrementing retryKey causes TicketExchangeGate to remount and perform\n\t// a fresh ticket exchange attempt.\n\tconst [retryKey, setRetryKey] = useState(0)\n\n\t// Force remount to reset all internal auth state (ticket exchange, WebSocket connections)\n\tconst handleRetry = useCallback(() => {\n\t\tsetRetryKey((k) => k + 1)\n\t}, [])\n\n\t// Resolve API base (defaults to production)\n\tconst resolvedApiBase = apiBase ?? WEBMCP_PRODUCTION_API_BASE\n\n\t// Derive host from apiBase if not explicitly provided\n\tconst resolvedHost =\n\t\thost ??\n\t\t(() => {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(resolvedApiBase)\n\t\t\t\treturn url.host\n\t\t\t} catch {\n\t\t\t\treturn 'localhost:3000'\n\t\t\t}\n\t\t})()\n\n\t// Compute token endpoint from apiBase if not explicitly provided\n\tconst resolvedTokenEndpoint = tokenEndpoint || `${resolvedApiBase}/api/realtime/session`\n\n\t// Content with TicketExchangeGate wrapping the runtime\n\t// key={retryKey} on TicketExchangeGate forces fresh auth on retry\n\t// TicketExchangeGate performs HTTP ticket exchange BEFORE WebSocket connection\n\tconst content = (\n\t\t<MCPToolsProvider autoConnectLocal={autoConnectLocal} onToolsChange={onToolsChange}>\n\t\t\t<TicketExchangeGate\n\t\t\t\tkey={retryKey}\n\t\t\t\tapiBase={resolvedApiBase}\n\t\t\t\tauthToken={authToken}\n\t\t\t\tclientId={clientId}\n\t\t\t\tticketAuth={ticketAuth}\n\t\t\t\tanthropicApiKey={anthropicApiKey}\n\t\t\t>\n\t\t\t\t{(resolvedAuth) => (\n\t\t\t\t\t<AgentRuntime\n\t\t\t\t\t\tresolvedAuth={resolvedAuth}\n\t\t\t\t\t\thost={resolvedHost}\n\t\t\t\t\t\ttokenEndpoint={resolvedTokenEndpoint}\n\t\t\t\t\t\tenableDebugTools={enableDebugTools}\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)}\n\t\t\t</TicketExchangeGate>\n\t\t</MCPToolsProvider>\n\t)\n\n\treturn (\n\t\t<AuthErrorBoundary\n\t\t\tdashboardBaseUrl={dashboardBaseUrl}\n\t\t\tdocsBaseUrl={docsBaseUrl}\n\t\t\tonError={onAuthError}\n\t\t\tonRetryAuth={handleRetry}\n\t\t\tonClose={onClose}\n\t\t\tshowDebug={showErrorDebug}\n\t\t>\n\t\t\t<AgentUIProvider\n\t\t\t\topen={open}\n\t\t\t\tdefaultOpen={defaultOpen}\n\t\t\t\tdefaultMode={defaultMode}\n\t\t\t\tonOpenChange={onOpenChange}\n\t\t\t\tonModeChange={onModeChange}\n\t\t\t>\n\t\t\t\t{hasExclusions ? (\n\t\t\t\t\t<ToolExclusionProvider\n\t\t\t\t\t\texclude={excludeTools}\n\t\t\t\t\t\texcludeNames={excludeToolNames}\n\t\t\t\t\t\texcludePrefixes={excludeToolPrefixes}\n\t\t\t\t\t>\n\t\t\t\t\t\t{content}\n\t\t\t\t\t</ToolExclusionProvider>\n\t\t\t\t) : (\n\t\t\t\t\tcontent\n\t\t\t\t)}\n\t\t\t</AgentUIProvider>\n\t\t</AuthErrorBoundary>\n\t)\n}\n","'use client'\n\n/**\n * AgentThread - Self-contained thread UI component\n *\n * A full chat interface that fills its container. Includes all provider\n * infrastructure internally - no wrapper needed.\n *\n * @example Basic usage\n * ```tsx\n * import { AgentThread } from '@mcp-b/embedded-agent'\n *\n * function App() {\n * return (\n * <div className=\"h-screen\">\n * <AgentThread\n * apiBase=\"https://your-api.com\"\n * authToken={session.idToken}\n * />\n * </div>\n * )\n * }\n * ```\n *\n * @example With close button\n * ```tsx\n * <AgentThread\n * apiBase=\"https://your-api.com\"\n * authToken={session.idToken}\n * onClose={() => setShowAgent(false)}\n * />\n * ```\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport type { FC } from 'react'\nimport { ArrowLeft, Plus, X } from 'lucide-react'\n\nimport { Thread } from '../components/assistant-ui/thread'\nimport { TooltipIconButton } from '../components/assistant-ui/tooltip-icon-button'\nimport { AgentThreadList } from '../components/agent/AgentThreadList'\nimport { useAgent } from '../hooks/useAgent'\nimport { useAgentThreads } from '../hooks/useAgentThreads'\nimport { AgentProvider, type AgentProviderConfig } from '../providers/AgentProvider'\nimport { cn } from '../utils/cn'\n\n/** Screen types for internal navigation */\ntype Screen = 'thread-list' | 'thread-view'\n\n/**\n * Props for the AgentThread component.\n * Combines provider configuration with UI options.\n */\nexport interface AgentThreadProps extends AgentProviderConfig {\n\t/** Additional class name for the container */\n\tclassName?: string\n\n\t/** Callback when close button is clicked */\n\tonClose?: () => void\n}\n\n/**\n * AgentThread - Self-contained full thread UI\n *\n * Renders a complete chat interface with:\n * - Thread view with messages\n * - Thread list navigation\n * - New thread creation\n * - All provider infrastructure built-in\n */\nexport const AgentThread: FC<AgentThreadProps> = ({ className, onClose, ...providerConfig }) => {\n\treturn (\n\t\t<AgentProvider {...providerConfig} onClose={onClose}>\n\t\t\t<AgentThreadInner className={className} onClose={onClose} />\n\t\t</AgentProvider>\n\t)\n}\n\ninterface AgentThreadInnerProps {\n\tclassName?: string\n\tonClose?: () => void\n}\n\n/**\n * Inner component that renders the thread UI.\n * Must be inside AgentProvider to access hooks.\n */\nconst AgentThreadInner: FC<AgentThreadInnerProps> = ({ className, onClose }) => {\n\tconst { isLoading, threadIds, switchToNewThread } = useAgentThreads()\n\tconst agent = useAgent()\n\n\t// Internal screen navigation state\n\tconst [screen, setScreen] = useState<Screen>('thread-view')\n\n\t// Switch to thread list\n\tconst showThreadList = useCallback(() => {\n\t\tsetScreen('thread-list')\n\t}, [])\n\n\t// Switch to thread view\n\tconst showThreadView = useCallback(() => {\n\t\tsetScreen('thread-view')\n\t}, [])\n\n\t// Start new thread and switch to thread view\n\tconst startNewThread = useCallback(() => {\n\t\tsetScreen('thread-view')\n\t\tvoid agent.thread?.startNew()?.catch((error) => {\n\t\t\tconsole.error('[AgentThread] Failed to start new thread:', error)\n\t\t})\n\t}, [agent.thread])\n\n\t// Handle thread selection from list\n\tconst handleSelectThread = useCallback(() => {\n\t\tsetScreen('thread-view')\n\t}, [])\n\n\t// Auto-create first thread if none exist\n\tconst didAutoCreateThreadRef = useRef(false)\n\tuseEffect(() => {\n\t\tif (didAutoCreateThreadRef.current) return\n\t\tif (isLoading) return\n\t\tif (threadIds.length > 0) return\n\n\t\tdidAutoCreateThreadRef.current = true\n\t\ttry {\n\t\t\tswitchToNewThread()\n\t\t} catch (error) {\n\t\t\tconsole.error('[AgentThread] Failed to auto-create initial thread:', error)\n\t\t}\n\t}, [isLoading, threadIds.length, switchToNewThread])\n\n\t/** Glassmorphic button styles */\n\tconst glassmorphicButtonClass =\n\t\t'h-8 w-8 rounded-full border border-white/10 backdrop-blur-sm shadow-lg shadow-black/20 bg-[color-mix(in_oklab,rgb(var(--background))_20%,transparent)] [box-shadow:inset_0_1px_2px_0_rgba(255,255,255,0.15)] transition-all duration-200 hover:border-white/20 hover:bg-[color-mix(in_oklab,rgb(var(--background))_30%,transparent)]'\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\t'relative flex h-full w-full min-h-0 flex-col',\n\t\t\t\t'bg-background text-foreground',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t>\n\t\t\t{screen === 'thread-list' ? (\n\t\t\t\t<div className=\"relative flex min-h-0 flex-1 flex-col\">\n\t\t\t\t\t{/* Floating top bar for thread list */}\n\t\t\t\t\t<div className=\"absolute top-2 left-2 right-2 z-50 flex items-center gap-2\">\n\t\t\t\t\t\t{/* Left side - Back button */}\n\t\t\t\t\t\t<div className=\"flex gap-1\">\n\t\t\t\t\t\t\t<TooltipIconButton\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\tclassName={glassmorphicButtonClass}\n\t\t\t\t\t\t\t\tonClick={showThreadView}\n\t\t\t\t\t\t\t\ttooltip=\"Back to chat\"\n\t\t\t\t\t\t\t\tside=\"bottom\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<ArrowLeft className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t</TooltipIconButton>\n\t\t\t\t\t\t\t<TooltipIconButton\n\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\tclassName={glassmorphicButtonClass}\n\t\t\t\t\t\t\t\tonClick={startNewThread}\n\t\t\t\t\t\t\t\ttooltip=\"New chat\"\n\t\t\t\t\t\t\t\tside=\"bottom\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Plus className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t</TooltipIconButton>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{/* Right side - Close button */}\n\t\t\t\t\t\t{onClose && (\n\t\t\t\t\t\t\t<div className=\"ml-auto\">\n\t\t\t\t\t\t\t\t<TooltipIconButton\n\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\t\t\t\tclassName={glassmorphicButtonClass}\n\t\t\t\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\t\t\t\ttooltip=\"Close\"\n\t\t\t\t\t\t\t\t\tside=\"bottom\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<X className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t\t</TooltipIconButton>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className=\"flex min-h-0 flex-1 flex-col gap-3 p-3 pt-14\">\n\t\t\t\t\t\t<AgentThreadList className=\"flex-1\" onSelectThread={handleSelectThread} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<Thread\n\t\t\t\t\tonThreadsClick={showThreadList}\n\t\t\t\t\tonNewThread={startNewThread}\n\t\t\t\t\tonClose={onClose}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t)\n}\n","'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport type { FC, ReactNode } from 'react'\n\nimport { PortalContainerProvider } from '../../providers/PortalContainerProvider'\n\n/** Error state when Shadow DOM initialization fails */\ninterface ShadowRootError {\n\tmessage: string\n\tdetails?: string\n}\n\n/**\n * CSS Variable Theming\n *\n * External theming is handled via the CSS private/public variable pattern:\n * - Public variables (--char-*) are the external API that host apps SET\n * - Private variables (--_char-*) inherit from public OR use fallback defaults\n *\n * This allows CSS inheritance through Shadow DOM without JavaScript extraction.\n * Host apps can set variables on :root or any ancestor element:\n *\n * :root {\n * --char-color-primary: #8b5cf6;\n * --char-color-background: #1a1a1a;\n * }\n */\n\nexport interface ShadowRootProps {\n\t/** Children to render inside the shadow DOM */\n\tchildren: ReactNode\n\t/** CSS styles to inject into the shadow root */\n\tstyles: string\n\t/** Optional class name for the shadow host element */\n\tclassName?: string\n\t/** Mode for the shadow DOM (default: 'open') */\n\tmode?: 'open' | 'closed'\n}\n\n/**\n * ShadowRoot - Renders children inside an isolated shadow DOM\n *\n * This component creates a shadow DOM boundary that:\n * - Isolates styles from the main page (no style leakage in/out)\n * - Injects provided CSS directly into the shadow root\n * - Uses React portals to render children into the shadow DOM\n * - Fills its parent container (position: relative, width/height: 100%)\n *\n * Why shadow DOM?\n * - Prevents host page CSS from affecting the agent widget\n * - Prevents agent CSS from affecting the host page\n * - Perfect for embeddable widgets on third-party sites\n *\n * @example\n * ```tsx\n * import { WEBMCP_SHADOW_STYLES } from './generated/inline-styles'\n *\n * <ShadowRoot styles={WEBMCP_SHADOW_STYLES}>\n * <AgentPill />\n * </ShadowRoot>\n * ```\n */\nexport const ShadowRoot: FC<ShadowRootProps> = ({\n\tchildren,\n\tstyles,\n\tclassName,\n\tmode = 'open',\n}) => {\n\tconst hostRef = useRef<HTMLDivElement>(null)\n\tconst [portalContainer, setPortalContainer] = useState<Element | null>(null)\n\tconst [error, setError] = useState<ShadowRootError | null>(null)\n\n\t// Detect current theme from document\n\tconst detectTheme = useCallback(() => {\n\t\tconst html = document.documentElement\n\t\treturn (\n\t\t\thtml.classList.contains('dark') ||\n\t\t\t(!html.classList.contains('light') && window.matchMedia('(prefers-color-scheme: dark)').matches)\n\t\t)\n\t}, [])\n\n\t// Theme detection: observe host page's dark mode and sync to shadow host\n\tuseEffect(() => {\n\t\tconst host = hostRef.current\n\t\tif (!host) return\n\n\t\tconst syncTheme = () => {\n\t\t\tconst isDark = detectTheme()\n\t\t\thost.classList.toggle('dark', isDark)\n\t\t}\n\n\t\t// Initial sync\n\t\tsyncTheme()\n\n\t\t// Observe class changes on <html>\n\t\tconst observer = new MutationObserver(syncTheme)\n\t\tobserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })\n\n\t\t// Listen to system preference changes\n\t\tconst mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n\t\tmediaQuery.addEventListener('change', syncTheme)\n\n\t\treturn () => {\n\t\t\tobserver.disconnect()\n\t\t\tmediaQuery.removeEventListener('change', syncTheme)\n\t\t}\n\t}, [detectTheme])\n\n\tuseEffect(() => {\n\t\tconst host = hostRef.current\n\t\tif (!host) return\n\n\t\t// Check if shadow root already exists (strict mode / hot reload)\n\t\tlet shadow = host.shadowRoot\n\t\tif (!shadow) {\n\t\t\ttry {\n\t\t\t\tshadow = host.attachShadow({ mode })\n\t\t\t} catch (e) {\n\t\t\t\tconst errorMessage = 'Shadow DOM not supported in this environment.'\n\t\t\t\tconsole.error('[Char]', errorMessage, e)\n\t\t\t\tsetError({\n\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\tdetails: e instanceof Error ? e.message : 'The embedded agent requires Shadow DOM support to function properly.',\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Host CSS rules - fills parent container\n\t\tconst hostCSSRules = `\n\t\t\t:host {\n\t\t\t\tposition: relative !important;\n\t\t\t\tinset: auto !important;\n\t\t\t\tdisplay: block !important;\n\t\t\t\twidth: 100% !important;\n\t\t\t\theight: 100% !important;\n\t\t\t\tpointer-events: auto !important;\n\t\t\t}\n\t\t\t[data-webmcp-container] {\n\t\t\t\tdisplay: block !important;\n\t\t\t\twidth: 100% !important;\n\t\t\t\theight: 100% !important;\n\t\t\t}\n\t\t`\n\n\t\t// Create or update the style element\n\t\tlet styleElement = shadow.querySelector('style[data-webmcp-styles]')\n\t\tif (!styleElement) {\n\t\t\tstyleElement = document.createElement('style')\n\t\t\tstyleElement.setAttribute('data-webmcp-styles', '')\n\t\t\tshadow.insertBefore(styleElement, shadow.firstChild)\n\t\t}\n\t\t// CSS variables are handled via the private/public pattern in globals.css\n\t\t// No JavaScript extraction needed - CSS inheritance handles it\n\t\tstyleElement.textContent = hostCSSRules + styles\n\n\t\t// Create container for React content if it doesn't exist\n\t\tlet container = shadow.querySelector('[data-webmcp-container]')\n\t\tif (!container) {\n\t\t\tcontainer = document.createElement('div')\n\t\t\tcontainer.setAttribute('data-webmcp-container', '')\n\t\t\tshadow.appendChild(container)\n\t\t}\n\n\t\tsetPortalContainer(container)\n\t}, [mode, styles])\n\n\t// Show error UI if Shadow DOM initialization failed\n\tif (error) {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tref={hostRef}\n\t\t\t\tclassName={className}\n\t\t\t\trole=\"alert\"\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: 'flex',\n\t\t\t\t\talignItems: 'center',\n\t\t\t\t\tjustifyContent: 'center',\n\t\t\t\t\tpadding: '1rem',\n\t\t\t\t\tbackgroundColor: 'rgba(239, 68, 68, 0.1)',\n\t\t\t\t\tborder: '1px solid rgba(239, 68, 68, 0.2)',\n\t\t\t\t\tborderRadius: '0.5rem',\n\t\t\t\t\tcolor: '#ef4444',\n\t\t\t\t\tfontSize: '0.875rem',\n\t\t\t\t\ttextAlign: 'center',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div>\n\t\t\t\t\t<p style={{ fontWeight: 500, marginBottom: '0.25rem' }}>{error.message}</p>\n\t\t\t\t\t{error.details && (\n\t\t\t\t\t\t<p style={{ fontSize: '0.75rem', opacity: 0.8 }}>{error.details}</p>\n\t\t\t\t\t)}\n\t\t\t\t\t<p style={{ fontSize: '0.75rem', marginTop: '0.5rem', opacity: 0.7 }}>\n\t\t\t\t\t\tPlease use a modern browser to access this feature.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t)\n\t}\n\n\treturn (\n\t\t<div ref={hostRef} className={className}>\n\t\t\t{portalContainer && createPortal(\n\t\t\t\t<PortalContainerProvider container={portalContainer as HTMLElement}>\n\t\t\t\t\t{children}\n\t\t\t\t</PortalContainerProvider>,\n\t\t\t\tportalContainer\n\t\t\t)}\n\t\t</div>\n\t)\n}\n\nexport default ShadowRoot\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 * Styles are injected into the ShadowRoot for complete isolation from host page.\n */\n\n/**\n * CSS styles optimized for shadow DOM injection.\n * Use this with the ShadowRoot component for complete style isolation.\n *\n * Features:\n * - No body styles (shadow DOM doesn't have a body element)\n * - No @property declarations (not supported in shadow DOM)\n * - Uses :host selector for theming (in addition to :root)\n */\nexport const WEBMCP_SHADOW_STYLES = \"/*! tailwindcss v4.1.18 | 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-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-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-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--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-red-600:oklch(57.7% .245 27.325);--color-orange-400:oklch(75% .183 55.934);--color-orange-500:oklch(70.5% .213 47.604);--color-orange-600:oklch(64.6% .222 41.116);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-indigo-500:oklch(58.5% .233 277.117);--color-purple-600:oklch(55.8% .288 302.321);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-3xl:48rem;--container-6xl:72rem;--text-xs--line-height:calc(1/.75);--text-sm--line-height:calc(1.25/.875);--text-base:var(--_char-font-size-base);--text-base--line-height:calc(1.5/1);--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-widest:.1em;--leading-tight:1.25;--leading-normal:1.5;--leading-relaxed:1.625;--radius-xs:.125rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--_char-font-sans);--default-mono-font-family:var(--_char-font-mono);--color-background:var(--_char-color-background)}}@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}:host,:root{--_char-color-background:var(--char-color-background,oklch(100% 0 0));--_char-color-foreground:var(--char-color-foreground,oklch(14.1% .005 285.823));--_char-color-primary:var(--char-color-primary,oklch(21% .006 285.885));--_char-color-primary-foreground:var(--char-color-primary-foreground,oklch(98.5% 0 0));--_char-color-muted:var(--char-color-muted,oklch(96.7% .001 286.375));--_char-color-muted-foreground:var(--char-color-muted-foreground,oklch(55.2% .016 285.938));--_char-color-border:var(--char-color-border,oklch(92% .004 286.32));--_char-color-success:var(--char-color-success,oklch(70% .2 145));--_char-color-warning:var(--char-color-warning,oklch(75% .15 85));--_char-color-error:var(--char-color-error,oklch(65% .25 25));--_char-color-card:var(--_char-color-background);--_char-color-card-foreground:var(--_char-color-foreground);--_char-color-popover:var(--_char-color-background);--_char-color-popover-foreground:var(--_char-color-foreground);--_char-color-secondary:var(--_char-color-muted);--_char-color-secondary-foreground:var(--_char-color-foreground);--_char-color-accent:var(--_char-color-muted);--_char-color-accent-foreground:var(--_char-color-foreground);--_char-color-destructive:var(--_char-color-error);--_char-color-destructive-foreground:var(--_char-color-primary-foreground);--_char-color-input:var(--char-color-input,var(--_char-color-border));--_char-color-ring:var(--char-color-ring,var(--_char-color-muted-foreground));--_char-user-bubble-bg:var(--char-user-bubble-bg,var(--_char-color-muted));--_char-user-bubble-text:var(--char-user-bubble-text,var(--_char-color-foreground));--_char-assistant-bubble-bg:var(--char-assistant-bubble-bg,transparent);--_char-assistant-bubble-text:var(--char-assistant-bubble-text,var(--_char-color-foreground));--_char-composer-bg:var(--char-composer-bg,var(--_char-color-background));--_char-composer-border:var(--char-composer-border,var(--_char-color-input));--_char-composer-text:var(--char-composer-text,var(--_char-color-foreground));--_char-composer-placeholder:var(--char-composer-placeholder,var(--_char-color-muted-foreground));--_char-composer-button-bg:var(--char-composer-button-bg,var(--_char-color-primary));--_char-composer-button-text:var(--char-composer-button-text,var(--_char-color-primary-foreground));--_char-tool-bg:var(--char-tool-bg,var(--_char-color-muted));--_char-tool-border:var(--char-tool-border,var(--_char-color-border));--_char-tool-text:var(--char-tool-text,var(--_char-color-foreground));--_char-tool-header-bg:var(--char-tool-header-bg,var(--_char-color-muted));--_char-tool-approve-bg:var(--char-tool-approve-bg,var(--_char-color-primary));--_char-tool-approve-text:var(--char-tool-approve-text,var(--_char-color-primary-foreground));--_char-tool-deny-bg:var(--char-tool-deny-bg,transparent);--_char-tool-deny-text:var(--char-tool-deny-text,var(--_char-color-muted-foreground));--_char-code-bg:var(--char-code-bg,oklch(14.1% .005 285.823));--_char-code-text:var(--char-code-text,oklch(98.5% 0 0));--_char-code-header-bg:var(--char-code-header-bg,var(--_char-color-muted-foreground))}@supports (color:color-mix(in lab, red, red)){:host,:root{--_char-code-header-bg:var(--char-code-header-bg,color-mix(in oklch,var(--_char-color-muted-foreground),transparent 85%))}}:host,:root{--_char-radius:var(--char-radius,.75rem);--_char-radius-sm:calc(var(--_char-radius)*.5);--_char-radius-md:calc(var(--_char-radius)*.67);--_char-radius-lg:var(--_char-radius);--_char-radius-xl:calc(var(--_char-radius)*1.33);--_char-radius-2xl:calc(var(--_char-radius)*1.67);--_char-radius-3xl:calc(var(--_char-radius)*2);--_char-radius-full:9999px;--_char-spacing-unit:.25rem;--_char-font-sans:var(--char-font-sans,ui-sans-serif,system-ui,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\",\\\"Noto Color Emoji\\\");--_char-font-mono:var(--char-font-mono,ui-monospace,SFMono-Regular,\\\"SF Mono\\\",Menlo,Consolas,monospace);--_char-font-size-xs:.75rem;--_char-font-size-sm:.8125rem;--_char-font-size-base:.875rem;--_char-font-size-lg:1rem;--_char-duration-fast:.15s;--_char-duration-normal:.25s;--_char-duration-slow:.4s;--_char-easing-default:cubic-bezier(.4,0,.2,1);--_char-easing-spring:cubic-bezier(.34,1.56,.64,1);--_char-z-base:0;--_char-z-content:10;--_char-z-overlay:50;--_char-z-max:2147480000;--_char-shadow-sm:0 1px 2px #0000000d;--_char-shadow-md:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--_char-shadow-lg:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--_char-blur-sm:8px;--_char-blur-md:12px;--_char-blur-lg:20px}:host(.dark),.dark{--_char-color-background:var(--char-color-background,oklch(14.1% .005 285.823));--_char-color-foreground:var(--char-color-foreground,oklch(98.5% 0 0));--_char-color-primary:var(--char-color-primary,oklch(92% .004 286.32));--_char-color-primary-foreground:var(--char-color-primary-foreground,oklch(21% .006 285.885));--_char-color-muted:var(--char-color-muted,oklch(27.4% .006 286.033));--_char-color-muted-foreground:var(--char-color-muted-foreground,oklch(70.5% .015 286.067));--_char-color-border:var(--char-color-border,oklch(100% 0 0/.1));--_char-color-input:var(--char-color-input,oklch(100% 0 0/.15));--_char-color-ring:var(--char-color-ring,oklch(55.2% .016 285.938));--_char-color-success:var(--char-color-success,oklch(75% .18 145));--_char-color-warning:var(--char-color-warning,oklch(80% .14 85));--_char-color-error:var(--char-color-error,oklch(70% .22 25))}*{border-color:var(--_char-color-border);outline-color:var(--_char-color-ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklch,var(--_char-color-ring),transparent 50%)}}}@layer components{.char-animate-fade-in-up{opacity:0;animation:.5s ease-out forwards char-fade-in-up}.char-animate-gradient-shift{background-size:200% 200%;animation:20s ease-in-out infinite char-gradient-shift}.char-animate-float-slow{animation:20s ease-in-out infinite char-float}.char-animate-float-delayed{animation:25s ease-in-out 5s infinite char-float-delayed}.char-animate-shimmer{animation:2s linear infinite char-shimmer}.char-animate-pulse-success{animation:.6s ease-out char-pulse-success}.char-animate-shake{animation:.3s ease-out char-shake}.char-animate-pulse-glow{animation:2s ease-in-out infinite char-pulse-glow}.char-animate-gradient-x{animation:8s ease-in-out infinite char-gradient-x}.char-transition-spring{transition:all var(--_char-duration-slow)var(--_char-easing-spring)}.char-transition-smooth{transition:all var(--_char-duration-normal)var(--_char-easing-default)}.char-app-shell{z-index:var(--_char-z-base);background-color:var(--_char-color-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 .char-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)}.char-app-shell:before,.char-app-shell:after{content:\\\"\\\";pointer-events:none;border-radius:var(--_char-radius-full);filter:blur(32px);opacity:.6;z-index:-1;position:absolute;inset:auto}.char-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}.char-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}.char-toolbar-surface{border-top:1px solid var(--_char-color-border);background:linear-gradient(to right,var(--_char-color-background),var(--_char-color-background),var(--_char-color-background))}@supports (color:color-mix(in lab, red, red)){.char-toolbar-surface{background:linear-gradient(to right,var(--_char-color-background),color-mix(in oklch,var(--_char-color-background),transparent 5%),var(--_char-color-background))}}.char-toolbar-surface{-webkit-backdrop-filter:blur(var(--_char-blur-md));backdrop-filter:blur(var(--_char-blur-md))}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.char-toolbar-surface{background:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.char-toolbar-surface{background:color-mix(in oklch,var(--_char-color-background),transparent 20%)}}}.char-toolbar-surface-top{border-bottom:1px solid var(--_char-color-border);background:linear-gradient(to right,var(--_char-color-background),var(--_char-color-background),var(--_char-color-background))}@supports (color:color-mix(in lab, red, red)){.char-toolbar-surface-top{background:linear-gradient(to right,var(--_char-color-background),color-mix(in oklch,var(--_char-color-background),transparent 5%),var(--_char-color-background))}}.char-toolbar-surface-top{-webkit-backdrop-filter:blur(var(--_char-blur-md));backdrop-filter:blur(var(--_char-blur-md))}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.char-toolbar-surface-top{background:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.char-toolbar-surface-top{background:color-mix(in oklch,var(--_char-color-background),transparent 20%)}}}.char-toolbar-inner{justify-content:space-between;align-items:center;padding:.5rem .75rem;display:flex}.char-toolbar-card{background:var(--_char-color-card);justify-content:space-between;align-items:center;gap:.5rem;display:flex}@supports (color:color-mix(in lab, red, red)){.char-toolbar-card{background:color-mix(in oklch,var(--_char-color-card),transparent 60%)}}.char-toolbar-card{border:1px solid var(--_char-color-border);border-radius:var(--_char-radius-lg);padding:.5rem .75rem}.char-toolbar-group{align-items:center;gap:.25rem;display:flex}.char-btn-toolbar-primary{border-radius:var(--_char-radius-lg);background:linear-gradient(to right,var(--_char-color-primary),var(--_char-color-primary));align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;display:flex}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-primary{background:linear-gradient(to right,color-mix(in oklch,var(--_char-color-primary),transparent 95%),color-mix(in oklch,var(--_char-color-primary),transparent 90%))}}.char-btn-toolbar-primary{border:1px solid var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-primary{border:1px solid color-mix(in oklch,var(--_char-color-primary),transparent 80%)}}.char-btn-toolbar-primary{transition:all var(--_char-duration-fast)}.char-btn-toolbar-primary:hover{background:linear-gradient(to right,var(--_char-color-primary),var(--_char-color-primary))}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-primary:hover{background:linear-gradient(to right,color-mix(in oklch,var(--_char-color-primary),transparent 90%),color-mix(in oklch,var(--_char-color-primary),transparent 80%))}}.char-btn-toolbar-icon-primary{border-radius:var(--_char-radius-full);background:linear-gradient(to bottom right,var(--_char-color-primary),var(--_char-color-primary));width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-icon-primary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--_char-color-primary),transparent 90%),color-mix(in oklch,var(--_char-color-primary),transparent 80%))}}.char-btn-toolbar-icon-primary{border:1px solid var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-icon-primary{border:1px solid color-mix(in oklch,var(--_char-color-primary),transparent 70%)}}.char-btn-toolbar-icon-primary{box-shadow:var(--_char-shadow-sm);transition:all var(--_char-duration-fast)}.char-btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,var(--_char-color-primary),var(--_char-color-primary))}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--_char-color-primary),transparent 80%),color-mix(in oklch,var(--_char-color-primary),transparent 70%))}}.char-btn-toolbar-icon-secondary{border-radius:var(--_char-radius-full);background:linear-gradient(to bottom right,var(--_char-color-secondary),var(--_char-color-secondary));width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--_char-color-secondary),transparent 90%),color-mix(in oklch,var(--_char-color-secondary),transparent 80%))}}.char-btn-toolbar-icon-secondary{border:1px solid var(--_char-color-secondary)}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-icon-secondary{border:1px solid color-mix(in oklch,var(--_char-color-secondary),transparent 70%)}}.char-btn-toolbar-icon-secondary{box-shadow:var(--_char-shadow-sm);transition:all var(--_char-duration-fast)}.char-btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,var(--_char-color-secondary),var(--_char-color-secondary))}@supports (color:color-mix(in lab, red, red)){.char-btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--_char-color-secondary),transparent 80%),color-mix(in oklch,var(--_char-color-secondary),transparent 70%))}}.char-badge-compact{height:1.25rem;padding:0 .5rem;font-size:10px}.char-badge-mini{height:1rem;padding:0 .375rem;font-size:10px}.char-shimmer{background:linear-gradient(90deg,transparent,var(--_char-color-foreground),transparent);animation:3s linear infinite char-shimmer}@supports (color:color-mix(in lab, red, red)){.char-shimmer{background:linear-gradient(90deg,transparent,color-mix(in oklch,var(--_char-color-foreground),transparent 90%),transparent)}}.char-shimmer{background-size:1000px 100%}.char-gradient-text{background:linear-gradient(to right,var(--_char-color-foreground),var(--_char-color-foreground))}@supports (color:color-mix(in lab, red, red)){.char-gradient-text{background:linear-gradient(to right,var(--_char-color-foreground),color-mix(in oklch,var(--_char-color-foreground),transparent 30%))}}.char-gradient-text{-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.char-glass{background:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.char-glass{background:color-mix(in oklch,var(--_char-color-background),transparent 50%)}}.char-glass{-webkit-backdrop-filter:blur(var(--_char-blur-md));backdrop-filter:blur(var(--_char-blur-md));border:1px solid var(--_char-color-border)}@supports (color:color-mix(in lab, red, red)){.char-glass{border:1px solid color-mix(in oklch,var(--_char-color-border),transparent 50%)}}.char-tool-card{transition:all .3s ease-out}.char-tool-card:hover{box-shadow:var(--_char-shadow-lg);transform:scale(1.02)}.char-tool-border-calling{position:relative;overflow:hidden}.char-tool-border-calling:before{content:\\\"\\\";background:conic-gradient(from 0deg,transparent 0deg,transparent 60deg,var(--_char-color-primary)90deg,var(--_char-color-primary)120deg,var(--_char-color-primary)150deg,transparent 180deg,transparent 360deg);position:absolute;inset:-50%}@supports (color:color-mix(in lab, red, red)){.char-tool-border-calling:before{background:conic-gradient(from 0deg,transparent 0deg,transparent 60deg,color-mix(in oklch,var(--_char-color-primary),transparent 50%)90deg,color-mix(in oklch,var(--_char-color-primary),transparent 30%)120deg,color-mix(in oklch,var(--_char-color-primary),transparent 50%)150deg,transparent 180deg,transparent 360deg)}}.char-tool-border-calling:before{animation:1.5s linear infinite char-border-rotate}.char-tool-border-success{background:var(--_char-color-success)}@supports (color:color-mix(in lab, red, red)){.char-tool-border-success{background:color-mix(in oklch,var(--_char-color-success),transparent 60%)}}.char-tool-border-success{box-shadow:0 0 12px var(--_char-color-success),inset 0 0 8px var(--_char-color-success)}@supports (color:color-mix(in lab, red, red)){.char-tool-border-success{box-shadow:0 0 12px color-mix(in oklch,var(--_char-color-success),transparent 70%),inset 0 0 8px color-mix(in oklch,var(--_char-color-success),transparent 90%)}}.char-tool-border-error{background:var(--_char-color-error)}@supports (color:color-mix(in lab, red, red)){.char-tool-border-error{background:color-mix(in oklch,var(--_char-color-error),transparent 60%)}}.char-tool-border-error{box-shadow:0 0 12px var(--_char-color-error),inset 0 0 8px var(--_char-color-error)}@supports (color:color-mix(in lab, red, red)){.char-tool-border-error{box-shadow:0 0 12px color-mix(in oklch,var(--_char-color-error),transparent 70%),inset 0 0 8px color-mix(in oklch,var(--_char-color-error),transparent 90%)}}.char-scrollbar-thin{scrollbar-width:thin;scrollbar-color:var(--_char-color-primary)transparent}@supports (color:color-mix(in lab, red, red)){.char-scrollbar-thin{scrollbar-color:color-mix(in oklch,var(--_char-color-primary),transparent 80%)transparent}}.char-scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.char-scrollbar-thin::-webkit-scrollbar-track{background:0 0}.char-scrollbar-thin::-webkit-scrollbar-thumb{background-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.char-scrollbar-thin::-webkit-scrollbar-thumb{background-color:color-mix(in oklch,var(--_char-color-primary),transparent 80%)}}.char-scrollbar-thin::-webkit-scrollbar-thumb{border-radius:3px}.char-scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.char-scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:color-mix(in oklch,var(--_char-color-primary),transparent 70%)}}.char-glass-pill{background:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill{background:color-mix(in oklch,var(--_char-color-background),transparent 15%)}}.char-glass-pill{-webkit-backdrop-filter:blur(var(--_char-blur-lg))saturate(150%);box-shadow:0 4px 16px var(--_char-color-foreground),inset 0 .5px 0 var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill{box-shadow:0 4px 16px color-mix(in oklch,var(--_char-color-foreground),transparent 80%),inset 0 .5px 0 color-mix(in oklch,var(--_char-color-foreground),transparent 92%)}}.char-glass-pill{border:1px solid var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill{border:1px solid color-mix(in oklch,var(--_char-color-foreground),transparent 94%)}}.char-glass-pill:before{content:\\\"\\\";border-radius:inherit;background:linear-gradient(180deg,var(--_char-color-foreground)0%,transparent 40%);position:absolute;inset:0}@supports (color:color-mix(in lab, red, red)){.char-glass-pill:before{background:linear-gradient(180deg,color-mix(in oklch,var(--_char-color-foreground),transparent 96%)0%,transparent 40%)}}.char-glass-pill:before{pointer-events:none;z-index:1}.char-glass-pill-collapsed{background:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill-collapsed{background:color-mix(in oklch,var(--_char-color-background),transparent 15%)}}.char-glass-pill-collapsed{-webkit-backdrop-filter:blur(var(--_char-blur-lg))saturate(150%);box-shadow:0 2px 8px var(--_char-color-foreground),inset 0 .5px 0 var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill-collapsed{box-shadow:0 2px 8px color-mix(in oklch,var(--_char-color-foreground),transparent 80%),inset 0 .5px 0 color-mix(in oklch,var(--_char-color-foreground),transparent 92%)}}.char-glass-pill-collapsed{border:1px solid var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill-collapsed{border:1px solid color-mix(in oklch,var(--_char-color-foreground),transparent 94%)}}.char-glass-pill-hovered{background:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill-hovered{background:color-mix(in oklch,var(--_char-color-background),transparent 20%)}}.char-glass-pill-hovered{-webkit-backdrop-filter:blur(16px)saturate(140%);box-shadow:0 2px 12px var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill-hovered{box-shadow:0 2px 12px color-mix(in oklch,var(--_char-color-foreground),transparent 82%)}}.char-glass-pill-hovered{border:1px solid var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.char-glass-pill-hovered{border:1px solid color-mix(in oklch,var(--_char-color-foreground),transparent 94%)}}.char-glass-shimmer{background:linear-gradient(90deg,var(--_char-color-foreground)0%,var(--_char-color-foreground)50%,var(--_char-color-foreground)100%)}@supports (color:color-mix(in lab, red, red)){.char-glass-shimmer{background:linear-gradient(90deg,color-mix(in oklch,var(--_char-color-foreground),transparent 92%)0%,color-mix(in oklch,var(--_char-color-foreground),transparent 85%)50%,color-mix(in oklch,var(--_char-color-foreground),transparent 92%)100%)}}.char-glass-shimmer{background-size:200% 100%;animation:4s ease-in-out infinite char-glass-shimmer}.char-scroll-touch{-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.char-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)}.char-pb-safe{padding-bottom:env(safe-area-inset-bottom,0px)}.char-mb-safe{margin-bottom:env(safe-area-inset-bottom,0px)}.char-bottom-safe{bottom:max(1rem,env(safe-area-inset-bottom,0px))}@supports (padding-bottom:env(safe-area-inset-bottom)){.char-pill-safe-bottom{padding-bottom:calc(env(safe-area-inset-bottom,0px) + .5rem)}}}@layer utilities{.\\\\@container\\\\/card-header{container:card-header/inline-size}.\\\\@container{container-type:inline-size}.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.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}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.inset-x-0{inset-inline:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.-top-12{top:calc(var(--spacing)*-12)}.top-0{top:calc(var(--spacing)*0)}.top-1\\\\.5{top:calc(var(--spacing)*1.5)}.top-1\\\\/2{top:50%}.top-2{top:calc(var(--spacing)*2)}.top-4{top:calc(var(--spacing)*4)}.top-\\\\[50\\\\%\\\\]{top:50%}.-right-0\\\\.5{right:calc(var(--spacing)*-.5)}.right-0{right:calc(var(--spacing)*0)}.right-1\\\\.5{right:calc(var(--spacing)*1.5)}.right-2{right:calc(var(--spacing)*2)}.right-4{right:calc(var(--spacing)*4)}.-bottom-0\\\\.5{bottom:calc(var(--spacing)*-.5)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-9{bottom:calc(var(--spacing)*9)}.left-0{left:calc(var(--spacing)*0)}.left-1\\\\/2{left:50%}.left-2{left:calc(var(--spacing)*2)}.left-\\\\[50\\\\%\\\\]{left:50%}.z-0{z-index:0}.z-10{z-index:10}.z-50{z-index:50}.col-span-1{grid-column:span 1/span 1}.col-span-5{grid-column:span 5/span 5}.col-span-6{grid-column:span 6/span 6}.col-span-12{grid-column:span 12/span 12}.col-span-full{grid-column:1/-1}.col-start-1{grid-column-start:1}.col-start-2{grid-column-start:2}.col-start-3{grid-column-start:3}.row-span-2{grid-row:span 2/span 2}.row-start-1{grid-row-start:1}.row-start-2{grid-row-start:2}.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-0{margin:calc(var(--spacing)*0)}.-mx-1{margin-inline:calc(var(--spacing)*-1)}.mx-2{margin-inline:calc(var(--spacing)*2)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing)*1)}.my-2{margin-block:calc(var(--spacing)*2)}.my-3{margin-block:calc(var(--spacing)*3)}.my-4{margin-block:calc(var(--spacing)*4)}.my-5{margin-block:calc(var(--spacing)*5)}.my-auto{margin-block:auto}.mt-0\\\\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-5{margin-top:calc(var(--spacing)*5)}.mt-6{margin-top:calc(var(--spacing)*6)}.mt-auto{margin-top:auto}.mr-1{margin-right:calc(var(--spacing)*1)}.mr-1\\\\.5{margin-right:calc(var(--spacing)*1.5)}.mr-2{margin-right:calc(var(--spacing)*2)}.-mb-2{margin-bottom:calc(var(--spacing)*-2)}.mb-0{margin-bottom:calc(var(--spacing)*0)}.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)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.-ml-1{margin-left:calc(var(--spacing)*-1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-6{margin-left:calc(var(--spacing)*6)}.ml-\\\\[3px\\\\]{margin-left:3px}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.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}.\\\\!inline{display:inline!important}.block{display:block}.contents{display:contents}.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}.field-sizing-content{field-sizing:content}.aspect-square{aspect-ratio:1}.size-\\\\(--cell-size\\\\){width:var(--cell-size);height:var(--cell-size)}.size-1\\\\.5{width:calc(var(--spacing)*1.5);height:calc(var(--spacing)*1.5)}.size-2{width:calc(var(--spacing)*2);height:calc(var(--spacing)*2)}.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-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.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-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.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-12{width:calc(var(--spacing)*12);height:calc(var(--spacing)*12)}.size-14{width:calc(var(--spacing)*14);height:calc(var(--spacing)*14)}.size-\\\\[34px\\\\]{width:34px;height:34px}.size-auto{width:auto;height:auto}.size-full{width:100%;height:100%}.h-\\\\(--cell-size\\\\){height:var(--cell-size)}.h-1{height:calc(var(--spacing)*1)}.h-2{height:calc(var(--spacing)*2)}.h-3{height:calc(var(--spacing)*3)}.h-3\\\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-16{height:calc(var(--spacing)*16)}.h-24{height:calc(var(--spacing)*24)}.h-\\\\[var\\\\(--radix-select-trigger-height\\\\)\\\\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-\\\\(--radix-dropdown-menu-content-available-height\\\\){max-height:var(--radix-dropdown-menu-content-available-height)}.max-h-\\\\(--radix-select-content-available-height\\\\){max-height:var(--radix-select-content-available-height)}.max-h-20{max-height:calc(var(--spacing)*20)}.max-h-24{max-height:calc(var(--spacing)*24)}.max-h-28{max-height:calc(var(--spacing)*28)}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-64{max-height:calc(var(--spacing)*64)}.max-h-\\\\[80dvh\\\\]{max-height:80dvh}.max-h-\\\\[80vh\\\\]{max-height:80vh}.max-h-\\\\[90vh\\\\]{max-height:90vh}.max-h-\\\\[300px\\\\]{max-height:300px}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-4{min-height:calc(var(--spacing)*4)}.min-h-14{min-height:calc(var(--spacing)*14)}.min-h-16{min-height:calc(var(--spacing)*16)}.min-h-40{min-height:calc(var(--spacing)*40)}.min-h-\\\\[80px\\\\]{min-height:80px}.min-h-screen{min-height:100vh}.w-\\\\(--cell-size\\\\){width:var(--cell-size)}.w-1\\\\/2{width:50%}.w-2{width:calc(var(--spacing)*2)}.w-2\\\\/3{width:66.6667%}.w-3{width:calc(var(--spacing)*3)}.w-3\\\\.5{width:calc(var(--spacing)*3.5)}.w-3\\\\/4{width:75%}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-12{width:calc(var(--spacing)*12)}.w-16{width:calc(var(--spacing)*16)}.w-20{width:calc(var(--spacing)*20)}.w-24{width:calc(var(--spacing)*24)}.w-32{width:calc(var(--spacing)*32)}.w-48{width:calc(var(--spacing)*48)}.w-64{width:calc(var(--spacing)*64)}.w-72{width:calc(var(--spacing)*72)}.w-80{width:calc(var(--spacing)*80)}.w-\\\\[70px\\\\]{width:70px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.max-w-\\\\(--thread-max-width\\\\){max-width:var(--thread-max-width)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\\\\[70\\\\%\\\\]{max-width:70%}.max-w-\\\\[75\\\\%\\\\]{max-width:75%}.max-w-\\\\[140px\\\\]{max-width:140px}.max-w-\\\\[calc\\\\(100\\\\%-2rem\\\\)\\\\]{max-width:calc(100% - 2rem)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-sm{max-width:var(--container-sm)}.min-w-\\\\(--cell-size\\\\){min-width:var(--cell-size)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-4{min-width:calc(var(--spacing)*4)}.min-w-\\\\[8rem\\\\]{min-width:8rem}.min-w-\\\\[var\\\\(--radix-select-trigger-width\\\\)\\\\]{min-width:var(--radix-select-trigger-width)}.flex-1{flex:1}.flex-none{flex:none}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.border-collapse{border-collapse:collapse}.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-dropdown-menu-content-transform-origin\\\\){transform-origin:var(--radix-dropdown-menu-content-transform-origin)}.origin-\\\\(--radix-popover-content-transform-origin\\\\){transform-origin:var(--radix-popover-content-transform-origin)}.origin-\\\\(--radix-select-content-transform-origin\\\\){transform-origin:var(--radix-select-content-transform-origin)}.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)}.rotate-45{rotate:45deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.transform-gpu{transform:translateZ(0)var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-collapsible-down{animation:collapsible-down var(--tw-animation-duration,var(--tw-duration,.2s))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.animate-collapsible-up{animation:collapsible-up var(--tw-animation-duration,var(--tw-duration,.2s))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.animate-in{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.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)}.scroll-my-1{scroll-margin-block:calc(var(--spacing)*1)}.scroll-py-1{scroll-padding-block:calc(var(--spacing)*1)}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.auto-rows-auto{grid-auto-rows:auto}.auto-rows-min{grid-auto-rows:min-content}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-\\\\[0_1fr\\\\]{grid-template-columns:0 1fr}.grid-cols-\\\\[minmax\\\\(72px\\\\,1fr\\\\)_auto\\\\]{grid-template-columns:minmax(72px,1fr) auto}.grid-rows-\\\\[0fr\\\\]{grid-template-rows:0fr}.grid-rows-\\\\[1fr\\\\]{grid-template-rows:1fr}.grid-rows-\\\\[auto_auto\\\\]{grid-template-rows:auto auto}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.content-start{align-content:flex-start}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.justify-items-end{justify-items:end}.justify-items-start{justify-items:start}.gap-0\\\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-0\\\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}: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-1\\\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1.5)*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-2\\\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*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)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}.gap-y-0\\\\.5{row-gap:calc(var(--spacing)*.5)}.gap-y-2{row-gap:calc(var(--spacing)*2)}.self-center{align-self:center}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.scroll-smooth{scroll-behavior:smooth}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--_char-radius-2xl)}.rounded-\\\\[2px\\\\]{border-radius:2px}.rounded-\\\\[4px\\\\]{border-radius:4px}.rounded-\\\\[14px\\\\]{border-radius:14px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--_char-radius-lg)}.rounded-md{border-radius:var(--_char-radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--_char-radius-sm)}.rounded-xl{border-radius:var(--_char-radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-t-lg{border-top-left-radius:var(--_char-radius-lg);border-top-right-radius:var(--_char-radius-lg)}.rounded-t-none\\\\!{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-l-md{border-top-left-radius:var(--_char-radius-md);border-bottom-left-radius:var(--_char-radius-md)}.rounded-r-md{border-top-right-radius:var(--_char-radius-md);border-bottom-right-radius:var(--_char-radius-md)}.rounded-b-lg{border-bottom-right-radius:var(--_char-radius-lg);border-bottom-left-radius:var(--_char-radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.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-dashed{--tw-border-style:dashed;border-style:dashed}.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\\\\/40{border-color:#f99c0066}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\\\/40{border-color:color-mix(in oklab,var(--color-amber-500)40%,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\\\\/40{border-color:#3080ff66}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\\\/40{border-color:color-mix(in oklab,var(--color-blue-500)40%,transparent)}}.border-border,.border-border\\\\/50{border-color:var(--_char-color-border)}@supports (color:color-mix(in lab, red, red)){.border-border\\\\/50{border-color:color-mix(in oklab,var(--_char-color-border)50%,transparent)}}.border-border\\\\/60{border-color:var(--_char-color-border)}@supports (color:color-mix(in lab, red, red)){.border-border\\\\/60{border-color:color-mix(in oklab,var(--_char-color-border)60%,transparent)}}.border-border\\\\/70{border-color:var(--_char-color-border)}@supports (color:color-mix(in lab, red, red)){.border-border\\\\/70{border-color:color-mix(in oklab,var(--_char-color-border)70%,transparent)}}.border-composer-border{border-color:var(--_char-composer-border)}.border-destructive,.border-destructive\\\\/20{border-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\\\\/20{border-color:color-mix(in oklab,var(--_char-color-destructive)20%,transparent)}}.border-destructive\\\\/50{border-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\\\\/50{border-color:color-mix(in oklab,var(--_char-color-destructive)50%,transparent)}}.border-emerald-500\\\\/20{border-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\\\\/20{border-color:color-mix(in oklab,var(--color-emerald-500)20%,transparent)}}.border-emerald-500\\\\/30{border-color:#00bb7f4d}@supports (color:color-mix(in lab, red, red)){.border-emerald-500\\\\/30{border-color:color-mix(in oklab,var(--color-emerald-500)30%,transparent)}}.border-foreground\\\\/20{border-color:var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.border-foreground\\\\/20{border-color:color-mix(in oklab,var(--_char-color-foreground)20%,transparent)}}.border-gray-200{border-color:var(--color-gray-200)}.border-input{border-color:var(--_char-color-input)}.border-muted-foreground\\\\/20{border-color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-muted-foreground\\\\/20{border-color:color-mix(in oklab,var(--_char-color-muted-foreground)20%,transparent)}}.border-muted-foreground\\\\/30{border-color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-muted-foreground\\\\/30{border-color:color-mix(in oklab,var(--_char-color-muted-foreground)30%,transparent)}}.border-orange-500\\\\/20{border-color:#fe6e0033}@supports (color:color-mix(in lab, red, red)){.border-orange-500\\\\/20{border-color:color-mix(in oklab,var(--color-orange-500)20%,transparent)}}.border-primary,.border-primary\\\\/50{border-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.border-primary\\\\/50{border-color:color-mix(in oklab,var(--_char-color-primary)50%,transparent)}}.border-red-500{border-color:var(--color-red-500)}.border-red-500\\\\/20{border-color:#fb2c3633}@supports (color:color-mix(in lab, red, red)){.border-red-500\\\\/20{border-color:color-mix(in oklab,var(--color-red-500)20%,transparent)}}.border-red-500\\\\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.border-red-500\\\\/30{border-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.border-transparent{border-color:#0000}.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-t-muted-foreground\\\\/60{border-top-color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-t-muted-foreground\\\\/60{border-top-color:color-mix(in oklab,var(--_char-color-muted-foreground)60%,transparent)}}.bg-\\\\[color-mix\\\\(in_oklab\\\\,rgb\\\\(var\\\\(--background\\\\)\\\\)_20\\\\%\\\\,transparent\\\\)\\\\]{background-color:rgb(var(--background))}@supports (color:color-mix(in lab, red, red)){.bg-\\\\[color-mix\\\\(in_oklab\\\\,rgb\\\\(var\\\\(--background\\\\)\\\\)_20\\\\%\\\\,transparent\\\\)\\\\]{background-color:color-mix(in oklab,rgb(var(--background))20%,transparent)}}.bg-accent{background-color:var(--_char-color-accent)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\\\\/5{background-color:#f99c000d}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\\\/5{background-color:color-mix(in oklab,var(--color-amber-500)5%,transparent)}}.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\\\\/15{background-color:#f99c0026}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\\\/15{background-color:color-mix(in oklab,var(--color-amber-500)15%,transparent)}}.bg-background,.bg-background\\\\/80{background-color:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\\\\/80{background-color:color-mix(in oklab,var(--_char-color-background)80%,transparent)}}.bg-background\\\\/95{background-color:var(--_char-color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\\\\/95{background-color:color-mix(in oklab,var(--_char-color-background)95%,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-500{background-color:var(--color-blue-500)}.bg-blue-500\\\\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\\\\/5{background-color:color-mix(in oklab,var(--color-blue-500)5%,transparent)}}.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-blue-500\\\\/70{background-color:#3080ffb3}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\\\\/70{background-color:color-mix(in oklab,var(--color-blue-500)70%,transparent)}}.bg-border{background-color:var(--_char-color-border)}.bg-card{background-color:var(--_char-color-card)}.bg-code-bg{background-color:var(--_char-code-bg)}.bg-code-header-bg{background-color:var(--_char-code-header-bg)}.bg-composer-bg{background-color:var(--_char-composer-bg)}.bg-current{background-color:currentColor}.bg-destructive,.bg-destructive\\\\/10{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\\\\/10{background-color:color-mix(in oklab,var(--_char-color-destructive)10%,transparent)}}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-emerald-500\\\\/6{background-color:#00bb7f0f}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\\\\/6{background-color:color-mix(in oklab,var(--color-emerald-500)6%,transparent)}}.bg-emerald-500\\\\/10{background-color:#00bb7f1a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\\\\/10{background-color:color-mix(in oklab,var(--color-emerald-500)10%,transparent)}}.bg-emerald-500\\\\/15{background-color:#00bb7f26}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\\\\/15{background-color:color-mix(in oklab,var(--color-emerald-500)15%,transparent)}}.bg-foreground{background-color:var(--_char-color-foreground)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-muted{background-color:var(--_char-color-muted)}.bg-muted-foreground\\\\/40{background-color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\\\/40{background-color:color-mix(in oklab,var(--_char-color-muted-foreground)40%,transparent)}}.bg-muted\\\\/5{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/5{background-color:color-mix(in oklab,var(--_char-color-muted)5%,transparent)}}.bg-muted\\\\/20{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/20{background-color:color-mix(in oklab,var(--_char-color-muted)20%,transparent)}}.bg-muted\\\\/30{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/30{background-color:color-mix(in oklab,var(--_char-color-muted)30%,transparent)}}.bg-muted\\\\/40{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/40{background-color:color-mix(in oklab,var(--_char-color-muted)40%,transparent)}}.bg-muted\\\\/50{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\\\/50{background-color:color-mix(in oklab,var(--_char-color-muted)50%,transparent)}}.bg-orange-500\\\\/10{background-color:#fe6e001a}@supports (color:color-mix(in lab, red, red)){.bg-orange-500\\\\/10{background-color:color-mix(in oklab,var(--color-orange-500)10%,transparent)}}.bg-popover{background-color:var(--_char-color-popover)}.bg-primary,.bg-primary\\\\/10{background-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.bg-primary\\\\/10{background-color:color-mix(in oklab,var(--_char-color-primary)10%,transparent)}}.bg-primary\\\\/90{background-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.bg-primary\\\\/90{background-color:color-mix(in oklab,var(--_char-color-primary)90%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\\\\/5{background-color:#fb2c360d}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\\\/5{background-color:color-mix(in oklab,var(--color-red-500)5%,transparent)}}.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\\\\/15{background-color:#fb2c3626}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\\\/15{background-color:color-mix(in oklab,var(--color-red-500)15%,transparent)}}.bg-secondary{background-color:var(--_char-color-secondary)}.bg-slate-500\\\\/10{background-color:#62748e1a}@supports (color:color-mix(in lab, red, red)){.bg-slate-500\\\\/10{background-color:color-mix(in oklab,var(--color-slate-500)10%,transparent)}}.bg-transparent{background-color:#0000}.bg-user-bubble-bg{background-color:var(--_char-user-bubble-bg)}.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-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-\\\\[linear-gradient\\\\(to_top\\\\,var\\\\(--color-background\\\\)\\\\,transparent\\\\)\\\\]{background-image:linear-gradient(to top,var(--color-background),transparent)}.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-current{fill:currentColor}.fill-foreground{fill:var(--_char-color-foreground)}.fill-primary{fill:var(--_char-color-primary)}.stroke-destructive{stroke:var(--_char-color-destructive)}.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-0\\\\.5{padding:calc(var(--spacing)*.5)}.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-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-\\\\(--cell-size\\\\){padding-inline:var(--cell-size)}.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-6{padding-block:calc(var(--spacing)*6)}.py-8{padding-block:calc(var(--spacing)*8)}.pt-0\\\\.5{padding-top:calc(var(--spacing)*.5)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-3{padding-top:calc(var(--spacing)*3)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-14{padding-top:calc(var(--spacing)*14)}.pr-0\\\\.5{padding-right:calc(var(--spacing)*.5)}.pr-1{padding-right:calc(var(--spacing)*1)}.pr-2{padding-right:calc(var(--spacing)*2)}.pr-8{padding-right:calc(var(--spacing)*8)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pl-0\\\\.5{padding-left:calc(var(--spacing)*.5)}.pl-2{padding-left:calc(var(--spacing)*2)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-6{padding-left:calc(var(--spacing)*6)}.pl-8{padding-left:calc(var(--spacing)*8)}.text-center{text-align:center}.text-left{text-align:left}.text-start{text-align:start}.font-mono{font-family:var(--_char-font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--_char-font-size-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--_char-font-size-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--_char-font-size-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--_char-font-size-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\\\[0\\\\.8rem\\\\]{font-size:.8rem}.text-\\\\[9px\\\\]{font-size:9px}.text-\\\\[10px\\\\]{font-size:10px}.text-\\\\[11px\\\\]{font-size:11px}.leading-7{--tw-leading:calc(var(--spacing)*7);line-height:calc(var(--spacing)*7)}.leading-none{--tw-leading:1;line-height:1}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.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-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.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)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.text-balance{text-wrap:balance}.wrap-break-word{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent-foreground{color:var(--_char-color-accent-foreground)}.text-amber-400{color:var(--color-amber-400)}.text-amber-500{color:var(--color-amber-500)}.text-amber-600{color:var(--color-amber-600)}.text-assistant-bubble-text{color:var(--_char-assistant-bubble-text)}.text-background{color:var(--_char-color-background)}.text-blue-600{color:var(--color-blue-600)}.text-card-foreground{color:var(--_char-color-card-foreground)}.text-code-text{color:var(--_char-code-text)}.text-composer-text{color:var(--_char-composer-text)}.text-current{color:currentColor}.text-destructive,.text-destructive\\\\/70{color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.text-destructive\\\\/70{color:color-mix(in oklab,var(--_char-color-destructive)70%,transparent)}}.text-emerald-500{color:var(--color-emerald-500)}.text-emerald-600{color:var(--color-emerald-600)}.text-foreground,.text-foreground\\\\/70{color:var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\\\\/70{color:color-mix(in oklab,var(--_char-color-foreground)70%,transparent)}}.text-foreground\\\\/80{color:var(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\\\\/80{color:color-mix(in oklab,var(--_char-color-foreground)80%,transparent)}}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-muted-foreground,.text-muted-foreground\\\\/50{color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\\\\/50{color:color-mix(in oklab,var(--_char-color-muted-foreground)50%,transparent)}}.text-muted-foreground\\\\/70{color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\\\\/70{color:color-mix(in oklab,var(--_char-color-muted-foreground)70%,transparent)}}.text-muted-foreground\\\\/80{color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\\\\/80{color:color-mix(in oklab,var(--_char-color-muted-foreground)80%,transparent)}}.text-orange-600{color:var(--color-orange-600)}.text-popover-foreground{color:var(--_char-color-popover-foreground)}.text-primary{color:var(--_char-color-primary)}.text-primary-foreground{color:var(--_char-color-primary-foreground)}.text-primary\\\\/80{color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.text-primary\\\\/80{color:color-mix(in oklab,var(--_char-color-primary)80%,transparent)}}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-secondary-foreground{color:var(--_char-color-secondary-foreground)}.text-slate-600{color:var(--color-slate-600)}.text-user-bubble-text{color:var(--_char-user-bubble-text)}.text-white{color:var(--color-white)}.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)}}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.opacity-100{opacity:1}.shadow{--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-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-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px 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-none{--tw-shadow:0 0 #0000;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-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px 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-1{--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)}.\\\\[box-shadow\\\\:inset_0_1px_2px_0_rgba\\\\(255\\\\,255\\\\,255\\\\,0\\\\.15\\\\)\\\\]{box-shadow:inset 0 1px 2px #ffffff26}.shadow-black\\\\/20{--tw-shadow-color:#0003}@supports (color:color-mix(in lab, red, red)){.shadow-black\\\\/20{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)20%,transparent)var(--tw-shadow-alpha),transparent)}}.ring-amber-500\\\\/30{--tw-ring-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.ring-amber-500\\\\/30{--tw-ring-color:color-mix(in oklab,var(--color-amber-500)30%,transparent)}}.ring-blue-500\\\\/25{--tw-ring-color:#3080ff40}@supports (color:color-mix(in lab, red, red)){.ring-blue-500\\\\/25{--tw-ring-color:color-mix(in oklab,var(--color-blue-500)25%,transparent)}}.ring-border\\\\/20{--tw-ring-color:var(--_char-color-border)}@supports (color:color-mix(in lab, red, red)){.ring-border\\\\/20{--tw-ring-color:color-mix(in oklab,var(--_char-color-border)20%,transparent)}}.ring-emerald-400\\\\/30{--tw-ring-color:#00d2944d}@supports (color:color-mix(in lab, red, red)){.ring-emerald-400\\\\/30{--tw-ring-color:color-mix(in oklab,var(--color-emerald-400)30%,transparent)}}.ring-red-500\\\\/30{--tw-ring-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.ring-red-500\\\\/30{--tw-ring-color:color-mix(in oklab,var(--color-red-500)30%,transparent)}}.ring-ring\\\\/50{--tw-ring-color:var(--_char-color-ring)}@supports (color:color-mix(in lab, red, red)){.ring-ring\\\\/50{--tw-ring-color:color-mix(in oklab,var(--_char-color-ring)50%,transparent)}}.ring-offset-background{--tw-ring-offset-color:var(--_char-color-background)}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.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,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.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-\\\\[transform\\\\,opacity\\\\]{transition-property:transform,opacity;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-shadow{transition-property:box-shadow;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))}.transition-none{transition-property:none}.duration-\\\\(--animation-duration\\\\){--tw-duration:var(--animation-duration);transition-duration:var(--animation-duration)}.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-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.fade-in-0{--tw-enter-opacity:0}.fill-mode-both{--tw-animation-fill-mode:both;animation-fill-mode:both}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.zoom-in-95{--tw-enter-scale:.95}.\\\\[--cell-size\\\\:--spacing\\\\(8\\\\)\\\\]{--cell-size:calc(var(--spacing)*8)}.\\\\[animation-delay\\\\:150ms\\\\]{animation-delay:.15s}.\\\\[animation-delay\\\\:300ms\\\\]{animation-delay:.3s}.\\\\[check\\\\:lint\\\\]{check:lint}.fade-in{--tw-enter-opacity:0}.running{animation-play-state:running}.slide-in-from-bottom-1{--tw-enter-translate-y:calc(1*var(--spacing))}.slide-in-from-bottom-2{--tw-enter-translate-y:calc(2*var(--spacing))}@media (hover:hover){.group-hover\\\\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-data-\\\\[disabled\\\\=true\\\\]\\\\:pointer-events-none:is(:where(.group)[data-disabled=true] *){pointer-events:none}.group-data-\\\\[disabled\\\\=true\\\\]\\\\:opacity-50:is(:where(.group)[data-disabled=true] *){opacity:.5}.group-data-\\\\[focused\\\\=true\\\\]\\\\/day\\\\:relative:is(:where(.group\\\\/day)[data-focused=true] *){position:relative}.group-data-\\\\[focused\\\\=true\\\\]\\\\/day\\\\:z-10:is(:where(.group\\\\/day)[data-focused=true] *){z-index:10}.group-data-\\\\[focused\\\\=true\\\\]\\\\/day\\\\:border-ring:is(:where(.group\\\\/day)[data-focused=true] *){border-color:var(--_char-color-ring)}.group-data-\\\\[focused\\\\=true\\\\]\\\\/day\\\\:ring-\\\\[3px\\\\]:is(:where(.group\\\\/day)[data-focused=true] *){--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)}.group-data-\\\\[focused\\\\=true\\\\]\\\\/day\\\\:ring-ring\\\\/50:is(:where(.group\\\\/day)[data-focused=true] *){--tw-ring-color:var(--_char-color-ring)}@supports (color:color-mix(in lab, red, red)){.group-data-\\\\[focused\\\\=true\\\\]\\\\/day\\\\:ring-ring\\\\/50:is(:where(.group\\\\/day)[data-focused=true] *){--tw-ring-color:color-mix(in oklab,var(--_char-color-ring)50%,transparent)}}.group-data-\\\\[state\\\\=closed\\\\]\\\\/collapsible-content\\\\:animate-out:is(:where(.group\\\\/collapsible-content)[data-state=closed] *){animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.group-data-\\\\[state\\\\=closed\\\\]\\\\/collapsible-content\\\\:duration-\\\\(--animation-duration\\\\):is(:where(.group\\\\/collapsible-content)[data-state=closed] *){--tw-duration:var(--animation-duration);transition-duration:var(--animation-duration)}.group-data-\\\\[state\\\\=closed\\\\]\\\\/collapsible-content\\\\:fade-out-0:is(:where(.group\\\\/collapsible-content)[data-state=closed] *){--tw-exit-opacity:0}.group-data-\\\\[state\\\\=closed\\\\]\\\\/collapsible-content\\\\:slide-out-to-top-4:is(:where(.group\\\\/collapsible-content)[data-state=closed] *){--tw-exit-translate-y:calc(4*var(--spacing)*-1)}.group-data-\\\\[state\\\\=closed\\\\]\\\\/trigger\\\\:-rotate-90:is(:where(.group\\\\/trigger)[data-state=closed] *){rotate:-90deg}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:animate-in:is(:where(.group\\\\/collapsible-content)[data-state=open] *){animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:animate-out:is(:where(.group\\\\/collapsible-content)[data-state=open] *){animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:delay-\\\\[calc\\\\(var\\\\(--animation-duration\\\\)\\\\*0\\\\.75\\\\)\\\\]:is(:where(.group\\\\/collapsible-content)[data-state=open] *){transition-delay:calc(var(--animation-duration)*.75)}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:duration-\\\\(--animation-duration\\\\):is(:where(.group\\\\/collapsible-content)[data-state=open] *){--tw-duration:var(--animation-duration);transition-duration:var(--animation-duration)}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:delay-\\\\[calc\\\\(var\\\\(--animation-duration\\\\)\\\\*0\\\\.75\\\\)\\\\]:is(:where(.group\\\\/collapsible-content)[data-state=open] *){animation-delay:calc(var(--animation-duration)*.75);--tw-animation-delay:calc(var(--animation-duration)*.75)}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:fade-in-0:is(:where(.group\\\\/collapsible-content)[data-state=open] *){--tw-enter-opacity:0}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:fade-out-0:is(:where(.group\\\\/collapsible-content)[data-state=open] *){--tw-exit-opacity:0}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:fill-mode-forwards:is(:where(.group\\\\/collapsible-content)[data-state=open] *){--tw-animation-fill-mode:forwards;animation-fill-mode:forwards}.group-data-\\\\[state\\\\=open\\\\]\\\\/collapsible-content\\\\:slide-in-from-top-4:is(:where(.group\\\\/collapsible-content)[data-state=open] *){--tw-enter-translate-y:calc(4*var(--spacing)*-1)}.group-data-\\\\[state\\\\=open\\\\]\\\\/trigger\\\\:rotate-0:is(:where(.group\\\\/trigger)[data-state=open] *){rotate:none}.peer-disabled\\\\:cursor-not-allowed:is(:where(.peer):disabled~*){cursor:not-allowed}.peer-disabled\\\\:opacity-50:is(:where(.peer):disabled~*){opacity:.5}.peer-disabled\\\\:opacity-70:is(:where(.peer):disabled~*){opacity:.7}.selection\\\\:bg-primary ::selection{background-color:var(--_char-color-primary)}.selection\\\\:bg-primary::selection{background-color:var(--_char-color-primary)}.selection\\\\:text-primary-foreground ::selection{color:var(--_char-color-primary-foreground)}.selection\\\\:text-primary-foreground::selection{color:var(--_char-color-primary-foreground)}.file\\\\:inline-flex::file-selector-button{display:inline-flex}.file\\\\:h-7::file-selector-button{height:calc(var(--spacing)*7)}.file\\\\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\\\\:bg-transparent::file-selector-button{background-color:#0000}.file\\\\:text-sm::file-selector-button{font-size:var(--_char-font-size-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\\\\:font-medium::file-selector-button{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.file\\\\:text-foreground::file-selector-button{color:var(--_char-color-foreground)}.placeholder\\\\:text-composer-placeholder::placeholder{color:var(--_char-composer-placeholder)}.placeholder\\\\:text-muted-foreground::placeholder{color:var(--_char-color-muted-foreground)}.first\\\\:mt-0:first-child{margin-top:calc(var(--spacing)*0)}.first\\\\:rounded-tl-lg:first-child{border-top-left-radius:var(--_char-radius-lg)}.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(--_char-radius-lg)}.last\\\\:border-r:last-child{border-right-style:var(--tw-border-style);border-right-width:1px}.empty\\\\:hidden:empty{display:none}.focus-within\\\\:ring-1:focus-within{--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-within\\\\:ring-ring:focus-within{--tw-ring-color:var(--_char-color-ring)}.focus-within\\\\:ring-offset-1:focus-within{--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)}@media (hover:hover){.hover\\\\:border-border:hover{border-color:var(--_char-color-border)}.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-\\\\[color-mix\\\\(in_oklab\\\\,rgb\\\\(var\\\\(--background\\\\)\\\\)_30\\\\%\\\\,transparent\\\\)\\\\]:hover{background-color:rgb(var(--background))}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-\\\\[color-mix\\\\(in_oklab\\\\,rgb\\\\(var\\\\(--background\\\\)\\\\)_30\\\\%\\\\,transparent\\\\)\\\\]:hover{background-color:color-mix(in oklab,rgb(var(--background))30%,transparent)}}.hover\\\\:bg-accent:hover,.hover\\\\:bg-accent\\\\/50:hover{background-color:var(--_char-color-accent)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-accent\\\\/50:hover{background-color:color-mix(in oklab,var(--_char-color-accent)50%,transparent)}}.hover\\\\:bg-amber-500\\\\/10:hover{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-amber-500\\\\/10:hover{background-color:color-mix(in oklab,var(--color-amber-500)10%,transparent)}}.hover\\\\:bg-blue-500\\\\/20:hover{background-color:#3080ff33}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-blue-500\\\\/20:hover{background-color:color-mix(in oklab,var(--color-blue-500)20%,transparent)}}.hover\\\\:bg-destructive\\\\/10:hover{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/10:hover{background-color:color-mix(in oklab,var(--_char-color-destructive)10%,transparent)}}.hover\\\\:bg-destructive\\\\/15:hover{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/15:hover{background-color:color-mix(in oklab,var(--_char-color-destructive)15%,transparent)}}.hover\\\\:bg-destructive\\\\/20:hover{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/20:hover{background-color:color-mix(in oklab,var(--_char-color-destructive)20%,transparent)}}.hover\\\\:bg-destructive\\\\/90:hover{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-destructive\\\\/90:hover{background-color:color-mix(in oklab,var(--_char-color-destructive)90%,transparent)}}.hover\\\\:bg-emerald-500\\\\/5:hover{background-color:#00bb7f0d}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-emerald-500\\\\/5:hover{background-color:color-mix(in oklab,var(--color-emerald-500)5%,transparent)}}.hover\\\\:bg-muted:hover{background-color:var(--_char-color-muted)}.hover\\\\:bg-muted-foreground\\\\/15:hover{background-color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-muted-foreground\\\\/15:hover{background-color:color-mix(in oklab,var(--_char-color-muted-foreground)15%,transparent)}}.hover\\\\:bg-muted\\\\/50:hover{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-muted\\\\/50:hover{background-color:color-mix(in oklab,var(--_char-color-muted)50%,transparent)}}.hover\\\\:bg-muted\\\\/60:hover{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-muted\\\\/60:hover{background-color:color-mix(in oklab,var(--_char-color-muted)60%,transparent)}}.hover\\\\:bg-muted\\\\/70:hover{background-color:var(--_char-color-muted)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-muted\\\\/70:hover{background-color:color-mix(in oklab,var(--_char-color-muted)70%,transparent)}}.hover\\\\:bg-orange-500\\\\/20:hover{background-color:#fe6e0033}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-orange-500\\\\/20:hover{background-color:color-mix(in oklab,var(--color-orange-500)20%,transparent)}}.hover\\\\:bg-primary\\\\/90:hover{background-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-primary\\\\/90:hover{background-color:color-mix(in oklab,var(--_char-color-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-secondary\\\\/80:hover{background-color:var(--_char-color-secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\\\:bg-secondary\\\\/80:hover{background-color:color-mix(in oklab,var(--_char-color-secondary)80%,transparent)}}.hover\\\\:bg-white\\\\!:hover{background-color:var(--color-white)!important}.hover\\\\:text-accent-foreground:hover{color:var(--_char-color-accent-foreground)}.hover\\\\:text-amber-400:hover{color:var(--color-amber-400)}.hover\\\\:text-foreground:hover{color:var(--_char-color-foreground)}.hover\\\\:text-muted-foreground:hover{color:var(--_char-color-muted-foreground)}.hover\\\\:text-red-400:hover{color:var(--color-red-400)}.hover\\\\:underline:hover{text-decoration-line:underline}.hover\\\\:opacity-75:hover{opacity:.75}.hover\\\\:opacity-100:hover{opacity:1}.hover\\\\:ring-4:hover{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + 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\\\\:bg-accent:focus{background-color:var(--_char-color-accent)}.focus\\\\:text-accent-foreground:focus{color:var(--_char-color-accent-foreground)}.focus\\\\:ring-1:focus{--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\\\\: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(--_char-color-ring)}.focus\\\\:ring-offset-1:focus{--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\\\\: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(--_char-color-ring)}.focus-visible\\\\:bg-muted:focus-visible{background-color:var(--_char-color-muted)}.focus-visible\\\\:opacity-100:focus-visible{opacity:1}.focus-visible\\\\:ring-0:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + 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-4:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(4px + 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-destructive\\\\/20:focus-visible{--tw-ring-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-destructive\\\\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--_char-color-destructive)20%,transparent)}}.focus-visible\\\\:ring-destructive\\\\/50:focus-visible{--tw-ring-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-destructive\\\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--_char-color-destructive)50%,transparent)}}.focus-visible\\\\:ring-ring:focus-visible,.focus-visible\\\\:ring-ring\\\\/50:focus-visible{--tw-ring-color:var(--_char-color-ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\\\:ring-ring\\\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--_char-color-ring)50%,transparent)}}.focus-visible\\\\:outline-hidden:focus-visible{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus-visible\\\\:outline-hidden:focus-visible{outline-offset:2px;outline:2px solid #0000}}.focus-visible\\\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\\\\:pointer-events-none:disabled{pointer-events:none}.disabled\\\\:invisible:disabled{visibility:hidden}.disabled\\\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\\\:opacity-50:disabled{opacity:.5}.has-focus\\\\:border-ring:has(:focus){border-color:var(--_char-color-ring)}.has-focus\\\\:ring-\\\\[3px\\\\]:has(:focus){--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)}.has-focus\\\\:ring-ring\\\\/50:has(:focus){--tw-ring-color:var(--_char-color-ring)}@supports (color:color-mix(in lab, red, red)){.has-focus\\\\:ring-ring\\\\/50:has(:focus){--tw-ring-color:color-mix(in oklab,var(--_char-color-ring)50%,transparent)}}.has-data-\\\\[slot\\\\=card-action\\\\]\\\\:grid-cols-\\\\[1fr_auto\\\\]:has([data-slot=card-action]){grid-template-columns:1fr auto}.has-\\\\[textarea\\\\:focus-visible\\\\]\\\\:border-ring:has(:is(textarea:focus-visible)){border-color:var(--_char-color-ring)}.has-\\\\[textarea\\\\:focus-visible\\\\]\\\\:ring-2:has(:is(textarea: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)}.has-\\\\[textarea\\\\:focus-visible\\\\]\\\\:ring-ring\\\\/20:has(:is(textarea:focus-visible)){--tw-ring-color:var(--_char-color-ring)}@supports (color:color-mix(in lab, red, red)){.has-\\\\[textarea\\\\:focus-visible\\\\]\\\\:ring-ring\\\\/20:has(:is(textarea:focus-visible)){--tw-ring-color:color-mix(in oklab,var(--_char-color-ring)20%,transparent)}}.has-\\\\[\\\\>svg\\\\]\\\\:grid-cols-\\\\[calc\\\\(var\\\\(--spacing\\\\)\\\\*4\\\\)_1fr\\\\]:has(>svg){grid-template-columns:calc(var(--spacing)*4)1fr}.has-\\\\[\\\\>svg\\\\]\\\\:gap-x-3:has(>svg){column-gap:calc(var(--spacing)*3)}.has-\\\\[\\\\>svg\\\\]\\\\:px-1\\\\.5:has(>svg){padding-inline:calc(var(--spacing)*1.5)}.has-\\\\[\\\\>svg\\\\]\\\\:px-2:has(>svg){padding-inline:calc(var(--spacing)*2)}.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-disabled\\\\:opacity-50[aria-disabled=true]{opacity:.5}.aria-invalid\\\\:border-destructive[aria-invalid=true]{border-color:var(--_char-color-destructive)}.aria-invalid\\\\:ring-destructive\\\\/20[aria-invalid=true]{--tw-ring-color:var(--_char-color-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(--_char-color-destructive)20%,transparent)}}.aria-selected\\\\:text-muted-foreground[aria-selected=true]{color:var(--_char-color-muted-foreground)}.data-floating\\\\:absolute[data-floating]{position:absolute}.data-floating\\\\:rounded-md[data-floating]{border-radius:var(--_char-radius-md)}.data-floating\\\\:border[data-floating]{border-style:var(--tw-border-style);border-width:1px}.data-floating\\\\:bg-background[data-floating]{background-color:var(--_char-color-background)}.data-floating\\\\:p-1[data-floating]{padding:calc(var(--spacing)*1)}.data-floating\\\\:shadow-sm[data-floating]{--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)}.data-\\\\[active\\\\=true\\\\]\\\\:bg-muted[data-active=true]{background-color:var(--_char-color-muted)}.data-\\\\[disabled\\\\]\\\\:pointer-events-none[data-disabled]{pointer-events:none}.data-\\\\[disabled\\\\]\\\\:opacity-50[data-disabled]{opacity:.5}.data-\\\\[disabled\\\\=true\\\\]\\\\:pointer-events-none[data-disabled=true]{pointer-events:none}.data-\\\\[disabled\\\\=true\\\\]\\\\:opacity-50[data-disabled=true]{opacity:.5}.data-\\\\[dragging\\\\=true\\\\]\\\\:border-dashed[data-dragging=true]{--tw-border-style:dashed;border-style:dashed}.data-\\\\[dragging\\\\=true\\\\]\\\\:border-ring[data-dragging=true]{border-color:var(--_char-color-ring)}.data-\\\\[dragging\\\\=true\\\\]\\\\:bg-accent\\\\/50[data-dragging=true]{background-color:var(--_char-color-accent)}@supports (color:color-mix(in lab, red, red)){.data-\\\\[dragging\\\\=true\\\\]\\\\:bg-accent\\\\/50[data-dragging=true]{background-color:color-mix(in oklab,var(--_char-color-accent)50%,transparent)}}.data-\\\\[inset\\\\]\\\\:pl-8[data-inset]{padding-left:calc(var(--spacing)*8)}.data-\\\\[orientation\\\\=horizontal\\\\]\\\\:h-1\\\\.5[data-orientation=horizontal]{height:calc(var(--spacing)*1.5)}.data-\\\\[orientation\\\\=horizontal\\\\]\\\\:h-full[data-orientation=horizontal]{height:100%}.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\\\\]\\\\:min-h-44[data-orientation=vertical]{min-height:calc(var(--spacing)*44)}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:w-1\\\\.5[data-orientation=vertical]{width:calc(var(--spacing)*1.5)}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:w-auto[data-orientation=vertical]{width:auto}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:w-full[data-orientation=vertical]{width:100%}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:w-px[data-orientation=vertical]{width:1px}.data-\\\\[orientation\\\\=vertical\\\\]\\\\:flex-col[data-orientation=vertical]{flex-direction:column}.data-\\\\[placeholder\\\\]\\\\:text-muted-foreground[data-placeholder]{color:var(--_char-color-muted-foreground)}.data-\\\\[range-end\\\\=true\\\\]\\\\:rounded-md[data-range-end=true]{border-radius:var(--_char-radius-md)}.data-\\\\[range-end\\\\=true\\\\]\\\\:rounded-r-md[data-range-end=true]{border-top-right-radius:var(--_char-radius-md);border-bottom-right-radius:var(--_char-radius-md)}.data-\\\\[range-end\\\\=true\\\\]\\\\:bg-primary[data-range-end=true]{background-color:var(--_char-color-primary)}.data-\\\\[range-end\\\\=true\\\\]\\\\:text-primary-foreground[data-range-end=true]{color:var(--_char-color-primary-foreground)}.data-\\\\[range-middle\\\\=true\\\\]\\\\:rounded-none[data-range-middle=true]{border-radius:0}.data-\\\\[range-middle\\\\=true\\\\]\\\\:bg-accent[data-range-middle=true]{background-color:var(--_char-color-accent)}.data-\\\\[range-middle\\\\=true\\\\]\\\\:text-accent-foreground[data-range-middle=true]{color:var(--_char-color-accent-foreground)}.data-\\\\[range-start\\\\=true\\\\]\\\\:rounded-md[data-range-start=true]{border-radius:var(--_char-radius-md)}.data-\\\\[range-start\\\\=true\\\\]\\\\:rounded-l-md[data-range-start=true]{border-top-left-radius:var(--_char-radius-md);border-bottom-left-radius:var(--_char-radius-md)}.data-\\\\[range-start\\\\=true\\\\]\\\\:bg-primary[data-range-start=true]{background-color:var(--_char-color-primary)}.data-\\\\[range-start\\\\=true\\\\]\\\\:text-primary-foreground[data-range-start=true]{color:var(--_char-color-primary-foreground)}.data-\\\\[selected-single\\\\=true\\\\]\\\\:bg-primary[data-selected-single=true]{background-color:var(--_char-color-primary)}.data-\\\\[selected-single\\\\=true\\\\]\\\\:text-primary-foreground[data-selected-single=true]{color:var(--_char-color-primary-foreground)}.data-\\\\[selected\\\\=true\\\\]\\\\:rounded-none[data-selected=true]{border-radius:0}.data-\\\\[selected\\\\=true\\\\]\\\\:bg-accent[data-selected=true]{background-color:var(--_char-color-accent)}.data-\\\\[selected\\\\=true\\\\]\\\\:text-accent-foreground[data-selected=true]{color:var(--_char-color-accent-foreground)}.data-\\\\[side\\\\=bottom\\\\]\\\\:translate-y-1[data-side=bottom]{--tw-translate-y:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\\\\[side\\\\=bottom\\\\]\\\\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y:calc(2*var(--spacing)*-1)}.data-\\\\[side\\\\=left\\\\]\\\\:-translate-x-1[data-side=left]{--tw-translate-x:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\\\\[side\\\\=left\\\\]\\\\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x:calc(2*var(--spacing))}.data-\\\\[side\\\\=right\\\\]\\\\:translate-x-1[data-side=right]{--tw-translate-x:calc(var(--spacing)*1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\\\\[side\\\\=right\\\\]\\\\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x:calc(2*var(--spacing)*-1)}.data-\\\\[side\\\\=top\\\\]\\\\:-translate-y-1[data-side=top]{--tw-translate-y:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.data-\\\\[side\\\\=top\\\\]\\\\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y:calc(2*var(--spacing))}.data-\\\\[size\\\\=default\\\\]\\\\:h-9[data-size=default]{height:calc(var(--spacing)*9)}.data-\\\\[size\\\\=sm\\\\]\\\\:h-8[data-size=sm]{height:calc(var(--spacing)*8)}:is(.\\\\*\\\\:data-\\\\[slot\\\\=alert-description\\\\]\\\\:text-destructive\\\\/90>*)[data-slot=alert-description]{color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){:is(.\\\\*\\\\:data-\\\\[slot\\\\=alert-description\\\\]\\\\:text-destructive\\\\/90>*)[data-slot=alert-description]{color:color-mix(in oklab,var(--_char-color-destructive)90%,transparent)}}:is(.\\\\*\\\\:data-\\\\[slot\\\\=select-value\\\\]\\\\:line-clamp-1>*)[data-slot=select-value]{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}:is(.\\\\*\\\\:data-\\\\[slot\\\\=select-value\\\\]\\\\:flex>*)[data-slot=select-value]{display:flex}:is(.\\\\*\\\\:data-\\\\[slot\\\\=select-value\\\\]\\\\:items-center>*)[data-slot=select-value]{align-items:center}:is(.\\\\*\\\\:data-\\\\[slot\\\\=select-value\\\\]\\\\:gap-2>*)[data-slot=select-value]{gap:calc(var(--spacing)*2)}.data-\\\\[state\\\\=checked\\\\]\\\\:border-primary[data-state=checked]{border-color:var(--_char-color-primary)}.data-\\\\[state\\\\=checked\\\\]\\\\:bg-primary[data-state=checked]{background-color:var(--_char-color-primary)}.data-\\\\[state\\\\=checked\\\\]\\\\:text-primary-foreground[data-state=checked]{color:var(--_char-color-primary-foreground)}.data-\\\\[state\\\\=closed\\\\]\\\\:pointer-events-none[data-state=closed]{pointer-events:none}.data-\\\\[state\\\\=closed\\\\]\\\\:animate-collapsible-up[data-state=closed]{animation:collapsible-up var(--tw-animation-duration,var(--tw-duration,.2s))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\\\\[state\\\\=closed\\\\]\\\\:animate-out[data-state=closed]{animation:exit var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\\\\[state\\\\=closed\\\\]\\\\:duration-\\\\(--animation-duration\\\\)[data-state=closed]{--tw-duration:var(--animation-duration);transition-duration:var(--animation-duration)}.data-\\\\[state\\\\=closed\\\\]\\\\:duration-200[data-state=closed]{--tw-duration:.2s;transition-duration:.2s}.data-\\\\[state\\\\=closed\\\\]\\\\:duration-300[data-state=closed]{--tw-duration:.3s;transition-duration:.3s}.data-\\\\[state\\\\=closed\\\\]\\\\:fade-out-0[data-state=closed]{--tw-exit-opacity:0}.data-\\\\[state\\\\=closed\\\\]\\\\:fill-mode-forwards[data-state=closed]{--tw-animation-fill-mode:forwards;animation-fill-mode:forwards}.data-\\\\[state\\\\=closed\\\\]\\\\:zoom-out-95[data-state=closed]{--tw-exit-scale:.95}.data-\\\\[state\\\\=closed\\\\]\\\\:slide-out-to-bottom[data-state=closed]{--tw-exit-translate-y:100%}.data-\\\\[state\\\\=closed\\\\]\\\\:slide-out-to-left[data-state=closed]{--tw-exit-translate-x:-100%}.data-\\\\[state\\\\=closed\\\\]\\\\:slide-out-to-right[data-state=closed]{--tw-exit-translate-x:100%}.data-\\\\[state\\\\=closed\\\\]\\\\:slide-out-to-top[data-state=closed]{--tw-exit-translate-y:-100%}.data-\\\\[state\\\\=open\\\\]\\\\:animate-collapsible-down[data-state=open]{animation:collapsible-down var(--tw-animation-duration,var(--tw-duration,.2s))var(--tw-ease,ease-out)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\\\\[state\\\\=open\\\\]\\\\:animate-in[data-state=open]{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.data-\\\\[state\\\\=open\\\\]\\\\:bg-accent[data-state=open]{background-color:var(--_char-color-accent)}.data-\\\\[state\\\\=open\\\\]\\\\:bg-secondary[data-state=open]{background-color:var(--_char-color-secondary)}.data-\\\\[state\\\\=open\\\\]\\\\:text-accent-foreground[data-state=open]{color:var(--_char-color-accent-foreground)}.data-\\\\[state\\\\=open\\\\]\\\\:text-muted-foreground[data-state=open]{color:var(--_char-color-muted-foreground)}.data-\\\\[state\\\\=open\\\\]\\\\:duration-\\\\(--animation-duration\\\\)[data-state=open]{--tw-duration:var(--animation-duration);transition-duration:var(--animation-duration)}.data-\\\\[state\\\\=open\\\\]\\\\:duration-200[data-state=open]{--tw-duration:.2s;transition-duration:.2s}.data-\\\\[state\\\\=open\\\\]\\\\:duration-500[data-state=open]{--tw-duration:.5s;transition-duration:.5s}.data-\\\\[state\\\\=open\\\\]\\\\:fade-in-0[data-state=open]{--tw-enter-opacity:0}.data-\\\\[state\\\\=open\\\\]\\\\:zoom-in-95[data-state=open]{--tw-enter-scale:.95}.data-\\\\[state\\\\=open\\\\]\\\\:slide-in-from-bottom[data-state=open]{--tw-enter-translate-y:100%}.data-\\\\[state\\\\=open\\\\]\\\\:slide-in-from-left[data-state=open]{--tw-enter-translate-x:-100%}.data-\\\\[state\\\\=open\\\\]\\\\:slide-in-from-right[data-state=open]{--tw-enter-translate-x:100%}.data-\\\\[state\\\\=open\\\\]\\\\:slide-in-from-top[data-state=open]{--tw-enter-translate-y:-100%}.data-\\\\[variant\\\\=destructive\\\\]\\\\:text-destructive[data-variant=destructive]{color:var(--_char-color-destructive)}.data-\\\\[variant\\\\=destructive\\\\]\\\\:focus\\\\:bg-destructive\\\\/10[data-variant=destructive]:focus{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.data-\\\\[variant\\\\=destructive\\\\]\\\\:focus\\\\:bg-destructive\\\\/10[data-variant=destructive]:focus{background-color:color-mix(in oklab,var(--_char-color-destructive)10%,transparent)}}.data-\\\\[variant\\\\=destructive\\\\]\\\\:focus\\\\:text-destructive[data-variant=destructive]:focus{color:var(--_char-color-destructive)}@media (prefers-reduced-motion:reduce){.motion-reduce\\\\:animate-none{animation:none}}@media (min-width:40rem){.sm\\\\:h-3{height:calc(var(--spacing)*3)}.sm\\\\:w-3{width:calc(var(--spacing)*3)}.sm\\\\:max-w-3xl{max-width:var(--container-3xl)}.sm\\\\:max-w-lg{max-width:var(--container-lg)}.sm\\\\:max-w-sm{max-width:var(--container-sm)}.sm\\\\:flex-row{flex-direction:row}.sm\\\\:justify-end{justify-content:flex-end}.sm\\\\:p-6{padding:calc(var(--spacing)*6)}.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\\\\:text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.sm\\\\:text-base{font-size:var(--_char-font-size-base);line-height:var(--tw-leading,var(--text-base--line-height))}}@media (min-width:48rem){.md\\\\:flex-row{flex-direction:row}.md\\\\:pb-6{padding-bottom:calc(var(--spacing)*6)}.md\\\\:text-sm{font-size:var(--_char-font-size-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}.ltr\\\\:ml-1:where(:dir(ltr),[dir=ltr],[dir=ltr] *){margin-left:calc(var(--spacing)*1)}.ltr\\\\:ml-2:where(:dir(ltr),[dir=ltr],[dir=ltr] *){margin-left:calc(var(--spacing)*2)}.rtl\\\\:mr-1:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*1)}.rtl\\\\:mr-2:where(:dir(rtl),[dir=rtl],[dir=rtl] *){margin-right:calc(var(--spacing)*2)}.rtl\\\\:flex-row-reverse:where(:dir(rtl),[dir=rtl],[dir=rtl] *){flex-direction:row-reverse}.dark\\\\:border-input:is(.dark *){border-color:var(--_char-color-input)}.dark\\\\:border-muted-foreground\\\\/15:is(.dark *){border-color:var(--_char-color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:border-muted-foreground\\\\/15:is(.dark *){border-color:color-mix(in oklab,var(--_char-color-muted-foreground)15%,transparent)}}.dark\\\\:bg-amber-500\\\\/10:is(.dark *){background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-amber-500\\\\/10:is(.dark *){background-color:color-mix(in oklab,var(--color-amber-500)10%,transparent)}}.dark\\\\:bg-blue-500\\\\/10:is(.dark *){background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-blue-500\\\\/10:is(.dark *){background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.dark\\\\:bg-destructive\\\\/5:is(.dark *){background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-destructive\\\\/5:is(.dark *){background-color:color-mix(in oklab,var(--_char-color-destructive)5%,transparent)}}.dark\\\\:bg-destructive\\\\/60:is(.dark *){background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-destructive\\\\/60:is(.dark *){background-color:color-mix(in oklab,var(--_char-color-destructive)60%,transparent)}}.dark\\\\:bg-emerald-500\\\\/12:is(.dark *){background-color:#00bb7f1f}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-emerald-500\\\\/12:is(.dark *){background-color:color-mix(in oklab,var(--color-emerald-500)12%,transparent)}}.dark\\\\:bg-input\\\\/30:is(.dark *){background-color:var(--_char-color-input)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-input\\\\/30:is(.dark *){background-color:color-mix(in oklab,var(--_char-color-input)30%,transparent)}}.dark\\\\:bg-muted:is(.dark *){background-color:var(--_char-color-muted)}.dark\\\\:bg-red-500\\\\/10:is(.dark *){background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.dark\\\\:bg-red-500\\\\/10:is(.dark *){background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.dark\\\\:stroke-\\\\[2\\\\.5px\\\\]:is(.dark *){stroke-width:2.5px}.dark\\\\:text-amber-300:is(.dark *){color:var(--color-amber-300)}.dark\\\\:text-blue-300:is(.dark *){color:var(--color-blue-300)}.dark\\\\:text-blue-400:is(.dark *){color:var(--color-blue-400)}.dark\\\\:text-emerald-300:is(.dark *){color:var(--color-emerald-300)}.dark\\\\:text-foreground:is(.dark *){color:var(--_char-color-foreground)}.dark\\\\:text-orange-400:is(.dark *){color:var(--color-orange-400)}.dark\\\\:text-red-200:is(.dark *){color:var(--color-red-200)}.dark\\\\:text-red-300:is(.dark *){color:var(--color-red-300)}.dark\\\\:text-red-400:is(.dark *){color:var(--color-red-400)}.dark\\\\:text-slate-300:is(.dark *){color:var(--color-slate-300)}.dark\\\\:ring-amber-400\\\\/30:is(.dark *){--tw-ring-color:#fcbb004d}@supports (color:color-mix(in lab, red, red)){.dark\\\\:ring-amber-400\\\\/30:is(.dark *){--tw-ring-color:color-mix(in oklab,var(--color-amber-400)30%,transparent)}}.dark\\\\:ring-blue-400\\\\/25:is(.dark *){--tw-ring-color:#54a2ff40}@supports (color:color-mix(in lab, red, red)){.dark\\\\:ring-blue-400\\\\/25:is(.dark *){--tw-ring-color:color-mix(in oklab,var(--color-blue-400)25%,transparent)}}.dark\\\\:ring-border\\\\/30:is(.dark *){--tw-ring-color:var(--_char-color-border)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:ring-border\\\\/30:is(.dark *){--tw-ring-color:color-mix(in oklab,var(--_char-color-border)30%,transparent)}}.dark\\\\:ring-emerald-500\\\\/25:is(.dark *){--tw-ring-color:#00bb7f40}@supports (color:color-mix(in lab, red, red)){.dark\\\\:ring-emerald-500\\\\/25:is(.dark *){--tw-ring-color:color-mix(in oklab,var(--color-emerald-500)25%,transparent)}}.dark\\\\:ring-red-400\\\\/30:is(.dark *){--tw-ring-color:#ff65684d}@supports (color:color-mix(in lab, red, red)){.dark\\\\:ring-red-400\\\\/30:is(.dark *){--tw-ring-color:color-mix(in oklab,var(--color-red-400)30%,transparent)}}@media (hover:hover){.dark\\\\:hover\\\\:bg-accent\\\\/50:is(.dark *):hover{background-color:var(--_char-color-accent)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-accent\\\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--_char-color-accent)50%,transparent)}}.dark\\\\:hover\\\\:bg-input\\\\/50:is(.dark *):hover{background-color:var(--_char-color-input)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:hover\\\\:bg-input\\\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--_char-color-input)50%,transparent)}}.dark\\\\:hover\\\\:bg-muted-foreground\\\\/30:is(.dark *):hover{background-color:var(--_char-color-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(--_char-color-muted-foreground)30%,transparent)}}.dark\\\\:hover\\\\:text-accent-foreground:is(.dark *):hover{color:var(--_char-color-accent-foreground)}}.dark\\\\:focus-visible\\\\:ring-destructive\\\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--_char-color-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(--_char-color-destructive)40%,transparent)}}.dark\\\\:aria-invalid\\\\:ring-destructive\\\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--_char-color-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(--_char-color-destructive)40%,transparent)}}.dark\\\\:data-\\\\[state\\\\=checked\\\\]\\\\:bg-primary:is(.dark *)[data-state=checked]{background-color:var(--_char-color-primary)}.dark\\\\:data-\\\\[variant\\\\=destructive\\\\]\\\\:focus\\\\:bg-destructive\\\\/20:is(.dark *)[data-variant=destructive]:focus{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\\\:data-\\\\[variant\\\\=destructive\\\\]\\\\:focus\\\\:bg-destructive\\\\/20:is(.dark *)[data-variant=destructive]:focus{background-color:color-mix(in oklab,var(--_char-color-destructive)20%,transparent)}}.\\\\[\\\\&_\\\\[cmdk-group-heading\\\\]\\\\]\\\\:px-2 [cmdk-group-heading]{padding-inline:calc(var(--spacing)*2)}.\\\\[\\\\&_\\\\[cmdk-group-heading\\\\]\\\\]\\\\:py-1\\\\.5 [cmdk-group-heading]{padding-block:calc(var(--spacing)*1.5)}.\\\\[\\\\&_\\\\[cmdk-group-heading\\\\]\\\\]\\\\:text-xs [cmdk-group-heading]{font-size:var(--_char-font-size-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\\\[\\\\&_\\\\[cmdk-group-heading\\\\]\\\\]\\\\:font-medium [cmdk-group-heading]{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.\\\\[\\\\&_\\\\[cmdk-group-heading\\\\]\\\\]\\\\:text-muted-foreground [cmdk-group-heading]{color:var(--_char-color-muted-foreground)}.\\\\[\\\\&_p\\\\]\\\\:-mb-2 p{margin-bottom:calc(var(--spacing)*-2)}.\\\\[\\\\&_p\\\\]\\\\:leading-relaxed p{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\\\\[\\\\&_svg\\\\]\\\\:pointer-events-none svg{pointer-events:none}.\\\\[\\\\&_svg\\\\]\\\\:shrink-0 svg{flex-shrink:0}.\\\\[\\\\&_svg\\\\]\\\\:text-background svg{color:var(--_char-color-background)}.\\\\[\\\\&_svg\\\\]\\\\:text-black svg{color:var(--color-black)}@media (hover:hover){.hover\\\\:\\\\[\\\\&_svg\\\\]\\\\:text-destructive:hover svg{color:var(--_char-color-destructive)}}.\\\\[\\\\&_svg\\\\:not\\\\(\\\\[class\\\\*\\\\=\\\\'size-\\\\'\\\\]\\\\)\\\\]\\\\:size-3 svg:not([class*=size-]){width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.\\\\[\\\\&_svg\\\\:not\\\\(\\\\[class\\\\*\\\\=\\\\'size-\\\\'\\\\]\\\\)\\\\]\\\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\\\[\\\\&_svg\\\\:not\\\\(\\\\[class\\\\*\\\\=\\\\'text-\\\\'\\\\]\\\\)\\\\]\\\\:text-muted-foreground svg:not([class*=text-]){color:var(--_char-color-muted-foreground)}.\\\\[\\\\&\\\\:first-child\\\\[data-selected\\\\=true\\\\]_button\\\\]\\\\:rounded-l-md:first-child[data-selected=true] button{border-top-left-radius:var(--_char-radius-md);border-bottom-left-radius:var(--_char-radius-md)}.\\\\[\\\\.border-b\\\\]\\\\:pb-6.border-b{padding-bottom:calc(var(--spacing)*6)}.\\\\[\\\\.border-t\\\\]\\\\:pt-6.border-t{padding-top:calc(var(--spacing)*6)}:is(.rtl\\\\:\\\\*\\\\*\\\\:\\\\[\\\\.rdp-button\\\\\\\\_next\\\\>svg\\\\]\\\\:rotate-180:where(:dir(rtl),[dir=rtl],[dir=rtl] *) *):is(.rdp-button_next>svg),:is(.rtl\\\\:\\\\*\\\\*\\\\:\\\\[\\\\.rdp-button\\\\\\\\_previous\\\\>svg\\\\]\\\\:rotate-180:where(:dir(rtl),[dir=rtl],[dir=rtl] *) *):is(.rdp-button_previous>svg){rotate:180deg}.\\\\[\\\\[align\\\\=center\\\\]\\\\]\\\\:text-center[align=center]{text-align:center}.\\\\[\\\\[align\\\\=right\\\\]\\\\]\\\\:text-right[align=right]{text-align:right}:is(.\\\\*\\\\:\\\\[span\\\\]\\\\:last\\\\:flex>*):is(span):last-child{display:flex}:is(.\\\\*\\\\:\\\\[span\\\\]\\\\:last\\\\:items-center>*):is(span):last-child{align-items:center}:is(.\\\\*\\\\:\\\\[span\\\\]\\\\:last\\\\:gap-2>*):is(span):last-child{gap:calc(var(--spacing)*2)}:is(.data-\\\\[variant\\\\=destructive\\\\]\\\\:\\\\*\\\\:\\\\[svg\\\\]\\\\:\\\\!text-destructive[data-variant=destructive]>*):is(svg){color:var(--_char-color-destructive)!important}.\\\\[\\\\&\\\\:last-child\\\\>td\\\\:first-child\\\\]\\\\:rounded-bl-lg:last-child>td:first-child{border-bottom-left-radius:var(--_char-radius-lg)}.\\\\[\\\\&\\\\:last-child\\\\>td\\\\:last-child\\\\]\\\\:rounded-br-lg:last-child>td:last-child{border-bottom-right-radius:var(--_char-radius-lg)}.\\\\[\\\\&\\\\:last-child\\\\[data-selected\\\\=true\\\\]_button\\\\]\\\\:rounded-r-md:last-child[data-selected=true] button{border-top-right-radius:var(--_char-radius-md);border-bottom-right-radius:var(--_char-radius-md)}.\\\\[\\\\&\\\\:nth-child\\\\(2\\\\)\\\\[data-selected\\\\=true\\\\]_button\\\\]\\\\:rounded-l-md:nth-child(2)[data-selected=true] button{border-top-left-radius:var(--_char-radius-md);border-bottom-left-radius:var(--_char-radius-md)}.\\\\[\\\\&\\\\:where\\\\(\\\\>\\\\*\\\\)\\\\]\\\\:col-start-2:where(){grid-column-start:2}.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(--_char-font-size-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(--_char-color-foreground)}@supports (color:color-mix(in lab, red, red)){.\\\\[\\\\&\\\\>button\\\\]\\\\:bg-foreground\\\\/60>button{background-color:color-mix(in oklab,var(--_char-color-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(--_char-color-destructive)}}.\\\\[\\\\&\\\\>li\\\\]\\\\:mt-2>li{margin-top:calc(var(--spacing)*2)}.\\\\[\\\\&\\\\>span\\\\]\\\\:text-xs>span{font-size:var(--_char-font-size-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\\\[\\\\&\\\\>span\\\\]\\\\:opacity-70>span{opacity:.7}.\\\\[\\\\&\\\\>svg\\\\]\\\\:pointer-events-none>svg{pointer-events:none}.\\\\[\\\\&\\\\>svg\\\\]\\\\:size-3>svg{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.\\\\[\\\\&\\\\>svg\\\\]\\\\:size-3\\\\.5>svg{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.\\\\[\\\\&\\\\>svg\\\\]\\\\:size-4>svg{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\\\[\\\\&\\\\>svg\\\\]\\\\:translate-y-0\\\\.5>svg{--tw-translate-y:calc(var(--spacing)*.5);translate:var(--tw-translate-x)var(--tw-translate-y)}.\\\\[\\\\&\\\\>svg\\\\]\\\\:text-current>svg{color:currentColor}.\\\\[\\\\&\\\\>svg\\\\]\\\\:text-muted-foreground>svg{color:var(--_char-color-muted-foreground)}[data-slot=card-content] .\\\\[\\\\[data-slot\\\\=card-content\\\\]_\\\\&\\\\]\\\\:bg-transparent,[data-slot=popover-content] .\\\\[\\\\[data-slot\\\\=popover-content\\\\]_\\\\&\\\\]\\\\:bg-transparent{background-color:#0000}@media (hover:hover){a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-accent:hover{background-color:var(--_char-color-accent)}a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-destructive\\\\/90:hover{background-color:var(--_char-color-destructive)}@supports (color:color-mix(in lab, red, red)){a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-destructive\\\\/90:hover{background-color:color-mix(in oklab,var(--_char-color-destructive)90%,transparent)}}a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-primary\\\\/90:hover{background-color:var(--_char-color-primary)}@supports (color:color-mix(in lab, red, red)){a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-primary\\\\/90:hover{background-color:color-mix(in oklab,var(--_char-color-primary)90%,transparent)}}a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-secondary\\\\/90:hover{background-color:var(--_char-color-secondary)}@supports (color:color-mix(in lab, red, red)){a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:bg-secondary\\\\/90:hover{background-color:color-mix(in oklab,var(--_char-color-secondary)90%,transparent)}}a.\\\\[a\\\\&\\\\]\\\\:hover\\\\:text-accent-foreground:hover{color:var(--_char-color-accent-foreground)}}}@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}@keyframes char-shimmer{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes char-subtle-pulse{0%,to{opacity:1}50%{opacity:.85}}@keyframes char-slide-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}@keyframes char-fade-in-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes char-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 char-float{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(-30px)translate(20px)}66%{transform:translateY(20px)translate(-20px)}}@keyframes char-float-delayed{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(30px)translate(-30px)}66%{transform:translateY(-20px)translate(20px)}}@keyframes char-border-rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes char-pulse-success{0%,to{box-shadow:0 0 0 0 color-mix(in oklch,var(--_char-color-success),transparent 60%)}50%{box-shadow:0 0 0 8px #0000}}@keyframes char-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}@keyframes char-pulse-glow{0%,to{box-shadow:0 0 20px color-mix(in oklch,var(--_char-color-primary),transparent 90%)}50%{box-shadow:0 0 30px color-mix(in oklch,var(--_char-color-primary),transparent 80%)}}@keyframes char-gradient-x{0%,to{background-position:0%}50%{background-position:100%}}@keyframes char-glass-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}@keyframes char-aui-pulse{50%{opacity:.5}}.char-no-scrollbar::-webkit-scrollbar{display:none}.char-no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@media (hover:none){.char-scrollbar-thin{scrollbar-width:none}.char-scrollbar-thin::-webkit-scrollbar{display:none}}.aui-md,.aui-user-message-content{font-size:var(--text-base)}.aui-md{line-height:1.5}.aui-md p{margin-bottom:.75rem;line-height:1.5}.aui-md ul,.aui-md ol{margin-top:.5rem;margin-bottom:.75rem;padding-left:1.25rem}.aui-md li{margin-top:.25rem;margin-bottom:.25rem}.aui-md li p{margin-bottom:.25rem}.aui-md h1,.aui-md h2,.aui-md h3,.aui-md h4{margin-top:1rem;margin-bottom:.5rem}.aui-md pre{margin-top:.5rem;margin-bottom:.75rem}: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{font-family:var(--_char-font-sans);--aui-content:\\\"●\\\";content:var(--aui-content);margin-left:.25rem;margin-right:.25rem;animation:2s cubic-bezier(.4,0,.6,1) infinite char-aui-pulse}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0));filter:blur(var(--tw-exit-blur,0))}}@keyframes collapsible-down{0%{height:0}to{height:var(--radix-collapsible-content-height,var(--bits-collapsible-content-height,var(--reka-collapsible-content-height,var(--kb-collapsible-content-height,auto))))}}@keyframes collapsible-up{0%{height:var(--radix-collapsible-content-height,var(--bits-collapsible-content-height,var(--reka-collapsible-content-height,var(--kb-collapsible-content-height,auto))))}to{height:0}}\";\n\n/**\n * Get the shadow DOM compatible styles.\n * Use this when manually creating a shadow root.\n *\n * @example\n * const shadow = element.attachShadow({ mode: 'open' })\n * const style = document.createElement('style')\n * style.textContent = getShadowStyles()\n * shadow.appendChild(style)\n */\nexport function getShadowStyles(): string {\n\treturn WEBMCP_SHADOW_STYLES\n}\n","/**\n * Char - React Component\n *\n * The recommended way to use Char in React applications.\n * For non-React apps, use the web component export instead.\n *\n * @example Basic usage with ticket auth (SSR-friendly)\n * ```tsx\n * import { Char } from '@mcp-b/char'\n *\n * function App() {\n * const [ticket, setTicket] = useState<TicketAuth | null>(null)\n *\n * useEffect(() => {\n * fetch('/api/auth/ticket', { method: 'POST' })\n * .then(res => res.json())\n * .then(setTicket)\n * }, [])\n *\n * if (!ticket) return <div>Loading...</div>\n *\n * return (\n * <Char\n * ticketAuth={ticket}\n * open={true}\n * onClose={() => console.log('closed')}\n * />\n * )\n * }\n * ```\n *\n * @example With ID token (SPA-friendly)\n * ```tsx\n * import { Char } from '@mcp-b/char'\n * import { useAuth } from 'your-auth-provider'\n *\n * function App() {\n * const { idToken } = useAuth()\n *\n * return (\n * <Char\n * authToken={idToken}\n * open={true}\n * />\n * )\n * }\n * ```\n *\n * @example Development mode\n * ```tsx\n * <Char\n * devMode={{\n * anthropicApiKey: import.meta.env.VITE_ANTHROPIC_API_KEY,\n * useLocalApi: true,\n * }}\n * open={true}\n * />\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { FC } from 'react'\n\nimport { resolveDevMode, type DevModeConfig } from './utils/dev-mode'\nimport type { TicketAuth } from '@char-ai/auth'\n\nimport { AgentThread } from './public/AgentThread'\nimport { ShadowRoot } from './components/agent/ShadowRoot'\nimport { WEBMCP_SHADOW_STYLES } from './generated/inline-styles'\nimport { WEBMCP_PRODUCTION_API_BASE } from './utils/constants'\n\n// Re-export types for consumers\nexport type { TicketAuth } from '@char-ai/auth'\n\n// Re-export MCP tools provider for consumers who want to access tools outside of Char\nexport { MCPToolsProvider, useMCPTools } from './providers/MCPToolsProvider'\nexport type { MCPToolsContextValue, MCPToolsProviderProps } from './providers/MCPToolsProvider'\n\nexport type { DevModeConfig } from './utils/dev-mode'\n\n/**\n * Props for the Char component\n */\nexport interface CharProps {\n\t/**\n\t * IDP token for SSO-first authentication.\n\t *\n\t * Pass your existing IDP token (from Okta, Azure AD, Auth0, Google, etc.)\n\t * and the backend will validate it against your organization's configured IDP.\n\t *\n\t * When provided:\n\t * - Messages persist across refreshes (Cloudflare Durable Objects)\n\t * - User ID extracted from token's sub claim\n\t * - Tools shared across all your organization's apps\n\t *\n\t * When NOT provided:\n\t * - Anonymous mode with Durable Objects\n\t * - Requires anthropicApiKey for AI calls\n\t * - Localhost-only for security\n\t */\n\tauthToken?: string\n\n\t/**\n\t * OIDC client ID for audience validation.\n\t * Required when using `authToken` authentication.\n\t *\n\t * This must match the token's `aud` claim and be in the organization's\n\t * `allowed_audiences` list (configured in the Char dashboard).\n\t */\n\tclientId?: string\n\n\t/**\n\t * Pre-fetched ticket for SSR-friendly authentication.\n\t *\n\t * Benefits:\n\t * - IDP token never exposed to browser (in SSR mode)\n\t * - No JWKS fetch on every connection (validation done once)\n\t * - Ticket is short-lived (60s default) and single-use\n\t */\n\tticketAuth?: TicketAuth\n\n\t/**\n\t * Controlled open state.\n\t * When provided, the host controls whether the agent UI is open or collapsed.\n\t */\n\topen?: boolean\n\n\t/**\n\t * Additional CSS class name for the container.\n\t * Useful for applying custom container styles.\n\t */\n\tclassName?: string\n\n\t/**\n\t * Callback when the close button is clicked.\n\t * Use this to control visibility from the host app.\n\t */\n\tonClose?: () => void\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\t/**\n\t * Enable debug tools for inspecting embedded agent internal state.\n\t * @default false\n\t */\n\tenableDebugTools?: boolean\n}\n\n/**\n * Get the default API base URL.\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 * Char - Drop-in AI chat widget for React\n *\n * A fully self-contained chat widget with:\n * - SSO-first authentication (use your existing IDP token)\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 * - Shadow DOM isolation (styles don't leak in or out)\n *\n * @example\n * ```tsx\n * <Char\n * ticketAuth={{ ticket, userId, orgId }}\n * open={isOpen}\n * onClose={() => setIsOpen(false)}\n * />\n * ```\n */\nexport const Char: FC<CharProps> = ({\n\tauthToken,\n\tclientId,\n\tticketAuth,\n\topen,\n\tdevMode,\n\tenableDebugTools = false,\n\tclassName,\n\tonClose,\n}) => {\n\tconst { devMode: resolvedDevMode, isEmpty } = resolveDevMode(devMode)\n\tconst apiBase = getDefaultApiBase(resolvedDevMode?.useLocalApi)\n\tconst authMode = ticketAuth ? 'ticket' : authToken ? 'sso-first' : 'anonymous'\n\n\tif (devMode && isEmpty) {\n\t\treturn (\n\t\t\t<ShadowRoot styles={WEBMCP_SHADOW_STYLES}>\n\t\t\t\t<div className=\"flex flex-col items-center justify-center h-full p-6 text-center gap-2\">\n\t\t\t\t\t<p className=\"text-sm font-medium text-destructive\">devMode Configuration Error</p>\n\t\t\t\t\t<p className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\tdevMode was provided but contains no usable values.\n\t\t\t\t\t\tProvide a valid API key (anthropicApiKey/openaiApiKey) or set useLocalApi: true.\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t</ShadowRoot>\n\t\t)\n\t}\n\n\tif (typeof window !== 'undefined') {\n\t\tconsole.debug('[Char] Initialized', {\n\t\t\thasAuthToken: !!authToken,\n\t\t\thasClientId: !!clientId,\n\t\t\thasTicketAuth: !!ticketAuth,\n\t\t\tauthMode,\n\t\t\tmode: resolvedDevMode ? 'development' : 'production',\n\t\t\tapiBase,\n\t\t})\n\t}\n\n\tconst voiceEnabled = !resolvedDevMode || !!resolvedDevMode.openaiApiKey\n\tconst anthropicApiKey = resolvedDevMode?.anthropicApiKey\n\n\treturn (\n\t\t<ShadowRoot styles={WEBMCP_SHADOW_STYLES}>\n\t\t\t<AgentThread\n\t\t\t\tapiBase={apiBase}\n\t\t\t\tauthToken={authToken}\n\t\t\t\tclientId={clientId}\n\t\t\t\tticketAuth={ticketAuth}\n\t\t\t\tanthropicApiKey={anthropicApiKey}\n\t\t\t\ttokenEndpoint={voiceEnabled ? `${apiBase}/api/realtime/session` : undefined}\n\t\t\t\tautoConnectLocal={true}\n\t\t\t\topen={open}\n\t\t\t\tenableDebugTools={enableDebugTools}\n\t\t\t\tclassName={className ?? 'h-full w-full'}\n\t\t\t\tonClose={onClose}\n\t\t\t/>\n\t\t</ShadowRoot>\n\t)\n}\n\nexport default Char\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/host/char-iframe-proxy.ts","../src/utils/constants.ts","../src/utils/css-sanitizer.ts","../src/utils/css-resolver.ts","../src/utils/css-variables.ts","../src/display-mode-policy.ts","../src/utils/display-mode.ts","../src/utils/host-context-merge.ts","../src/utils/parse-boolean-attribute.ts","../src/web-component.tsx","../src/shell-component.ts"],"sourcesContent":["/**\n * CharIframeProxy\n *\n * Host-side relay that bridges MCP server-to-client responses from the page's\n * TabServerTransport back to the iframe (embedded agent).\n *\n * Client-to-server messages (iframe → host) are handled directly by\n * TabServerTransport via allowedOrigins, so no relay is needed in that\n * direction.\n *\n * Zero runtime dependencies — uses only browser postMessage APIs.\n */\n\nexport class CharIframeProxy {\n\tprivate _cleanup: (() => void)[] = []\n\n\tconstructor(\n\t\tprivate _iframe: HTMLIFrameElement,\n\t\tprivate _iframeOrigin: string,\n\t\tprivate _channelId = 'mcp-default'\n\t) {}\n\n\tstart(): void {\n\t\t// window → iframe: relay server-to-client messages so the iframe client transport picks them up\n\t\tconst fromTab = (event: MessageEvent) => {\n\t\t\tif (event.source !== window) return\n\t\t\tconst d = event.data\n\t\t\tif (!d || d.channel !== this._channelId || d.type !== 'mcp' || d.direction !== 'server-to-client') return\n\t\t\tif (d._proxied) return // defense-in-depth: don't relay our own relayed messages\n\t\t\tif (!this._iframe.contentWindow) {\n\t\t\t\tconsole.error('[CharIframeProxy] Cannot relay to iframe: contentWindow is null')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis._iframe.contentWindow.postMessage(d, this._iframeOrigin)\n\t\t}\n\n\t\twindow.addEventListener('message', fromTab)\n\t\tthis._cleanup = [\n\t\t\t() => window.removeEventListener('message', fromTab),\n\t\t]\n\t}\n\n\tdestroy(): void {\n\t\tfor (const fn of this._cleanup) fn()\n\t\tthis._cleanup.length = 0\n\t}\n}\n","export const WEBMCP_PRODUCTION_API_BASE = 'https://app.usechar.ai'\n","/**\n * Maximum allowed length for CSS custom property values transported to iframe.\n *\n * NOTE: This value and the blocked-token policy intentionally mirror\n * `packages/shared-types/src/schemas/embed-bridge.ts` so validation happens\n * both before transport (host) and at contract parse-time (iframe).\n *\n * CONTROL_CHAR_PATTERN here is intentionally more permissive than\n * embed-bridge.ts: it allows tabs/newlines/CR/FF because\n * normalizeCssFormattingWhitespace converts them to spaces before the\n * control-char check. The iframe-side schema (embed-bridge.ts) uses\n * the stricter pattern as defense-in-depth for values that bypass\n * host-side sanitization.\n */\nexport const MAX_CSS_VARIABLE_VALUE_LENGTH = 1024\nexport const MAX_HOST_FONT_CSS_LENGTH = 16_384\n\nconst CONTROL_CHAR_PATTERN = /[\\u0000-\\u0008\\u000b\\u000e-\\u001f\\u007f]/u\nconst FONT_RULES_PATTERN = /^(?:\\s*@font-face\\s*\\{[^{}]*\\}\\s*)+$/iu\nconst CSS_COMMENT_PATTERN = /\\/\\*[\\s\\S]*?\\*\\//g\nconst CSS_FORMATTING_WHITESPACE_PATTERN = /[\\t\\n\\r\\f]+/gu\n\n/**\n * Normalizes CSS values for dangerous-token scanning.\n * Lowercases and removes CSS comments/whitespace/control chars to catch obfuscation.\n */\nfunction normalizeForSecurityScan(value: string): string {\n\tconst withoutComments = value.replace(CSS_COMMENT_PATTERN, '')\n\treturn withoutComments.toLowerCase().replace(/[\\s\\u0000-\\u001f\\u007f]+/gu, '')\n}\n\n/**\n * Collapses CSS formatting whitespace (tabs, newlines, carriage returns, form feeds)\n * into single spaces. Applied to the output value before trimming, so multiline\n * host-provided values (e.g., font stacks) become single-line without losing\n * meaningful token boundaries. This also ensures split-token obfuscation\n * (e.g., \"java\\nscript:\") is collapsed before the security scan.\n */\nfunction normalizeCssFormattingWhitespace(value: string): string {\n\treturn value.replace(CSS_FORMATTING_WHITESPACE_PATTERN, ' ')\n}\n\n/**\n * Sanitizes host-provided CSS variable values before iframe transport.\n * Returns `undefined` for unsafe or invalid values.\n *\n * @param value - The raw CSS property value.\n * @param variableName - Optional variable name for diagnostic logging.\n */\nexport function sanitizeCssVariableValue(value: string, variableName?: string): string | undefined {\n\tconst trimmed = normalizeCssFormattingWhitespace(value).trim()\n\tif (!trimmed) return undefined\n\tif (trimmed.length > MAX_CSS_VARIABLE_VALUE_LENGTH) {\n\t\tconsole.warn(`[Char] CSS variable ${variableName ?? '(unknown)'} rejected: value exceeds max length (${trimmed.length} > ${MAX_CSS_VARIABLE_VALUE_LENGTH})`)\n\t\treturn undefined\n\t}\n\tif (CONTROL_CHAR_PATTERN.test(trimmed)) {\n\t\tconsole.warn(`[Char] CSS variable ${variableName ?? '(unknown)'} rejected: contains control characters`)\n\t\treturn undefined\n\t}\n\n\tconst normalized = normalizeForSecurityScan(trimmed)\n\tconst blockedToken = getBlockedCssVariableToken(normalized)\n\tif (blockedToken) return warnAndReject(variableName, blockedToken)\n\n\treturn trimmed\n}\n\n/**\n * Sanitizes host-provided font CSS before iframe injection.\n * Only `@font-face` rules are allowed.\n */\nexport function sanitizeHostFontCss(fontCss: string): string | undefined {\n\tconst trimmed = fontCss.trim()\n\tif (!trimmed) return undefined\n\tif (trimmed.length > MAX_HOST_FONT_CSS_LENGTH) {\n\t\tconsole.warn(`[Char] Host font CSS rejected: value exceeds max length (${trimmed.length} > ${MAX_HOST_FONT_CSS_LENGTH})`)\n\t\treturn undefined\n\t}\n\tif (CONTROL_CHAR_PATTERN.test(trimmed)) {\n\t\tconsole.warn('[Char] Host font CSS rejected: contains control characters')\n\t\treturn undefined\n\t}\n\n\tconst normalized = normalizeForSecurityScan(trimmed)\n\tconst blockedToken = getBlockedFontToken(normalized)\n\tif (blockedToken) {\n\t\tconsole.warn(`[Char] Host font CSS rejected: contains blocked token \"${blockedToken}\"`)\n\t\treturn undefined\n\t}\n\n\tconst withoutComments = trimmed.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '').trim()\n\tif (!FONT_RULES_PATTERN.test(withoutComments)) {\n\t\tconsole.warn('[Char] Host font CSS rejected: only @font-face rules are allowed')\n\t\treturn undefined\n\t}\n\n\treturn trimmed\n}\n\nfunction getBlockedCssVariableToken(normalizedValue: string): string | undefined {\n\tif (normalizedValue.includes('javascript:')) return 'javascript:'\n\tif (normalizedValue.includes('vbscript:')) return 'vbscript:'\n\tif (normalizedValue.includes('expression(')) return 'expression('\n\tif (normalizedValue.includes('@import')) return '@import'\n\tif (normalizedValue.includes('-moz-binding')) return '-moz-binding'\n\tif (normalizedValue.includes('url(')) return 'url('\n\treturn undefined\n}\n\nfunction getBlockedFontToken(normalizedValue: string): string | undefined {\n\tif (normalizedValue.includes('javascript:')) return 'javascript:'\n\tif (normalizedValue.includes('vbscript:')) return 'vbscript:'\n\tif (normalizedValue.includes('expression(')) return 'expression('\n\tif (normalizedValue.includes('-moz-binding')) return '-moz-binding'\n\treturn undefined\n}\n\nfunction warnAndReject(variableName: string | undefined, blockedToken: string): undefined {\n\tconsole.warn(`[Char] CSS variable ${variableName ?? '(unknown)'} rejected: contains blocked token \"${blockedToken}\"`)\n\treturn undefined\n}\n","/**\n * CSS var() Resolver\n *\n * Recursively resolves CSS custom property references (`var(--x, fallback)`)\n * to concrete values using getComputedStyle(). Necessary because `var()`\n * references are not valid across iframe boundaries.\n *\n * Handles nested var() references, fallbacks, and cycle detection.\n */\n\nexport const MAX_CSS_VAR_RESOLVE_DEPTH = 12\n\nexport function findMatchingParen(value: string, openParenIndex: number): number {\n\tlet depth = 1\n\tfor (let i = openParenIndex + 1; i < value.length; i++) {\n\t\tconst char = value[i]\n\t\tif (char === '(') depth += 1\n\t\telse if (char === ')') depth -= 1\n\t\tif (depth === 0) return i\n\t}\n\treturn -1\n}\n\nexport function splitTopLevelComma(value: string): [string, string | undefined] {\n\tlet depth = 0\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst char = value[i]\n\t\tif (char === '(') depth += 1\n\t\telse if (char === ')') depth = Math.max(0, depth - 1)\n\t\telse if (char === ',' && depth === 0) return [value.slice(0, i), value.slice(i + 1)]\n\t}\n\treturn [value, undefined]\n}\n\nexport function resolveFallback(\n\tfallback: string | undefined,\n\tcomputed: CSSStyleDeclaration,\n\tseen: Set<string>,\n\tdepth: number,\n): string | undefined {\n\tif (!fallback) return undefined\n\treturn resolveCssValue(fallback, computed, seen, depth + 1) || undefined\n}\n\nexport function resolveCssVariable(\n\tvariableName: string,\n\tfallback: string | undefined,\n\tcomputed: CSSStyleDeclaration,\n\tseen: Set<string>,\n\tdepth: number,\n): string | undefined {\n\tif (depth > MAX_CSS_VAR_RESOLVE_DEPTH) {\n\t\tconsole.warn(`[Char] CSS variable resolution depth exceeded for \"${variableName}\". Possible circular reference.`)\n\t\treturn fallback?.trim()\n\t}\n\n\tif (!variableName.startsWith('--') || seen.has(variableName)) {\n\t\treturn resolveFallback(fallback, computed, seen, depth)\n\t}\n\n\tconst nextSeen = new Set(seen)\n\tnextSeen.add(variableName)\n\n\tconst rawValue = computed.getPropertyValue(variableName).trim()\n\tif (rawValue) {\n\t\tconst resolvedRaw = resolveCssValue(rawValue, computed, nextSeen, depth + 1)\n\t\tif (resolvedRaw) return resolvedRaw\n\t}\n\n\treturn resolveFallback(fallback, computed, seen, depth)\n}\n\nexport function resolveCssValue(\n\tvalue: string,\n\tcomputed: CSSStyleDeclaration,\n\tseen: Set<string>,\n\tdepth = 0,\n): string {\n\tconst trimmed = value.trim()\n\tif (!trimmed || !trimmed.includes('var(') || depth > MAX_CSS_VAR_RESOLVE_DEPTH) {\n\t\treturn trimmed\n\t}\n\n\tlet cursor = 0\n\tlet resolved = ''\n\tlet replacedAny = false\n\n\twhile (cursor < trimmed.length) {\n\t\tconst varStart = trimmed.indexOf('var(', cursor)\n\t\tif (varStart === -1) {\n\t\t\tresolved += trimmed.slice(cursor)\n\t\t\tbreak\n\t\t}\n\n\t\tresolved += trimmed.slice(cursor, varStart)\n\n\t\tconst openParenIndex = varStart + 3\n\t\tconst closeParenIndex = findMatchingParen(trimmed, openParenIndex)\n\t\tif (closeParenIndex === -1) {\n\t\t\tresolved += trimmed.slice(varStart)\n\t\t\tbreak\n\t\t}\n\n\t\tconst rawArgs = trimmed.slice(openParenIndex + 1, closeParenIndex)\n\t\tconst [rawVariableName, rawFallback] = splitTopLevelComma(rawArgs)\n\t\tconst variableName = rawVariableName.trim()\n\t\tconst fallback = rawFallback?.trim()\n\n\t\tconst replacement = variableName\n\t\t\t? resolveCssVariable(variableName, fallback, computed, seen, depth + 1)\n\t\t\t: undefined\n\n\t\tif (replacement !== undefined) {\n\t\t\tresolved += replacement\n\t\t\treplacedAny = true\n\t\t} else {\n\t\t\tresolved += trimmed.slice(varStart, closeParenIndex + 1)\n\t\t}\n\n\t\tcursor = closeParenIndex + 1\n\t}\n\n\tconst normalized = resolved.trim()\n\tif (!replacedAny || !normalized.includes('var(')) {\n\t\treturn normalized\n\t}\n\n\treturn resolveCssValue(normalized, computed, seen, depth + 1)\n}\n","/**\n * Public CSS variable names for the Char widget.\n *\n * These are the external API — host pages set these to customise the widget.\n * We maintain static lists because `getComputedStyle()` cannot enumerate\n * custom properties.\n *\n * Source of truth:\n * - `src/styles/globals.css` (`--char-*`)\n * - WebMCP ext-apps UI spec (`--color-*`, `--font-*`, etc.)\n */\n\nconst CHAR_PUBLIC_VARIABLE_NAMES = [\n\t// Colors - Core\n\t'--char-color-background',\n\t'--char-color-foreground',\n\t'--char-color-card',\n\t'--char-color-card-foreground',\n\t'--char-color-popover',\n\t'--char-color-popover-foreground',\n\t'--char-color-primary',\n\t'--char-color-primary-foreground',\n\t'--char-color-secondary',\n\t'--char-color-secondary-foreground',\n\t'--char-color-muted',\n\t'--char-color-muted-foreground',\n\t'--char-color-accent',\n\t'--char-color-accent-foreground',\n\t'--char-color-destructive',\n\t'--char-color-destructive-foreground',\n\t'--char-color-border',\n\n\t// Colors - Semantic\n\t'--char-color-success',\n\t'--char-color-warning',\n\t'--char-color-error',\n\n\t// Colors - Derived\n\t'--char-color-input',\n\t'--char-color-ring',\n\n\t// Message Bubbles\n\t'--char-user-bubble-bg',\n\t'--char-user-bubble-text',\n\t'--char-assistant-bubble-bg',\n\t'--char-assistant-bubble-text',\n\n\t// Composer\n\t'--char-composer-bg',\n\t'--char-composer-border',\n\t'--char-composer-text',\n\t'--char-composer-placeholder',\n\t'--char-composer-button-bg',\n\t'--char-composer-button-text',\n\n\t// Tool Cards\n\t'--char-tool-bg',\n\t'--char-tool-border',\n\t'--char-tool-text',\n\t'--char-tool-header-bg',\n\t'--char-tool-approve-bg',\n\t'--char-tool-approve-text',\n\t'--char-tool-deny-bg',\n\t'--char-tool-deny-text',\n\n\t// Code Blocks\n\t'--char-code-bg',\n\t'--char-code-text',\n\t'--char-code-header-bg',\n\n\t// Sizing\n\t'--char-radius',\n\t'--char-radius-sm',\n\t'--char-radius-md',\n\t'--char-radius-lg',\n\t'--char-radius-xl',\n\t'--char-radius-2xl',\n\t'--char-radius-3xl',\n\t'--char-radius-full',\n\t'--char-spacing-unit',\n\n\t// Typography\n\t'--char-font-sans',\n\t'--char-font-mono',\n\t'--char-font-size-xs',\n\t'--char-font-size-sm',\n\t'--char-font-size-base',\n\t'--char-font-size-lg',\n\n\t// Motion\n\t'--char-duration-fast',\n\t'--char-duration-normal',\n\t'--char-duration-slow',\n\t'--char-easing-default',\n\t'--char-easing-spring',\n\n\t// Z-index\n\t'--char-z-base',\n\t'--char-z-content',\n\t'--char-z-overlay',\n\t'--char-z-max',\n\n\t// Shadows\n\t'--char-shadow-sm',\n\t'--char-shadow-md',\n\t'--char-shadow-lg',\n\n\t// Blur\n\t'--char-blur-sm',\n\t'--char-blur-md',\n\t'--char-blur-lg',\n] as const\n\nconst MCP_UI_STYLE_VARIABLE_NAMES = [\n\t// Background colors\n\t'--color-background-primary',\n\t'--color-background-secondary',\n\t'--color-background-tertiary',\n\t'--color-background-inverse',\n\t'--color-background-ghost',\n\t'--color-background-info',\n\t'--color-background-danger',\n\t'--color-background-success',\n\t'--color-background-warning',\n\t'--color-background-disabled',\n\n\t// Text colors\n\t'--color-text-primary',\n\t'--color-text-secondary',\n\t'--color-text-tertiary',\n\t'--color-text-inverse',\n\t'--color-text-ghost',\n\t'--color-text-info',\n\t'--color-text-danger',\n\t'--color-text-success',\n\t'--color-text-warning',\n\t'--color-text-disabled',\n\n\t// Border colors\n\t'--color-border-primary',\n\t'--color-border-secondary',\n\t'--color-border-tertiary',\n\t'--color-border-inverse',\n\t'--color-border-ghost',\n\t'--color-border-info',\n\t'--color-border-danger',\n\t'--color-border-success',\n\t'--color-border-warning',\n\t'--color-border-disabled',\n\n\t// Ring colors\n\t'--color-ring-primary',\n\t'--color-ring-secondary',\n\t'--color-ring-inverse',\n\t'--color-ring-info',\n\t'--color-ring-danger',\n\t'--color-ring-success',\n\t'--color-ring-warning',\n\n\t// Typography - Family\n\t'--font-sans',\n\t'--font-mono',\n\n\t// Typography - Weight\n\t'--font-weight-normal',\n\t'--font-weight-medium',\n\t'--font-weight-semibold',\n\t'--font-weight-bold',\n\n\t// Typography - Text Size\n\t'--font-text-xs-size',\n\t'--font-text-sm-size',\n\t'--font-text-md-size',\n\t'--font-text-lg-size',\n\n\t// Typography - Heading Size\n\t'--font-heading-xs-size',\n\t'--font-heading-sm-size',\n\t'--font-heading-md-size',\n\t'--font-heading-lg-size',\n\t'--font-heading-xl-size',\n\t'--font-heading-2xl-size',\n\t'--font-heading-3xl-size',\n\n\t// Typography - Text Line Height\n\t'--font-text-xs-line-height',\n\t'--font-text-sm-line-height',\n\t'--font-text-md-line-height',\n\t'--font-text-lg-line-height',\n\n\t// Typography - Heading Line Height\n\t'--font-heading-xs-line-height',\n\t'--font-heading-sm-line-height',\n\t'--font-heading-md-line-height',\n\t'--font-heading-lg-line-height',\n\t'--font-heading-xl-line-height',\n\t'--font-heading-2xl-line-height',\n\t'--font-heading-3xl-line-height',\n\n\t// Border radius\n\t'--border-radius-xs',\n\t'--border-radius-sm',\n\t'--border-radius-md',\n\t'--border-radius-lg',\n\t'--border-radius-xl',\n\t'--border-radius-full',\n\n\t// Border width\n\t'--border-width-regular',\n\n\t// Shadows\n\t'--shadow-hairline',\n\t'--shadow-sm',\n\t'--shadow-md',\n\t'--shadow-lg',\n] as const\n\nexport const CHAR_CSS_VARIABLE_NAMES = [\n\t...CHAR_PUBLIC_VARIABLE_NAMES,\n\t...MCP_UI_STYLE_VARIABLE_NAMES,\n] as const\n","import type { CharDisplayMode } from './types'\nexport type { CharDisplayMode } from './types'\n\ntype AssertTrue<T extends true> = T\n\n/**\n * Default display modes advertised by Char hosts.\n *\n * Order matters for fallback behavior. When a preferred mode is unavailable,\n * the first available mode is selected.\n *\n * @public\n */\nexport const DEFAULT_AVAILABLE_DISPLAY_MODES = [\n\t'inline',\n\t'fullscreen',\n\t'pip',\n] as const satisfies readonly CharDisplayMode[]\n\n/**\n * Allowed display mode values for Char host policy resolution.\n */\ntype DisplayModesFromDefaults = (typeof DEFAULT_AVAILABLE_DISPLAY_MODES)[number]\n\ntype _AssertDisplayModesStayInSync = AssertTrue<\n\t[DisplayModesFromDefaults] extends [CharDisplayMode]\n\t\t? [CharDisplayMode] extends [DisplayModesFromDefaults]\n\t\t\t? true\n\t\t\t: false\n\t\t: false\n>\n\n/**\n * Runtime guard for Char display mode values.\n *\n * @param value - Raw value from host attributes, events, or external input.\n * @returns `true` when the value is one of `inline`, `fullscreen`, or `pip`.\n *\n * @public\n */\nexport function isDisplayMode(\n\tvalue: string | null | undefined,\n): value is CharDisplayMode {\n\treturn value === 'inline' || value === 'fullscreen' || value === 'pip'\n}\n\n/**\n * Checks whether a display mode represents an expanded agent surface.\n *\n * Expanded modes are:\n * - `inline` (panel-style)\n * - `fullscreen` (viewport-filling)\n *\n * Collapsed mode is:\n * - `pip` (launcher-only)\n *\n * @param mode - Current display mode from host context.\n * @returns `true` for expanded modes and `false` for collapsed/undefined modes.\n *\n * @public\n */\nexport function isExpandedDisplayMode(mode: CharDisplayMode | undefined): boolean {\n\treturn mode === 'inline' || mode === 'fullscreen'\n}\n\n/**\n * Resolves a preferred display mode against host-supported modes.\n *\n * An empty `availableModes` array means \"no constraint\" — the preferred mode\n * is returned unconditionally. This is intentional: it allows callers to opt\n * out of mode filtering without a separate code path.\n *\n * @param preferred - Preferred mode requested by host policy.\n * @param availableModes - Supported modes advertised by the host.\n * @returns Preferred mode when supported, otherwise the first available mode.\n *\n * @public\n */\nexport function resolveSupportedDisplayMode(\n\tpreferred: CharDisplayMode,\n\tavailableModes: readonly CharDisplayMode[] = DEFAULT_AVAILABLE_DISPLAY_MODES,\n): CharDisplayMode {\n\tif (availableModes.length === 0) {\n\t\treturn preferred\n\t}\n\n\tif (availableModes.includes(preferred)) {\n\t\treturn preferred\n\t}\n\n\tconsole.debug(`[Char] Display mode \"${preferred}\" not in available modes [${availableModes.join(', ')}], using \"${availableModes[0]}\"`)\n\treturn availableModes[0]\n}\n\n/**\n * Resolves Char's standard host display-mode policy.\n *\n * Policy:\n * - Closed state to `pip`\n * - Open on desktop to `inline`\n * - Open on narrow viewport to `fullscreen`\n *\n * The resolved mode is then constrained to `availableModes`.\n *\n * @param options - Host orchestration inputs: `open`, `isNarrowViewport`,\n * and optional `availableModes`.\n * @returns Final mode that satisfies policy and availability constraints.\n *\n * @public\n */\nexport function resolvePolicyDisplayMode(options: {\n\topen: boolean\n\tisNarrowViewport: boolean\n\tavailableModes?: readonly CharDisplayMode[]\n}): CharDisplayMode {\n\tconst availableModes = options.availableModes ?? DEFAULT_AVAILABLE_DISPLAY_MODES\n\tconst preferred: CharDisplayMode = options.open\n\t\t? options.isNarrowViewport\n\t\t\t? 'fullscreen'\n\t\t\t: 'inline'\n\t\t: 'pip'\n\n\treturn resolveSupportedDisplayMode(preferred, availableModes)\n}\n","import type { CharDisplayMode } from '../types'\n\nimport { isDisplayMode } from '../display-mode-policy'\n\nexport function resolveDisplayModeFromAttribute(\n\tdisplayModeAttr: string | null,\n): CharDisplayMode | undefined {\n\tif (!isDisplayMode(displayModeAttr)) {\n\t\treturn undefined\n\t}\n\n\treturn displayModeAttr\n}\n","/**\n * Host Context Merge Utilities\n *\n * Canonical merge logic for CharHostContext deltas. Used by both the host-side\n * web component and the iframe-side useHostContext hook to ensure identical\n * merge behavior on both sides of the postMessage bridge.\n */\n\nimport type { CharHostContext } from '../types'\n\nexport function mergeStyles(\n\tcurrent: CharHostContext['styles'] | undefined,\n\tpatch: CharHostContext['styles'] | undefined,\n): CharHostContext['styles'] | undefined {\n\tif (!patch) return current\n\treturn {\n\t\t...current,\n\t\t...patch,\n\t\t// variables are sent as a snapshot so removals propagate\n\t\tvariables: patch.variables ?? current?.variables,\n\t\tfonts: patch.fonts ?? current?.fonts,\n\t}\n}\n\nexport function shallowMerge<T extends object>(\n\tcurrent: T | undefined,\n\tpatch: T | undefined,\n): T | undefined {\n\tif (!patch) return current\n\treturn { ...current, ...patch }\n}\n\nexport function mergeHostContext(\n\tcurrent: CharHostContext | null,\n\tpatch: CharHostContext,\n): CharHostContext {\n\tconst previous = current ?? {}\n\treturn {\n\t\t...previous,\n\t\t...patch,\n\t\tstyles: mergeStyles(previous.styles, patch.styles),\n\t\tcontainerDimensions: shallowMerge(previous.containerDimensions, patch.containerDimensions),\n\t\tdeviceCapabilities: shallowMerge(previous.deviceCapabilities, patch.deviceCapabilities),\n\t\tsafeAreaInsets: shallowMerge(previous.safeAreaInsets, patch.safeAreaInsets),\n\t\thostCapabilities: shallowMerge(previous.hostCapabilities, patch.hostCapabilities),\n\t}\n}\n","/**\n * Attribute helper treating any value except `null` and `'false'` as enabled.\n */\nexport function parseBooleanAttribute(value: string | null): boolean {\n\treturn value !== null && value !== 'false'\n}\n","/**\n * Char - Web Component (iframe-based)\n *\n * A vanilla custom element that creates an iframe pointing to the SaaS app's\n * `/embed/` entrypoint. Exposes `connect()`, CSS variable theming, and DOM events\n * while keeping host and iframe concerns isolated.\n *\n * ## Authentication (Imperative API)\n *\n * Use the `connect()` method for secure authentication.\n *\n * @example Vanilla JS\n * ```js\n * const agent = document.querySelector('char-agent')\n * agent.connect({ idToken: 'eyJhbGciOi...', clientId: 'your-client-id' })\n * ```\n *\n * @example React\n * ```tsx\n * const agentRef = useRef<CharAgentElement>(null)\n * useEffect(() => {\n * agentRef.current?.connect({ idToken: session.idToken, clientId: 'your-client-id' })\n * }, [session.idToken])\n * return <char-agent ref={agentRef} />\n * ```\n *\n * @example CSS variable theming\n * ```css\n * char-agent {\n * --char-color-primary: #0f766e;\n * --char-radius: 12px;\n * }\n * ```\n */\n\nimport type {\n\tCharErrorDetail,\n\tCharContainerDimensions,\n\tCharDeviceCapabilities,\n\tCharDisplayMode,\n\tCharHostCapabilities,\n\tCharHostContext,\n\tCharHostToIframeMessage,\n\tCharOpenLinkDetail,\n\tCharRequestDisplayModeDetail,\n\tCharSizeChangedDetail,\n\tConnectOptions,\n\tDevModeConfig,\n\tTicketAuth,\n} from './types'\n\nimport { CharIframeProxy } from './host/char-iframe-proxy'\nimport { WEBMCP_PRODUCTION_API_BASE } from './utils/constants'\nimport { sanitizeCssVariableValue } from './utils/css-sanitizer'\nimport { resolveCssValue } from './utils/css-resolver'\nimport { CHAR_CSS_VARIABLE_NAMES } from './utils/css-variables'\nimport { resolveDisplayModeFromAttribute } from './utils/display-mode'\nimport { mergeHostContext } from './utils/host-context-merge'\n\n/**\n * Shared options used by custom events emitted from the host element.\n */\nconst CHAR_CUSTOM_EVENT_OPTIONS = { bubbles: true, composed: true } as const\n\n/**\n * Inline iframe styles used to make the host element a transparent container.\n */\nconst IFRAME_STYLE = 'width:100%;height:100%;border:none;display:block;'\n\n/**\n * Display mode values advertised to the embedded runtime.\n */\nconst DISPLAY_MODES: readonly CharDisplayMode[] = ['inline', 'fullscreen', 'pip']\n\n/**\n * Minimal structural shape for iframe-originated messages.\n */\ninterface CharIframeMessageData extends Record<string, unknown> {\n\ttype: string\n}\n\n/**\n * Normalizes an API key by trimming whitespace and collapsing empty strings.\n */\nfunction normalizeApiKey(value?: string): string | undefined {\n\tconst trimmed = value?.trim()\n\treturn trimmed ? trimmed : undefined\n}\n\n/**\n * Produces a sanitized dev-mode configuration and drops empty payloads.\n */\nfunction resolveDevMode(devMode?: DevModeConfig): DevModeConfig | undefined {\n\tif (!devMode) return undefined\n\n\tconst normalized = {\n\t\tanthropicApiKey: normalizeApiKey(devMode.anthropicApiKey),\n\t\topenaiApiKey: normalizeApiKey(devMode.openaiApiKey),\n\t\tuseLocalApi: devMode.useLocalApi === true ? true : undefined,\n\t} satisfies DevModeConfig\n\n\tconst hasAnyValue =\n\t\t!!normalized.anthropicApiKey || !!normalized.openaiApiKey || !!normalized.useLocalApi\n\n\treturn hasAnyValue ? normalized : undefined\n}\n\nimport { parseBooleanAttribute } from './utils/parse-boolean-attribute'\n\n/**\n * Runtime guard for the message envelope emitted by the iframe.\n */\nfunction isCharIframeMessageData(value: unknown): value is CharIframeMessageData {\n\tif (!value || typeof value !== 'object') return false\n\tconst maybeType = (value as { type?: unknown }).type\n\treturn typeof maybeType === 'string' && maybeType.startsWith('char-')\n}\n\nfunction getStringOrUndefined(value: unknown): string | undefined {\n\treturn typeof value === 'string' ? value : undefined\n}\n\nfunction getNumberOrUndefined(value: unknown): number | undefined {\n\treturn typeof value === 'number' ? value : undefined\n}\n\nexport type {\n\tCharContainerDimensions,\n\tCharDeviceCapabilities,\n\tCharDisplayMode,\n\tCharErrorDetail,\n\tCharHostCapabilities,\n\tCharHostContext,\n\tCharHostStyles,\n\tCharOpenLinkDetail,\n\tCharPlatform,\n\tCharRequestDisplayModeDetail,\n\tCharSafeAreaInsets,\n\tCharSizeChangedDetail,\n\tCharTheme,\n\tConnectOptions,\n\tDevModeConfig,\n\tTicketAuth,\n} from './types'\n\n/**\n * Get the iframe src URL.\n * Points to the SaaS app's static /embed/ entrypoint with the parent origin as a query parameter.\n *\n * @param apiBase - Public base URL for the Char SaaS application.\n * @param parentOrigin - Origin of the host page embedding the widget.\n * @returns Fully qualified iframe URL targeting the embed entrypoint.\n */\nfunction getIframeSrc(apiBase: string, parentOrigin: string): string {\n\treturn `${apiBase}/embed/?parentOrigin=${encodeURIComponent(parentOrigin)}`\n}\n\n/**\n * Extract host CSS variable values from a host element.\n * Includes both `--char-*` and MCP UI style `--color-*`/`--font-*` tokens.\n * Uses a static list since getComputedStyle() cannot enumerate custom properties.\n * Values containing `var()` are resolved to concrete values before transport\n * so the iframe can safely apply them in its own CSS scope.\n *\n * @param el - Host `<char-agent>` element.\n * @returns A snapshot of resolved CSS custom properties for the iframe.\n */\nfunction extractCharVariables(el: HTMLElement): Record<string, string> {\n\tconst computed = getComputedStyle(el)\n\tconst vars: Record<string, string> = {}\n\tfor (const name of CHAR_CSS_VARIABLE_NAMES) {\n\t\tconst rawValue = computed.getPropertyValue(name).trim()\n\t\tif (rawValue) {\n\t\t\tconst resolvedValue = resolveCssValue(rawValue, computed, new Set([name]))\n\t\t\tconst sanitizedValue = sanitizeCssVariableValue(resolvedValue || rawValue, name)\n\t\t\tif (sanitizedValue !== undefined) {\n\t\t\t\tvars[name] = sanitizedValue\n\t\t\t}\n\t\t}\n\t}\n\treturn vars\n}\n\n/**\n * Detect whether the host page is in dark mode.\n * Checks the data-theme attribute, the `dark` class on <html>, and the prefers-color-scheme media query.\n *\n * @returns `true` when the host page should be treated as dark mode.\n */\nfunction isDarkMode(): boolean {\n\tif (typeof document === 'undefined') return false\n\tconst themeAttr = document.documentElement.getAttribute('data-theme')\n\tif (themeAttr === 'dark') return true\n\tif (themeAttr === 'light') return false\n\treturn (\n\t\tdocument.documentElement.classList.contains('dark') ||\n\t\twindow.matchMedia('(prefers-color-scheme: dark)').matches\n\t)\n}\n\n/**\n * Deep equality check using JSON.stringify. Sufficient for the flat/nested\n * structures in CharHostContext (no circular refs, no functions).\n *\n * @param a - First value.\n * @param b - Second value.\n * @returns `true` when both values serialize identically.\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n\t// Key-order sensitive — acceptable here because both sides produce objects\n\t// with deterministic key order (host context built from static field lists).\n\treturn JSON.stringify(a) === JSON.stringify(b)\n}\n\n/**\n * Parses a CSS pixel value into a finite number.\n */\nfunction parsePxToNumber(value: string): number {\n\tconst parsed = Number.parseFloat(value)\n\treturn Number.isFinite(parsed) ? parsed : 0\n}\n\n/**\n * Reads safe-area inset values using `env(safe-area-inset-*)`.\n */\nfunction getSafeAreaInsets(): CharHostContext['safeAreaInsets'] | undefined {\n\tif (typeof document === 'undefined') return undefined\n\n\tconst probe = document.createElement('div')\n\tprobe.style.cssText = [\n\t\t'position:fixed',\n\t\t'visibility:hidden',\n\t\t'pointer-events:none',\n\t\t'inset:0 auto auto 0',\n\t\t'padding-top:env(safe-area-inset-top)',\n\t\t'padding-right:env(safe-area-inset-right)',\n\t\t'padding-bottom:env(safe-area-inset-bottom)',\n\t\t'padding-left:env(safe-area-inset-left)',\n\t].join(';')\n\n\tdocument.documentElement.appendChild(probe)\n\tconst computed = getComputedStyle(probe)\n\tconst insets = {\n\t\ttop: parsePxToNumber(computed.paddingTop),\n\t\tright: parsePxToNumber(computed.paddingRight),\n\t\tbottom: parsePxToNumber(computed.paddingBottom),\n\t\tleft: parsePxToNumber(computed.paddingLeft),\n\t}\n\tprobe.remove()\n\n\treturn insets\n}\n\n/**\n * Identifies the host platform category from the user agent.\n * Note: 'desktop' detection not yet implemented; non-mobile UAs resolve to 'web'.\n */\nfunction detectPlatform(): 'web' | 'desktop' | 'mobile' {\n\tif (typeof navigator === 'undefined') return 'web'\n\tconst ua = navigator.userAgent.toLowerCase()\n\tif (/(iphone|ipad|ipod|android|mobile)/.test(ua)) return 'mobile'\n\treturn 'web'\n}\n\n/**\n * Captures lightweight host device capability hints.\n */\nfunction getDeviceCapabilities(): CharDeviceCapabilities {\n\tif (typeof window === 'undefined' || typeof navigator === 'undefined') {\n\t\treturn {}\n\t}\n\treturn {\n\t\ttouch: 'ontouchstart' in window || navigator.maxTouchPoints > 0,\n\t\thover: window.matchMedia('(hover: hover)').matches,\n\t\tpointerFine: window.matchMedia('(pointer: fine)').matches,\n\t}\n}\n\n/**\n * `<char-agent>` custom element.\n *\n * Creates an iframe pointing to the SaaS app's /embed/ entrypoint and relays\n * auth, styles, dark mode, display mode, and MCP messages via postMessage.\n *\n * Uses a unified `char-context` message with diffing (only changed fields\n * are sent) instead of separate messages per concern.\n *\n * @public\n */\nclass CharAgentElement extends HTMLElement {\n\tstatic observedAttributes = [\n\t\t'dev-mode',\n\t\t'enable-debug-tools',\n\t\t'display-mode',\n\t\t'api-base',\n\t]\n\n\t/**\n\t * React 19-friendly property form of `dev-mode`.\n\t * Read once during `connectedCallback`.\n\t */\n\tdeclare devMode?: DevModeConfig\n\n\t/**\n\t * React 19-friendly property form of `api-base`.\n\t * Read once during `connectedCallback`.\n\t */\n\tdeclare apiBase?: string\n\n\t/** Active iframe element owned by this custom element instance. */\n\tprivate _iframe: HTMLIFrameElement | null = null\n\t/** MCP relay between host window and embed iframe. */\n\tprivate _proxy: CharIframeProxy | null = null\n\t/** Indicates whether the iframe has emitted `char-ready`. */\n\tprivate _iframeReady = false\n\t/** Bound window message handler for iframe-originated events. */\n\tprivate _messageListener: ((event: MessageEvent) => void) | null = null\n\t/** Observer that tracks host theme mutations. */\n\tprivate _darkModeObserver: MutationObserver | null = null\n\t/** Media query object for `prefers-color-scheme`. */\n\tprivate _darkModeMediaQuery: MediaQueryList | null = null\n\t/** Registered media query callback. */\n\tprivate _darkModeMediaHandler: (() => void) | null = null\n\t/** Observer that tracks host style/class mutations. */\n\tprivate _styleObserver: MutationObserver | null = null\n\t/** Observer that tracks container size changes. */\n\tprivate _containerResizeObserver: ResizeObserver | null = null\n\t/** In-flight teardown request waiting for iframe acknowledgement. */\n\tprivate _teardownPending:\n\t\t| { requestId: string; resolve: () => void; timeoutId: number }\n\t\t| null = null\n\t/** Monotonic sequence used to construct teardown request IDs. */\n\tprivate _teardownSequence = 0\n\t/** Re-entrancy guard used during disconnect lifecycle. */\n\tprivate _isDisconnecting = false\n\n\t/** Last host context snapshot used for delta emission. */\n\tprivate _hostContext: CharHostContext = {}\n\n\t/** Pending credentials that are flushed when the iframe is ready. */\n\tprivate _pendingAuth: {\n\t\tidToken?: string\n\t\tclientId?: string\n\t\torganizationId?: string\n\t\tticketAuth?: TicketAuth\n\t\tanthropicApiKey?: string\n\t} | null = null\n\n\t/**\n\t * Mount lifecycle: builds iframe runtime, starts proxying, and starts host observers.\n\t * The existing runtime is reused when reconnecting during fast detach/reattach cycles.\n\t */\n\tconnectedCallback() {\n\t\tif (this._hasActiveRuntime()) {\n\t\t\tthis._isDisconnecting = false\n\t\t\tthis._teardownSequence = 0\n\t\t\tif (this._teardownPending) {\n\t\t\t\twindow.clearTimeout(this._teardownPending.timeoutId)\n\t\t\t\tthis._teardownPending.resolve()\n\t\t\t\tthis._teardownPending = null\n\t\t\t}\n\t\t\tif (this._iframe && !this.contains(this._iframe)) {\n\t\t\t\tthis.appendChild(this._iframe)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.style.display) {\n\t\t\tthis.style.display = 'block'\n\t\t}\n\n\t\tconst devMode = this._resolveDevMode()\n\t\tconst resolvedDevMode = resolveDevMode(devMode)\n\t\tconst apiBase =\n\t\t\tthis._resolveApiBaseOverride() ??\n\t\t\t(resolvedDevMode?.useLocalApi ? window.location.origin : WEBMCP_PRODUCTION_API_BASE)\n\t\tconst iframeOrigin = this._resolveIframeOrigin(apiBase)\n\t\tconst iframe = this._createIframe(apiBase)\n\t\tthis._iframe = iframe\n\n\t\t// Queue dev-mode API key for relay to the iframe on char-ready\n\t\tif (resolvedDevMode?.anthropicApiKey) {\n\t\t\tthis._pendingAuth = { anthropicApiKey: resolvedDevMode.anthropicApiKey }\n\t\t}\n\n\t\tthis._proxy = new CharIframeProxy(iframe, iframeOrigin)\n\t\tthis._proxy.start()\n\n\t\tthis._messageListener = this._createMessageListener(iframe, iframeOrigin)\n\t\twindow.addEventListener('message', this._messageListener)\n\n\t\tthis._observeDarkMode()\n\t\tthis._observeStyleChanges()\n\t\tthis._observeContainerDimensions()\n\t\tthis.appendChild(iframe)\n\t}\n\n\t/**\n\t * Determines whether this instance already has an initialized runtime.\n\t */\n\tprivate _hasActiveRuntime(): boolean {\n\t\treturn !!(this._iframe || this._proxy || this._messageListener)\n\t}\n\n\t/**\n\t * Parses and validates the iframe origin from the configured API base URL.\n\t *\n\t * @throws Error When `apiBase` is not a valid URL.\n\t */\n\tprivate _resolveIframeOrigin(apiBase: string): string {\n\t\ttry {\n\t\t\treturn new URL(apiBase).origin\n\t\t} catch {\n\t\t\tthrow new Error(`[Char] Invalid api-base: \"${apiBase}\". Must be a valid URL.`)\n\t\t}\n\t}\n\n\t/**\n\t * Creates a fully configured iframe element for the embed runtime.\n\t */\n\tprivate _createIframe(apiBase: string): HTMLIFrameElement {\n\t\tconst iframe = document.createElement('iframe')\n\t\tiframe.src = getIframeSrc(apiBase, window.location.origin)\n\t\tiframe.style.cssText = IFRAME_STYLE\n\t\tiframe.title = 'Char AI Assistant'\n\t\tiframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms')\n\t\tiframe.setAttribute('allow', 'microphone')\n\t\treturn iframe\n\t}\n\n\t/**\n\t * Creates the message listener that filters by source/origin and dispatches typed events.\n\t */\n\tprivate _createMessageListener(\n\t\tiframe: HTMLIFrameElement,\n\t\tiframeOrigin: string,\n\t): (event: MessageEvent) => void {\n\t\treturn (event: MessageEvent) => {\n\t\t\t// TODO(security#2): trusted-host assumption currently defers per-origin message rate limits\n\t\t\t// and payload-size caps for iframe -> host postMessage handling.\n\t\t\tif (event.source !== iframe.contentWindow) return\n\t\t\tif (event.origin !== iframeOrigin) return\n\t\t\tif (!isCharIframeMessageData(event.data)) return\n\t\t\tthis._handleIframeMessage(event.data, iframeOrigin)\n\t\t}\n\t}\n\n\t/**\n\t * Routes validated iframe messages to local handlers and host DOM events.\n\t */\n\tprivate _handleIframeMessage(data: CharIframeMessageData, iframeOrigin: string): void {\n\t\tswitch (data.type) {\n\t\t\tcase 'char-ready':\n\t\t\t\tthis._iframeReady = true\n\t\t\t\tthis._sendInitialContext(iframeOrigin)\n\t\t\t\treturn\n\t\t\tcase 'char-initialized':\n\t\t\t\tthis._emitCharEvent('char-initialized')\n\t\t\t\treturn\n\t\t\tcase 'char-size-changed': {\n\t\t\t\tconst width = getNumberOrUndefined(data.width)\n\t\t\t\tconst height = getNumberOrUndefined(data.height)\n\t\t\t\tconst rawSizeMode = getStringOrUndefined(data.displayMode)\n\t\t\t\tconst sizeDisplayMode = rawSizeMode && (DISPLAY_MODES as readonly string[]).includes(rawSizeMode)\n\t\t\t\t\t? (rawSizeMode as CharDisplayMode)\n\t\t\t\t\t: undefined\n\t\t\t\tif (width !== undefined || height !== undefined) {\n\t\t\t\t\tconst detail: CharSizeChangedDetail = { width, height, displayMode: sizeDisplayMode }\n\t\t\t\t\tthis._emitCharEventWithDetail('char-size-changed', detail)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'char-request-display-mode': {\n\t\t\t\tconst rawMode = getStringOrUndefined(data.mode)\n\t\t\t\tconst mode = rawMode && (DISPLAY_MODES as readonly string[]).includes(rawMode)\n\t\t\t\t\t? (rawMode as CharDisplayMode)\n\t\t\t\t\t: undefined\n\t\t\t\tconst detail: CharRequestDisplayModeDetail = { mode }\n\t\t\t\tthis._emitCharEventWithDetail('char-request-display-mode', detail)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'char-close':\n\t\t\t\tthis._emitCharEvent('char-close')\n\t\t\t\treturn\n\t\t\tcase 'char-error':\n\t\t\t\tthis._emitCharEventWithDetail('char-error', {\n\t\t\t\t\tcode: getStringOrUndefined(data.code) ?? 'UNKNOWN',\n\t\t\t\t\tmessage: getStringOrUndefined(data.message),\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\tcase 'char-open-link': {\n\t\t\t\tconst requestId = getStringOrUndefined(data.requestId)\n\t\t\t\tconst url = getStringOrUndefined(data.url)\n\t\t\t\tif (requestId && url) {\n\t\t\t\t\tthis._handleOpenLinkRequest(requestId, url, iframeOrigin)\n\t\t\t\t} else if (requestId) {\n\t\t\t\t\tthis._iframe?.contentWindow?.postMessage(\n\t\t\t\t\t\t{ type: 'char-open-link-result', requestId, ok: false, error: 'Missing url in char-open-link message' } satisfies CharHostToIframeMessage,\n\t\t\t\t\t\tiframeOrigin,\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('[Char] Received char-open-link without requestId')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'char-teardown-complete':\n\t\t\t\tthis._resolvePendingTeardown(getStringOrUndefined(data.requestId))\n\t\t\t\treturn\n\t\t\tdefault:\n\t\t\t\tconsole.warn(`[Char] Unrecognized iframe message type: \"${(data as { type?: string }).type}\"`)\n\t\t\t\treturn\n\t\t}\n\t}\n\n\t/**\n\t * Emits a host-facing custom event without detail payload.\n\t */\n\tprivate _emitCharEvent(type: string): void {\n\t\tthis.dispatchEvent(new CustomEvent(type, CHAR_CUSTOM_EVENT_OPTIONS))\n\t}\n\n\t/**\n\t * Emits a host-facing custom event with detail payload.\n\t */\n\tprivate _emitCharEventWithDetail(type: string, detail: unknown): void {\n\t\tthis.dispatchEvent(new CustomEvent(type, { ...CHAR_CUSTOM_EVENT_OPTIONS, detail }))\n\t}\n\n\t/**\n\t * Emits a standardized `char-error` event.\n\t */\n\tprivate _emitCharError(code: string, message: string): void {\n\t\tconst detail: CharErrorDetail = { code, message }\n\t\tthis._emitCharEventWithDetail('char-error', detail)\n\t}\n\n\t/**\n\t * Unmount lifecycle: requests iframe teardown and releases all host resources.\n\t */\n\tdisconnectedCallback() {\n\t\tif (this._isDisconnecting) return\n\t\tthis._isDisconnecting = true\n\n\t\ttry {\n\t\t\tconst iframeOrigin = this._getIframeOrigin()\n\t\t\tif (this._iframeReady && iframeOrigin) {\n\t\t\t\tthis._requestTeardown(iframeOrigin, 'unmount')\n\t\t\t\t\t.catch((err) => console.error('[Char] Teardown failed:', err))\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tif (this.isConnected) {\n\t\t\t\t\t\t\tthis._isDisconnecting = false\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis._finalizeDisconnect()\n\t\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error('[Char] Error during disconnect:', err)\n\t\t}\n\n\t\tthis._finalizeDisconnect()\n\t}\n\n\t/**\n\t * Releases iframe, observers, listeners, and pending teardown state.\n\t */\n\tprivate _finalizeDisconnect(): void {\n\t\tif (this._proxy) {\n\t\t\tthis._proxy.destroy()\n\t\t\tthis._proxy = null\n\t\t}\n\n\t\tif (this._messageListener) {\n\t\t\twindow.removeEventListener('message', this._messageListener)\n\t\t\tthis._messageListener = null\n\t\t}\n\n\t\tif (this._darkModeObserver) {\n\t\t\tthis._darkModeObserver.disconnect()\n\t\t\tthis._darkModeObserver = null\n\t\t}\n\t\tif (this._darkModeMediaQuery && this._darkModeMediaHandler) {\n\t\t\tthis._darkModeMediaQuery.removeEventListener('change', this._darkModeMediaHandler)\n\t\t\tthis._darkModeMediaQuery = null\n\t\t\tthis._darkModeMediaHandler = null\n\t\t}\n\n\t\tif (this._styleObserver) {\n\t\t\tthis._styleObserver.disconnect()\n\t\t\tthis._styleObserver = null\n\t\t}\n\n\t\tif (this._containerResizeObserver) {\n\t\t\tthis._containerResizeObserver.disconnect()\n\t\t\tthis._containerResizeObserver = null\n\t\t}\n\n\t\tif (this._iframe) {\n\t\t\tthis._iframe.remove()\n\t\t\tthis._iframe = null\n\t\t}\n\n\t\tif (this._teardownPending) {\n\t\t\twindow.clearTimeout(this._teardownPending.timeoutId)\n\t\t\tthis._teardownPending.resolve()\n\t\t\tthis._teardownPending = null\n\t\t}\n\n\t\tthis._iframeReady = false\n\t\tthis._pendingAuth = null\n\t\tthis._hostContext = {}\n\t\tthis._teardownSequence = 0\n\t\tthis._isDisconnecting = false\n\t}\n\n\t/**\n\t * Reacts to observed attribute updates after iframe readiness.\n\t * Attributes that affect iframe boot configuration are intentionally ignored\n\t * after mount (`dev-mode`, `enable-debug-tools`, `api-base`).\n\t */\n\tattributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {\n\t\tif (!this._iframe || !this._iframeReady) return\n\n\t\tswitch (name) {\n\t\t\tcase 'display-mode':\n\t\t\t\tthis.setHostContext({\n\t\t\t\t\tdisplayMode: resolveDisplayModeFromAttribute(newValue),\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\tcase 'dev-mode':\n\t\t\tcase 'enable-debug-tools':\n\t\t\tcase 'api-base':\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * Connect to the Char agent with authentication.\n\t *\n\t * The token is stored as a JavaScript property (not as a DOM attribute),\n\t * preventing exposure to DOM inspection and session replay tools.\n\t *\n\t * @param options - Authentication payload for either ID token or ticket auth.\n\t * @returns `true` when the payload is accepted; `false` when validation fails.\n\t */\n\tconnect(options: ConnectOptions): boolean {\n\t\tif (!options?.idToken && !options?.ticketAuth) {\n\t\t\tthis._emitCharError(\n\t\t\t\t'MISSING_TOKEN',\n\t\t\t\t'connect() requires either idToken or ticketAuth parameter',\n\t\t\t)\n\t\t\treturn false\n\t\t}\n\n\t\tif (options?.idToken && !options?.ticketAuth && !options?.clientId) {\n\t\t\tthis._emitCharError(\n\t\t\t\t'MISSING_CLIENT_ID',\n\t\t\t\t'connect() requires clientId when using idToken authentication',\n\t\t\t)\n\t\t\treturn false\n\t\t}\n\n\t\tthis._pendingAuth = {\n\t\t\tidToken: options.ticketAuth ? undefined : options.idToken,\n\t\t\tclientId: options.ticketAuth ? undefined : options.clientId,\n\t\t\torganizationId: options.ticketAuth ? undefined : options.organizationId,\n\t\t\tticketAuth: options.ticketAuth,\n\t\t}\n\n\t\tconst iframeOrigin = this._getIframeOrigin()\n\t\tif (this._iframeReady && iframeOrigin) {\n\t\t\tthis._postAuth(iframeOrigin)\n\t\t}\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Convenience method for declarative wrappers.\n\t * Applies auth when provided, otherwise clears auth.\n\t *\n\t * @param options - Auth payload to connect, or `null` to disconnect.\n\t * @returns Result from `connect()` or `disconnect()`.\n\t */\n\tsetAuth(options: ConnectOptions | null): boolean {\n\t\tif (!options) {\n\t\t\treturn this.disconnect()\n\t\t}\n\t\treturn this.connect(options)\n\t}\n\n\t/**\n\t * Disconnect from the Char agent.\n\t * Clears the authentication token.\n\t *\n\t * @returns `true` when the disconnect message was sent; `false` when the iframe was not ready.\n\t */\n\tdisconnect(): boolean {\n\t\tthis._pendingAuth = null\n\t\tconst iframeOrigin = this._getIframeOrigin()\n\t\tif (this._iframeReady && this._iframe && iframeOrigin) {\n\t\t\tthis._iframe.contentWindow?.postMessage(\n\t\t\t\t{ type: 'char-disconnect' } satisfies CharHostToIframeMessage,\n\t\t\t\tiframeOrigin,\n\t\t\t)\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\t/**\n\t * Resolves the current iframe origin when mounted.\n\t */\n\tprivate _getIframeOrigin(): string | null {\n\t\tif (!this._iframe?.src) return null\n\t\ttry {\n\t\t\treturn new URL(this._iframe.src).origin\n\t\t} catch {\n\t\t\tconsole.error('[Char] Failed to parse iframe origin from src:', this._iframe.src)\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * Update the host context sent to the iframe.\n\t * Only changed fields are transmitted (diffing pattern).\n\t *\n\t * @param hostContext - Partial host context patch to merge and emit.\n\t */\n\tsetHostContext(hostContext: CharHostContext): void {\n\t\tconst changes: CharHostContext = {}\n\t\tconst nextContext = mergeHostContext(this._hostContext, hostContext)\n\n\t\tlet hasChanges = false\n\t\tfor (const key of Object.keys(hostContext) as Array<keyof CharHostContext>) {\n\t\t\tconst oldValue = this._hostContext[key]\n\t\t\tconst newValue = nextContext[key]\n\t\t\tif (deepEqual(oldValue, newValue)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t;(changes as Record<string, unknown>)[key] = hostContext[key]\n\t\t\thasChanges = true\n\t\t}\n\t\tif (hasChanges) {\n\t\t\tthis._hostContext = nextContext\n\t\t\tthis._sendContextDelta(changes)\n\t\t}\n\t}\n\n\t/**\n\t * Build and send the full initial context after iframe signals char-ready.\n\t *\n\t * @param iframeOrigin - Trusted origin used for postMessage target filtering.\n\t */\n\tprivate _sendInitialContext(iframeOrigin: string): void {\n\t\tconst vars = extractCharVariables(this)\n\t\tconst theme = isDarkMode() ? 'dark' as const : 'light' as const\n\t\tconst displayModeAttr = this.getAttribute('display-mode')\n\t\tconst locale = typeof navigator !== 'undefined' ? navigator.language : undefined\n\t\tconst timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n\t\tconst containerDimensions: CharContainerDimensions = {\n\t\t\twidth: this.clientWidth,\n\t\t\theight: this.clientHeight,\n\t\t}\n\t\tconst safeAreaInsets = getSafeAreaInsets()\n\n\t\tconst displayMode = resolveDisplayModeFromAttribute(displayModeAttr)\n\n\t\tconst hostCapabilities: CharHostCapabilities = {\n\t\t\tsupportedDisplayModes: [...DISPLAY_MODES],\n\t\t\tsupportsOpenLink: true,\n\t\t\tsupportsTeardown: true,\n\t\t}\n\n\t\tconst context: CharHostContext = {\n\t\t\ttheme,\n\t\t\tstyles: { variables: vars },\n\t\t\tdisplayMode,\n\t\t\tavailableDisplayModes: [...DISPLAY_MODES],\n\t\t\tcontainerDimensions,\n\t\t\tlocale,\n\t\t\ttimeZone,\n\t\t\tplatform: detectPlatform(),\n\t\t\tdeviceCapabilities: getDeviceCapabilities(),\n\t\t\tsafeAreaInsets,\n\t\t\tuserAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,\n\t\t\thostCapabilities,\n\t\t}\n\n\t\tthis._hostContext = context\n\t\tif (!this._iframe?.contentWindow) {\n\t\t\tconsole.error('[Char] iframe signaled char-ready but contentWindow is null')\n\t\t\tthis._iframeReady = false\n\t\t\tthis._emitCharError('IFRAME_CONTENT_WINDOW_NULL', 'iframe signaled char-ready but contentWindow is null')\n\t\t\treturn\n\t\t}\n\t\tthis._iframe.contentWindow.postMessage(\n\t\t\t{ type: 'char-context', ...context } satisfies CharHostToIframeMessage,\n\t\t\tiframeOrigin\n\t\t)\n\n\t\tconst debugAttr = this.getAttribute('enable-debug-tools')\n\t\tif (parseBooleanAttribute(debugAttr)) {\n\t\t\tthis._iframe?.contentWindow?.postMessage(\n\t\t\t\t{ type: 'char-debug-tools', enabled: true } satisfies CharHostToIframeMessage,\n\t\t\t\tiframeOrigin\n\t\t\t)\n\t\t}\n\n\t\tif (this._pendingAuth) {\n\t\t\tthis._postAuth(iframeOrigin)\n\t\t}\n\t}\n\n\t/**\n\t * Send a context delta to the iframe.\n\t *\n\t * @param changes - Minimal context patch derived from diffing.\n\t */\n\tprivate _sendContextDelta(changes: CharHostContext): void {\n\t\tif (!this._iframeReady || !this._iframe?.contentWindow) return\n\t\tconst iframeOrigin = this._getIframeOrigin()\n\t\tif (!iframeOrigin) {\n\t\t\tconsole.warn('[Char] Cannot send context delta: iframe origin is null')\n\t\t\treturn\n\t\t}\n\t\tthis._iframe.contentWindow.postMessage(\n\t\t\t{ type: 'char-context', ...changes } satisfies CharHostToIframeMessage,\n\t\t\tiframeOrigin\n\t\t)\n\t}\n\n\t/**\n\t * Post authentication credentials to the iframe.\n\t *\n\t * @param iframeOrigin - Trusted origin used for postMessage target filtering.\n\t */\n\tprivate _postAuth(iframeOrigin: string): void {\n\t\tif (!this._pendingAuth || !this._iframe?.contentWindow) return\n\n\t\tconst message: CharHostToIframeMessage = this._pendingAuth.ticketAuth\n\t\t\t? { type: 'char-auth', ticketAuth: this._pendingAuth.ticketAuth }\n\t\t\t: this._pendingAuth.anthropicApiKey\n\t\t\t\t? { type: 'char-auth', anthropicApiKey: this._pendingAuth.anthropicApiKey }\n\t\t\t\t: {\n\t\t\t\t\t\ttype: 'char-auth',\n\t\t\t\t\t\tidToken: this._pendingAuth.idToken!,\n\t\t\t\t\t\tclientId: this._pendingAuth.clientId,\n\t\t\t\t\t\torganizationId: this._pendingAuth.organizationId,\n\t\t\t\t\t}\n\n\t\tthis._iframe.contentWindow.postMessage(message, iframeOrigin)\n\t}\n\n\t/**\n\t * Requests graceful iframe teardown and resolves once acknowledged or timed out.\n\t *\n\t * @param iframeOrigin - Trusted origin used for postMessage target filtering.\n\t * @param reason - Lifecycle reason for teardown.\n\t * @returns Promise resolved when teardown flow completes.\n\t */\n\tprivate _requestTeardown(\n\t\tiframeOrigin: string,\n\t\treason: 'disconnect' | 'unmount' | 'reload',\n\t): Promise<void> {\n\t\tif (!this._iframeReady || !this._iframe?.contentWindow) {\n\t\t\treturn Promise.resolve()\n\t\t}\n\n\t\tif (this._teardownPending) {\n\t\t\twindow.clearTimeout(this._teardownPending.timeoutId)\n\t\t\tthis._teardownPending.resolve()\n\t\t\tthis._teardownPending = null\n\t\t}\n\n\t\tconst requestId = `teardown-${Date.now()}-${++this._teardownSequence}`\n\t\treturn new Promise((resolve) => {\n\t\t\tconst timeoutId = window.setTimeout(() => {\n\t\t\t\tif (this._teardownPending?.requestId === requestId) {\n\t\t\t\t\tconsole.debug('[Char] Teardown timed out after 1000ms, requestId:', requestId)\n\t\t\t\t\tthis._teardownPending = null\n\t\t\t\t\tresolve()\n\t\t\t\t}\n\t\t\t}, 1000)\n\n\t\t\tthis._teardownPending = {\n\t\t\t\trequestId,\n\t\t\t\ttimeoutId,\n\t\t\t\tresolve: () => {\n\t\t\t\t\twindow.clearTimeout(timeoutId)\n\t\t\t\t\tresolve()\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tthis._iframe?.contentWindow?.postMessage(\n\t\t\t\t{\n\t\t\t\t\ttype: 'char-teardown',\n\t\t\t\t\trequestId,\n\t\t\t\t\treason,\n\t\t\t\t} satisfies CharHostToIframeMessage,\n\t\t\t\tiframeOrigin\n\t\t\t)\n\t\t})\n\t}\n\n\t/**\n\t * Completes an in-flight teardown promise when the iframe acknowledges it.\n\t *\n\t * @param requestId - Optional request identifier to match against pending teardown.\n\t */\n\tprivate _resolvePendingTeardown(requestId?: string): void {\n\t\tconst pending = this._teardownPending\n\t\tif (!pending) return\n\t\tif (requestId && requestId !== pending.requestId) return\n\t\tthis._teardownPending = null\n\t\tpending.resolve()\n\t}\n\n\t/**\n\t * Handles open-link requests from the iframe with protocol allowlisting.\n\t * This allowlist intentionally mirrors the iframe-side pre-filter.\n\t *\n\t * @param requestId - Link request identifier supplied by the iframe.\n\t * @param url - Requested URL string.\n\t * @param iframeOrigin - Trusted origin used for postMessage target filtering.\n\t */\n\tprivate _handleOpenLinkRequest(requestId: string, url: string, iframeOrigin: string): void {\n\t\t// TODO(security#4): trusted-host assumption currently defers destination domain allowlisting.\n\t\tlet ok = false\n\t\tlet error: string | undefined\n\t\ttry {\n\t\t\tconst parsed = new URL(url, window.location.href)\n\t\t\tconst protocol = parsed.protocol.toLowerCase()\n\t\t\tconst isAllowedProtocol =\n\t\t\t\tprotocol === 'http:' ||\n\t\t\t\tprotocol === 'https:' ||\n\t\t\t\tprotocol === 'mailto:' ||\n\t\t\t\tprotocol === 'tel:'\n\t\t\tif (!isAllowedProtocol) {\n\t\t\t\tthrow new Error(`Unsupported URL protocol: ${protocol}`)\n\t\t\t}\n\n\t\t\tconst popup = window.open(parsed.toString(), '_blank', 'noopener,noreferrer')\n\t\t\tok = popup !== null || protocol === 'mailto:' || protocol === 'tel:'\n\t\t\tif (!ok) {\n\t\t\t\terror = 'Popup blocked by browser'\n\t\t\t}\n\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent('char-open-link', {\n\t\t\t\t\t...CHAR_CUSTOM_EVENT_OPTIONS,\n\t\t\t\t\tdetail: {\n\t\t\t\t\t\trequestId,\n\t\t\t\t\t\turl: parsed.toString(),\n\t\t\t\t\t\tok,\n\t\t\t\t\t} satisfies CharOpenLinkDetail,\n\t\t\t\t})\n\t\t\t)\n\t\t} catch (err) {\n\t\t\terror = err instanceof Error ? err.message : String(err)\n\t\t\tconsole.error('[Char] open-link request failed:', err)\n\t\t}\n\n\t\tthis._iframe?.contentWindow?.postMessage(\n\t\t\t{ type: 'char-open-link-result', requestId, ok, error } satisfies CharHostToIframeMessage,\n\t\t\tiframeOrigin\n\t\t)\n\t}\n\n\t/**\n\t * Observe dark mode changes and forward to iframe via unified context.\n\t */\n\tprivate _observeDarkMode(): void {\n\t\tconst syncThemeAndStyles = () => {\n\t\t\tif (!this._iframeReady) return\n\t\t\tthis.setHostContext({\n\t\t\t\ttheme: isDarkMode() ? 'dark' : 'light',\n\t\t\t\tstyles: { variables: extractCharVariables(this) },\n\t\t\t})\n\t\t}\n\n\t\tthis._darkModeObserver = new MutationObserver(syncThemeAndStyles)\n\t\tthis._darkModeObserver.observe(document.documentElement, {\n\t\t\tattributes: true,\n\t\t\tattributeFilter: ['class', 'style', 'data-theme'],\n\t\t})\n\n\t\tthis._darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n\t\tthis._darkModeMediaHandler = syncThemeAndStyles\n\t\tthis._darkModeMediaQuery.addEventListener('change', this._darkModeMediaHandler)\n\t}\n\n\t/**\n\t * Observe style attribute changes on <char-agent> to detect CSS variable updates.\n\t * Re-extracts variables and sends delta via unified context.\n\t */\n\tprivate _observeStyleChanges(): void {\n\t\tthis._styleObserver = new MutationObserver(() => {\n\t\t\tif (!this._iframeReady) return\n\t\t\tthis.setHostContext({ styles: { variables: extractCharVariables(this) } })\n\t\t})\n\t\tthis._styleObserver.observe(this, {\n\t\t\tattributes: true,\n\t\t\tattributeFilter: ['style', 'class'],\n\t\t})\n\t}\n\n\t/**\n\t * Observe host element dimensions to provide containerDimensions context.\n\t */\n\tprivate _observeContainerDimensions(): void {\n\t\tthis._containerResizeObserver = new ResizeObserver((entries) => {\n\t\t\tif (!this._iframeReady) return\n\t\t\tconst entry = entries[0]\n\t\t\tif (!entry) return\n\t\t\tthis.setHostContext({\n\t\t\t\tcontainerDimensions: {\n\t\t\t\t\twidth: Math.round(entry.contentRect.width),\n\t\t\t\t\theight: Math.round(entry.contentRect.height),\n\t\t\t\t},\n\t\t\t\tsafeAreaInsets: getSafeAreaInsets(),\n\t\t\t})\n\t\t})\n\t\tthis._containerResizeObserver.observe(this)\n\t}\n\n\t/**\n\t * Resolve devMode from property (React 19) or attribute.\n\t *\n\t * @returns Parsed dev-mode configuration when valid.\n\t */\n\tprivate _resolveDevMode(): DevModeConfig | undefined {\n\t\tif (this.devMode && typeof this.devMode === 'object') {\n\t\t\treturn this.devMode\n\t\t}\n\n\t\tconst devModeAttr = this.getAttribute('dev-mode')\n\t\tif (!devModeAttr) return undefined\n\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(devModeAttr)\n\t\t\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\t\t\tconst actual = Array.isArray(parsed) ? 'array' : typeof parsed\n\t\t\t\tconst msg = `dev-mode attribute must be a JSON object, got: ${actual}`\n\t\t\t\tconsole.warn(`[Char] ${msg}`)\n\t\t\t\tthis._emitCharError('INVALID_DEV_MODE', msg)\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tconst obj = parsed as Record<string, unknown>\n\t\t\treturn {\n\t\t\t\tanthropicApiKey: typeof obj.anthropicApiKey === 'string' ? obj.anthropicApiKey : undefined,\n\t\t\t\topenaiApiKey: typeof obj.openaiApiKey === 'string' ? obj.openaiApiKey : undefined,\n\t\t\t\tuseLocalApi: typeof obj.useLocalApi === 'boolean' ? obj.useLocalApi : undefined,\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconst msg = `Failed to parse dev-mode attribute as JSON: ${e instanceof Error ? e.message : String(e)}`\n\t\t\tconsole.warn(`[Char] ${msg}`)\n\t\t\tthis._emitCharError('INVALID_DEV_MODE', msg)\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\t/**\n\t * Resolve apiBase override from property (React 19) or attribute.\n\t *\n\t * @returns Sanitized API base URL without trailing slash.\n\t */\n\tprivate _resolveApiBaseOverride(): string | undefined {\n\t\tconst raw =\n\t\t\t(typeof this.apiBase === 'string' ? this.apiBase : this.getAttribute('api-base')) ??\n\t\t\tundefined\n\t\tconst trimmed = raw?.trim()\n\t\tif (!trimmed) return undefined\n\t\treturn trimmed.replace(/\\/+$/, '')\n\t}\n}\n\n/**\n * Type declaration for the Char custom element.\n * Useful for TypeScript consumers using refs.\n *\n * @public\n */\nexport type { CharAgentElement }\n\n/**\n * Legacy alias for `CharAgentElement`.\n *\n * @public\n */\nexport type CharElement = CharAgentElement\n\n/**\n * Backward-compatible alias for `CharAgentElement`.\n *\n * @public\n */\nexport type WebMCPAgentElement = CharAgentElement\n\n/**\n * Register the <char-agent> custom element.\n * Called automatically when importing this module.\n *\n * @param tagName - Optional custom tag name override.\n *\n * @public\n */\nexport function registerChar(tagName = 'char-agent'): void {\n\tif (typeof window === 'undefined') return\n\n\tif (!customElements.get(tagName)) {\n\t\tcustomElements.define(tagName, CharAgentElement)\n\t}\n}\n\nregisterChar()\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'char-agent': CharAgentElement\n\t}\n\n\t/* biome-ignore lint/style/noNamespace: JSX intrinsic-elements augmentation uses namespace syntax by TypeScript design. */\n\tnamespace JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'char-agent': {\n\t\t\t\t/** Development mode configuration (JSON string for HTML attributes). */\n\t\t\t\t'dev-mode'?: string\n\t\t\t\t/** Property form of dev mode config. */\n\t\t\t\tdevMode?: DevModeConfig\n\t\t\t\t/** Explicit API base override, e.g. `https://staging-app.usechar.ai`. */\n\t\t\t\t'api-base'?: string\n\t\t\t\t/** Property form of API base override. */\n\t\t\t\tapiBase?: string\n\t\t\t\t/** Enable debug tools for inspecting embedded agent internal state. */\n\t\t\t\t'enable-debug-tools'?: boolean\n\t\t\t\t/** Display mode for host orchestration: `pip` is collapsed launcher mode. */\n\t\t\t\t'display-mode'?: CharDisplayMode\n\t\t\t\t/** Callback when the close button inside the agent panel is clicked. */\n\t\t\t\tonClose?: () => void\n\t\t\t\t/** Imperative ref to the custom element instance. */\n\t\t\t\tref?: unknown\n\t\t\t\t[key: string]: unknown\n\t\t\t}\n\t\t}\n\t}\n}\n\ndeclare module 'react/jsx-runtime' {\n\t/* biome-ignore lint/style/noNamespace: JSX intrinsic-elements augmentation uses namespace syntax by TypeScript design. */\n\tnamespace JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'char-agent': {\n\t\t\t\t'dev-mode'?: string\n\t\t\t\tdevMode?: DevModeConfig\n\t\t\t\t'api-base'?: string\n\t\t\t\tapiBase?: string\n\t\t\t\t'enable-debug-tools'?: boolean\n\t\t\t\t'display-mode'?: CharDisplayMode\n\t\t\t\tonClose?: () => void\n\t\t\t\tref?: unknown\n\t\t\t\t[key: string]: unknown\n\t\t\t}\n\t\t}\n\t}\n}\n","import type {\n\tCharErrorDetail,\n\tCharDisplayMode,\n\tCharHostContext,\n\tCharRequestDisplayModeDetail,\n\tCharSizeChangedDetail,\n\tConnectOptions,\n\tDevModeConfig,\n} from './types'\nimport {\n\tDEFAULT_AVAILABLE_DISPLAY_MODES,\n\tisDisplayMode,\n\tresolvePolicyDisplayMode,\n} from './display-mode-policy'\nimport { mergeHostContext } from './utils/host-context-merge'\nimport { parseBooleanAttribute } from './utils/parse-boolean-attribute'\nimport { registerChar, type CharAgentElement } from './web-component'\n\nconst SHELL_OPEN_CHANGE_EVENT = 'char-shell-open-change'\nconst SHELL_Z_INDEX = 2147483000\nconst DEFAULT_FULLSCREEN_BREAKPOINT = 1024\nconst DEFAULT_PANEL_WIDTH = 420\nconst DEFAULT_PIP_WIDTH = 300\nconst DEFAULT_PIP_HEIGHT = 96\nconst DEFAULT_PIP_POSITION: CharPipPosition = 'bottom-center'\nconst SHELL_HEALTH_TIMEOUT_MS = 10_000\nconst PANEL_BORDER = '1px solid rgba(15, 23, 42, 0.12)'\nconst SAFE_BOTTOM = 'calc(16px + env(safe-area-inset-bottom, 0px))'\nconst SHELL_LAYOUT_TRANSITION =\n\t'opacity 280ms ease, width 220ms ease, min-width 220ms ease, flex-basis 220ms ease'\nconst SHELL_REVEAL_FADE_MS = 280\nconst PIP_MIN_COLLAPSED_WIDTH = 70\nconst PIP_MIN_COLLAPSED_HEIGHT = 30\nconst PIP_MAX_MEASURED_HEIGHT = 320\nconst PIP_COLLAPSE_DELAY_MS = 400\nconst PIP_PILL_HEIGHT = 40\nconst PIP_MORPH_TRANSITION =\n\t'width 280ms ease, height 280ms ease, bottom 280ms ease, border-radius 280ms ease, opacity 200ms ease, transform 280ms ease'\nconst PIP_MORPH_DURATION_MS = 280\nconst PIP_SCROLL_HIDE_OFFSET = 100\nconst PIP_COLLAPSED_WIDTH_RATIO = 0.75\nconst PIP_SWIPE_THRESHOLD = 50\nconst PIP_SCROLL_DIRECTION_THRESHOLD = 40\nconst WHEEL_DELTA_LINE_MULTIPLIER = 15\nconst WHEEL_DELTA_PAGE_MULTIPLIER = 300\n\n/**\n * Allowed positions for the collapsed PIP composer surface.\n *\n * @public\n */\nexport type CharPipPosition = 'bottom-center' | 'bottom-right' | 'bottom-left'\n\n/**\n * Payload for `char-shell-open-change`.\n *\n * @public\n */\nexport interface CharShellOpenChangeDetail {\n\topen: boolean\n}\n\ntype ShellHealthState = 'idle' | 'waiting' | 'healthy' | 'unavailable'\nexport type {\n\tCharContainerDimensions,\n\tCharDeviceCapabilities,\n\tCharDisplayMode,\n\tCharHostCapabilities,\n\tCharHostContext,\n\tCharHostStyles,\n\tCharPlatform,\n\tCharSafeAreaInsets,\n\tCharTheme,\n\tConnectOptions,\n\tDevModeConfig,\n\tTicketAuth,\n} from './types'\n\nfunction normalizePositiveInteger(value: number, fallback: number): number {\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tconsole.warn(`[Char] Invalid value ${value}, using fallback ${fallback}`)\n\t\treturn fallback\n\t}\n\treturn Math.round(value)\n}\n\nfunction parsePositiveIntegerAttribute(\n\tvalue: string | null,\n\tfallback: number,\n): number {\n\tif (value === null || value.trim() === '') {\n\t\treturn fallback\n\t}\n\tconst parsed = Number.parseInt(value, 10)\n\tif (!Number.isFinite(parsed)) {\n\t\treturn fallback\n\t}\n\treturn normalizePositiveInteger(parsed, fallback)\n}\n\nfunction normalizePipPosition(value: string | null): CharPipPosition {\n\tif (value === 'bottom-right' || value === 'bottom-left') {\n\t\treturn value\n\t}\n\treturn DEFAULT_PIP_POSITION\n}\n\nfunction getPipPositionStyles(position: CharPipPosition): {\n\tleft: string\n\tright: string\n\ttransform: string\n} {\n\tif (position === 'bottom-right') {\n\t\treturn {\n\t\t\tleft: 'auto',\n\t\t\tright: '16px',\n\t\t\ttransform: 'none',\n\t\t}\n\t}\n\tif (position === 'bottom-left') {\n\t\treturn {\n\t\t\tleft: '16px',\n\t\t\tright: 'auto',\n\t\t\ttransform: 'none',\n\t\t}\n\t}\n\treturn {\n\t\tleft: '50%',\n\t\tright: 'auto',\n\t\ttransform: 'translateX(-50%)',\n\t}\n}\n\nfunction setStyleValue(el: HTMLElement, name: string, value: string): void {\n\tel.style.setProperty(name, value)\n}\n\nfunction resetStyleValue(el: HTMLElement, name: string): void {\n\tel.style.removeProperty(name)\n}\n\nfunction applyOpenAttribute(el: HTMLElement, open: boolean): void {\n\tif (open) {\n\t\tel.setAttribute('open', '')\n\t\treturn\n\t}\n\tel.removeAttribute('open')\n}\n\n/**\n * Strips shell-owned mode fields from host context patches.\n * `char-agent-shell` owns `displayMode` and `availableDisplayModes`.\n */\nfunction sanitizeShellHostContext(hostContext: CharHostContext): CharHostContext {\n\tconst { displayMode: _displayMode, availableDisplayModes: _availableModes, ...rest } =\n\t\thostContext\n\treturn rest\n}\n\n/**\n * `<char-agent-shell>` custom element.\n *\n * Opinionated host shell that composes a persistent inner `<char-agent>` and\n * owns responsive mode policy plus host layout orchestration.\n * This shell does not render chat controls, prompts, or composer UI.\n * Visible assistant UI is always iframe-owned.\n *\n * Policy:\n * - closed to `pip`\n * - open desktop to `inline`\n * - open narrow viewport to `fullscreen`\n *\n * @public\n */\nexport class CharAgentShellElement extends HTMLElement {\n\tstatic observedAttributes = [\n\t\t'open',\n\t\t'fullscreen-breakpoint',\n\t\t'panel-width',\n\t\t'pip-position',\n\t\t'pip-width',\n\t\t'pip-height',\n\t\t'dev-mode',\n\t\t'enable-debug-tools',\n\t\t'api-base',\n\t]\n\n\tdeclare devMode?: DevModeConfig\n\tdeclare apiBase?: string\n\n\tprivate _agent: CharAgentElement | null = null\n\tprivate _open = false\n\tprivate _fullscreenBreakpoint = DEFAULT_FULLSCREEN_BREAKPOINT\n\tprivate _panelWidth = DEFAULT_PANEL_WIDTH\n\tprivate _pipWidth = DEFAULT_PIP_WIDTH\n\tprivate _pipHeight = DEFAULT_PIP_HEIGHT\n\tprivate _pipPosition: CharPipPosition = DEFAULT_PIP_POSITION\n\tprivate _isNarrowViewport = false\n\tprivate _mediaQuery: MediaQueryList | null = null\n\tprivate _mediaQueryHandler: ((event: MediaQueryListEvent) => void) | null = null\n\tprivate _pendingConnectOptions: ConnectOptions | null = null\n\tprivate _pendingHostContext: CharHostContext = {}\n\tprivate _isApplyingOpenAttribute = false\n\tprivate _forwardedListenersAttached = false\n\tprivate _healthState: ShellHealthState = 'idle'\n\tprivate _healthTimeoutId: number | null = null\n\tprivate _pipMeasuredHeight: number | null = null\n\tprivate _revealFrameId: number | null = null\n\tprivate _pipExpanded = false\n\tprivate _pipPillElement: HTMLDivElement | null = null\n\tprivate _pipCollapseTimerId: number | null = null\n\tprivate _hoverMediaQuery: MediaQueryList | null = null\n\tprivate _pipListenersAttached = false\n\tprivate _pipAnimating = false\n\tprivate _pipAnimationTimeoutId: number | null = null\n\tprivate _pendingPipMeasuredHeight: number | null = null\n\tprivate _tapOutsideListener: ((e: Event) => void) | null = null\n\tprivate _pipHiddenByScroll = false\n\tprivate _scrollListener: ((e: Event) => void) | null = null\n\tprivate _scrollRafId: number | null = null\n\tprivate _lastScrollEl: Element | null = null\n\tprivate _lastScrollTop: number | null = null\n\tprivate _scrollDelta = 0\n\tprivate _swipeTouchStartY: number | null = null\n\tprivate _swipeStartAtTop = false\n\tprivate _swipeStartAtBottom = false\n\tprivate _swipeTouchStartListener: ((e: TouchEvent) => void) | null = null\n\tprivate _swipeTouchEndListener: ((e: TouchEvent) => void) | null = null\n\tprivate _wheelListener: ((e: WheelEvent) => void) | null = null\n\tprivate _wheelDelta = 0\n\n\tget open(): boolean {\n\t\treturn this._open\n\t}\n\n\tset open(value: boolean) {\n\t\tthis.setOpen(value)\n\t}\n\n\tget fullscreenBreakpoint(): number {\n\t\treturn this._fullscreenBreakpoint\n\t}\n\n\tset fullscreenBreakpoint(value: number) {\n\t\tconst normalized = normalizePositiveInteger(\n\t\t\tvalue,\n\t\t\tDEFAULT_FULLSCREEN_BREAKPOINT,\n\t\t)\n\t\tif (normalized === this._fullscreenBreakpoint) {\n\t\t\treturn\n\t\t}\n\t\tthis._fullscreenBreakpoint = normalized\n\t\tthis.setAttribute('fullscreen-breakpoint', String(normalized))\n\t\tthis._setupViewportObserver()\n\t\tthis._applyDisplayModeAndLayout()\n\t}\n\n\tget panelWidth(): number {\n\t\treturn this._panelWidth\n\t}\n\n\tset panelWidth(value: number) {\n\t\tconst normalized = normalizePositiveInteger(value, DEFAULT_PANEL_WIDTH)\n\t\tif (normalized === this._panelWidth) {\n\t\t\treturn\n\t\t}\n\t\tthis._panelWidth = normalized\n\t\tthis.setAttribute('panel-width', String(normalized))\n\t\tthis._applyDisplayModeAndLayout()\n\t}\n\n\tget pipWidth(): number {\n\t\treturn this._pipWidth\n\t}\n\n\tset pipWidth(value: number) {\n\t\tconst normalized = normalizePositiveInteger(value, DEFAULT_PIP_WIDTH)\n\t\tif (normalized === this._pipWidth) {\n\t\t\treturn\n\t\t}\n\t\tthis._pipWidth = normalized\n\t\tthis.setAttribute('pip-width', String(normalized))\n\t\tthis._applyDisplayModeAndLayout()\n\t}\n\n\tget pipHeight(): number {\n\t\treturn this._pipHeight\n\t}\n\n\tset pipHeight(value: number) {\n\t\tconst normalized = normalizePositiveInteger(value, DEFAULT_PIP_HEIGHT)\n\t\tif (normalized === this._pipHeight) {\n\t\t\treturn\n\t\t}\n\t\tthis._pipHeight = normalized\n\t\tthis.setAttribute('pip-height', String(normalized))\n\t\tthis._applyDisplayModeAndLayout()\n\t}\n\n\tget pipPosition(): CharPipPosition {\n\t\treturn this._pipPosition\n\t}\n\n\tset pipPosition(value: CharPipPosition) {\n\t\tconst normalized = normalizePipPosition(value)\n\t\tif (normalized === this._pipPosition) {\n\t\t\treturn\n\t\t}\n\t\tthis._pipPosition = normalized\n\t\tthis.setAttribute('pip-position', normalized)\n\t\tthis._applyDisplayModeAndLayout()\n\t}\n\n\tconnectedCallback(): void {\n\t\tthis._upgradeProperty('open')\n\t\tthis._upgradeProperty('fullscreenBreakpoint')\n\t\tthis._upgradeProperty('panelWidth')\n\t\tthis._upgradeProperty('pipPosition')\n\t\tthis._upgradeProperty('pipWidth')\n\t\tthis._upgradeProperty('pipHeight')\n\t\tthis._upgradeProperty('devMode')\n\t\tthis._upgradeProperty('apiBase')\n\n\t\tregisterChar()\n\t\tthis._ensureAgent()\n\t\tthis._readConfigFromAttributes()\n\t\tthis._syncForwardedAttributes()\n\t\tthis._setupViewportObserver()\n\t\tthis._applyDisplayModeAndLayout()\n\t\tthis._flushPendingConnectAndContext()\n\t}\n\n\tdisconnectedCallback(): void {\n\t\tthis._stopHealthWait()\n\t\tthis._cancelRevealFade()\n\t\tthis._teardownViewportObserver()\n\t\tthis._detachForwardedListeners()\n\t\tthis._detachPipInteractionListeners()\n\t\tthis._clearPipCollapseTimer()\n\t\tif (this._pipAnimationTimeoutId !== null) {\n\t\t\twindow.clearTimeout(this._pipAnimationTimeoutId)\n\t\t\tthis._pipAnimationTimeoutId = null\n\t\t}\n\t\tthis._pipAnimating = false\n\t\tif (this._pipPillElement) {\n\t\t\tthis._pipPillElement.remove()\n\t\t\tthis._pipPillElement = null\n\t\t}\n\t\tthis._hoverMediaQuery = null\n\t}\n\n\tattributeChangedCallback(\n\t\tname: string,\n\t\t_oldValue: string | null,\n\t\tnewValue: string | null,\n\t): void {\n\t\tswitch (name) {\n\t\t\tcase 'open': {\n\t\t\t\tif (this._isApplyingOpenAttribute) return\n\t\t\t\tconst nextOpen = parseBooleanAttribute(newValue)\n\t\t\t\tthis._setOpenInternal(nextOpen, {\n\t\t\t\t\temit: true,\n\t\t\t\t\treflect: false,\n\t\t\t\t})\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'fullscreen-breakpoint': {\n\t\t\t\tconst next = parsePositiveIntegerAttribute(\n\t\t\t\t\tnewValue,\n\t\t\t\t\tDEFAULT_FULLSCREEN_BREAKPOINT,\n\t\t\t\t)\n\t\t\t\tif (next !== this._fullscreenBreakpoint) {\n\t\t\t\t\tthis._fullscreenBreakpoint = next\n\t\t\t\t\tthis._setupViewportObserver()\n\t\t\t\t\tthis._applyDisplayModeAndLayout()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'panel-width': {\n\t\t\t\tconst next = parsePositiveIntegerAttribute(\n\t\t\t\t\tnewValue,\n\t\t\t\t\tDEFAULT_PANEL_WIDTH,\n\t\t\t\t)\n\t\t\t\tif (next !== this._panelWidth) {\n\t\t\t\t\tthis._panelWidth = next\n\t\t\t\t\tthis._applyDisplayModeAndLayout()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'pip-width': {\n\t\t\t\tconst next = parsePositiveIntegerAttribute(newValue, DEFAULT_PIP_WIDTH)\n\t\t\t\tif (next !== this._pipWidth) {\n\t\t\t\t\tthis._pipWidth = next\n\t\t\t\t\tthis._applyDisplayModeAndLayout()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'pip-height': {\n\t\t\t\tconst next = parsePositiveIntegerAttribute(newValue, DEFAULT_PIP_HEIGHT)\n\t\t\t\tif (next !== this._pipHeight) {\n\t\t\t\t\tthis._pipHeight = next\n\t\t\t\t\tthis._applyDisplayModeAndLayout()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'pip-position': {\n\t\t\t\tconst next = normalizePipPosition(newValue)\n\t\t\t\tif (next !== this._pipPosition) {\n\t\t\t\t\tthis._pipPosition = next\n\t\t\t\t\tthis._applyDisplayModeAndLayout()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcase 'dev-mode':\n\t\t\tcase 'enable-debug-tools':\n\t\t\tcase 'api-base': {\n\t\t\t\tthis._syncForwardedAttributes()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Connects shell authentication and starts availability health checks.\n\t *\n\t * @param options - Authentication payload for either ID token or ticket auth.\n\t * @returns `true` when connect is accepted by the inner element.\n\t */\n\tconnect(options: ConnectOptions): boolean {\n\t\tif (this._healthState === 'unavailable') {\n\t\t\tthis._recoverFromUnavailable()\n\t\t}\n\n\t\tif (!this._agent) {\n\t\t\tthis._pendingConnectOptions = options\n\t\t\tthis._startHealthWait()\n\t\t\treturn true\n\t\t}\n\n\t\tconst ok = this._agent.connect(options)\n\t\tif (ok) {\n\t\t\tthis._pendingConnectOptions = options\n\t\t\tthis._startHealthWait()\n\t\t}\n\t\treturn ok\n\t}\n\n\t/**\n\t * Clears authentication and disconnects the inner `<char-agent>`.\n\t *\n\t * @returns `true` when disconnect dispatch succeeds.\n\t */\n\tdisconnect(): boolean {\n\t\tthis._pendingConnectOptions = null\n\t\tthis._stopHealthWait()\n\t\tif (this._healthState !== 'unavailable') {\n\t\t\tthis._healthState = 'idle'\n\t\t}\n\t\treturn this._agent ? this._agent.disconnect() : true\n\t}\n\n\t/**\n\t * Convenience method for declarative wrappers.\n\t * Applies auth when provided, otherwise clears auth.\n\t *\n\t * @param options - Auth payload to connect, or `null` to disconnect.\n\t * @returns Result from `connect()` or `disconnect()`.\n\t */\n\tsetAuth(options: ConnectOptions | null): boolean {\n\t\tif (!options) {\n\t\t\treturn this.disconnect()\n\t\t}\n\t\treturn this.connect(options)\n\t}\n\n\t/**\n\t * Merges and forwards host context to the inner `<char-agent>`.\n\t * Shell-owned fields (`displayMode`, `availableDisplayModes`) are ignored.\n\t *\n\t * @param hostContext - Partial host context patch to forward.\n\t */\n\tsetHostContext(hostContext: CharHostContext): void {\n\t\tconst sanitizedContext = sanitizeShellHostContext(hostContext)\n\t\tif (Object.keys(sanitizedContext).length === 0) {\n\t\t\treturn\n\t\t}\n\t\tif (!this._agent) {\n\t\t\tthis._pendingHostContext = mergeHostContext(\n\t\t\t\tthis._pendingHostContext,\n\t\t\t\tsanitizedContext,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tthis._agent.setHostContext(sanitizedContext)\n\t}\n\n\t/**\n\t * Sets shell open state.\n\t *\n\t * @param open - Next desired open state.\n\t */\n\tsetOpen(open: boolean): void {\n\t\tif (this._healthState === 'unavailable' && open) {\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent('char-error', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcomposed: true,\n\t\t\t\t\tdetail: {\n\t\t\t\t\t\tcode: 'SHELL_UNAVAILABLE',\n\t\t\t\t\t\tmessage: 'Cannot open shell: agent is unavailable',\n\t\t\t\t\t} satisfies CharErrorDetail,\n\t\t\t\t}),\n\t\t\t)\n\t\t\treturn\n\t\t}\n\t\tthis._setOpenInternal(Boolean(open), { emit: true, reflect: true })\n\t}\n\n\t/**\n\t * Toggles shell open state.\n\t */\n\ttoggleOpen(): void {\n\t\tthis._setOpenInternal(!this._open, { emit: true, reflect: true })\n\t}\n\n\tprivate _upgradeProperty(propertyName: string): void {\n\t\tif (!Object.hasOwn(this, propertyName)) {\n\t\t\treturn\n\t\t}\n\t\tconst value = (this as Record<string, unknown>)[propertyName]\n\t\tdelete (this as Record<string, unknown>)[propertyName]\n\t\t;(this as Record<string, unknown>)[propertyName] = value\n\t}\n\n\tprivate _ensureAgent(): void {\n\t\tif (this._agent) {\n\t\t\tif (!this.contains(this._agent)) {\n\t\t\t\tthis.appendChild(this._agent)\n\t\t\t}\n\t\t\tthis._attachForwardedListeners()\n\t\t\treturn\n\t\t}\n\n\t\tconst agent = document.createElement('char-agent') as CharAgentElement\n\t\tagent.style.display = 'block'\n\t\tagent.style.width = '100%'\n\t\tagent.style.height = '100%'\n\t\tagent.style.border = 'none'\n\t\tthis._primeAgentBootConfig(agent)\n\t\tthis._agent = agent\n\t\tthis.appendChild(agent)\n\t\tthis._attachForwardedListeners()\n\t}\n\n\tprivate _primeAgentBootConfig(agent: CharAgentElement): void {\n\t\tfor (const name of ['dev-mode', 'enable-debug-tools', 'api-base']) {\n\t\t\tconst value = this.getAttribute(name)\n\t\t\tif (value !== null) {\n\t\t\t\tagent.setAttribute(name, value)\n\t\t\t}\n\t\t}\n\n\t\tagent.devMode = this.devMode && typeof this.devMode === 'object' ? this.devMode : undefined\n\t\tagent.apiBase = typeof this.apiBase === 'string' ? this.apiBase : undefined\n\t}\n\n\tprivate _attachForwardedListeners(): void {\n\t\tif (!this._agent || this._forwardedListenersAttached) {\n\t\t\treturn\n\t\t}\n\t\tthis._agent.addEventListener(\n\t\t\t'char-request-display-mode',\n\t\t\tthis._handleRequestDisplayMode,\n\t\t)\n\t\tthis._agent.addEventListener('char-close', this._handleClose)\n\t\tthis._agent.addEventListener('char-initialized', this._handleInitialized)\n\t\tthis._agent.addEventListener('char-error', this._handleInnerError)\n\t\tthis._agent.addEventListener('char-size-changed', this._handleInnerSizeChanged)\n\t\tthis._forwardedListenersAttached = true\n\t}\n\n\tprivate _detachForwardedListeners(): void {\n\t\tif (!this._agent || !this._forwardedListenersAttached) {\n\t\t\treturn\n\t\t}\n\t\tthis._agent.removeEventListener(\n\t\t\t'char-request-display-mode',\n\t\t\tthis._handleRequestDisplayMode,\n\t\t)\n\t\tthis._agent.removeEventListener('char-close', this._handleClose)\n\t\tthis._agent.removeEventListener('char-initialized', this._handleInitialized)\n\t\tthis._agent.removeEventListener('char-error', this._handleInnerError)\n\t\tthis._agent.removeEventListener('char-size-changed', this._handleInnerSizeChanged)\n\t\tthis._forwardedListenersAttached = false\n\t}\n\n\tprivate _readConfigFromAttributes(): void {\n\t\tthis._open = parseBooleanAttribute(this.getAttribute('open'))\n\t\tthis._fullscreenBreakpoint = parsePositiveIntegerAttribute(\n\t\t\tthis.getAttribute('fullscreen-breakpoint'),\n\t\t\tDEFAULT_FULLSCREEN_BREAKPOINT,\n\t\t)\n\t\tthis._panelWidth = parsePositiveIntegerAttribute(\n\t\t\tthis.getAttribute('panel-width'),\n\t\t\tDEFAULT_PANEL_WIDTH,\n\t\t)\n\t\tthis._pipWidth = parsePositiveIntegerAttribute(\n\t\t\tthis.getAttribute('pip-width'),\n\t\t\tDEFAULT_PIP_WIDTH,\n\t\t)\n\t\tthis._pipHeight = parsePositiveIntegerAttribute(\n\t\t\tthis.getAttribute('pip-height'),\n\t\t\tDEFAULT_PIP_HEIGHT,\n\t\t)\n\t\tthis._pipPosition = normalizePipPosition(this.getAttribute('pip-position'))\n\t}\n\n\tprivate _syncForwardedAttributes(): void {\n\t\tif (!this._agent) return\n\n\t\tfor (const name of ['dev-mode', 'enable-debug-tools', 'api-base']) {\n\t\t\tconst value = this.getAttribute(name)\n\t\t\tif (value === null) {\n\t\t\t\tthis._agent.removeAttribute(name)\n\t\t\t} else {\n\t\t\t\tthis._agent.setAttribute(name, value)\n\t\t\t}\n\t\t}\n\n\t\tthis._agent.devMode =\n\t\t\tthis.devMode && typeof this.devMode === 'object' ? this.devMode : undefined\n\t\tthis._agent.apiBase = typeof this.apiBase === 'string' ? this.apiBase : undefined\n\t}\n\n\tprivate _setupViewportObserver(): void {\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tconst query = `(max-width: ${this._fullscreenBreakpoint - 1}px)`\n\t\tif (this._mediaQuery?.media === query) {\n\t\t\tthis._isNarrowViewport = this._mediaQuery.matches\n\t\t\treturn\n\t\t}\n\n\t\tthis._teardownViewportObserver()\n\t\tthis._mediaQuery = window.matchMedia(query)\n\t\tthis._isNarrowViewport = this._mediaQuery.matches\n\n\t\tthis._mediaQueryHandler = (event: MediaQueryListEvent) => {\n\t\t\tthis._isNarrowViewport = event.matches\n\t\t\tthis._applyDisplayModeAndLayout()\n\t\t}\n\t\tthis._mediaQuery.addEventListener('change', this._mediaQueryHandler)\n\t}\n\n\tprivate _teardownViewportObserver(): void {\n\t\tif (this._mediaQuery && this._mediaQueryHandler) {\n\t\t\tthis._mediaQuery.removeEventListener('change', this._mediaQueryHandler)\n\t\t}\n\t\tthis._mediaQuery = null\n\t\tthis._mediaQueryHandler = null\n\t}\n\n\tprivate _applyDisplayModeAndLayout(): void {\n\t\tif (!this._agent) return\n\t\tif (this._healthState === 'unavailable') {\n\t\t\tthis._applyUnavailableLayout()\n\t\t\treturn\n\t\t}\n\t\tif (this._healthState !== 'healthy') {\n\t\t\tthis._applyPreReadyLayout()\n\t\t\treturn\n\t\t}\n\t\tthis.hidden = false\n\n\t\tconst displayMode = resolvePolicyDisplayMode({\n\t\t\topen: this._open,\n\t\t\tisNarrowViewport: this._isNarrowViewport,\n\t\t\tavailableModes: DEFAULT_AVAILABLE_DISPLAY_MODES,\n\t\t})\n\t\tif (displayMode !== 'pip') {\n\t\t\tif (this._pipMeasuredHeight !== null) {\n\t\t\t\tthis._pipMeasuredHeight = null\n\t\t\t}\n\t\t}\n\t\tthis._agent.setAttribute('display-mode', displayMode)\n\t\tthis._applyHostLayout(displayMode)\n\t\tthis._applyAgentLayout(displayMode)\n\t}\n\n\tprivate _applyHostLayout(displayMode: CharDisplayMode): void {\n\t\tif (displayMode === 'inline' && !this._isNarrowViewport) {\n\t\t\tsetStyleValue(this, 'position', 'relative')\n\t\t\tsetStyleValue(this, 'flex', `0 0 ${this._panelWidth}px`)\n\t\t\tsetStyleValue(this, 'width', `${this._panelWidth}px`)\n\t\t\tsetStyleValue(this, 'min-width', `${this._panelWidth}px`)\n\t\t\tsetStyleValue(this, 'height', '100%')\n\t\t\tsetStyleValue(this, 'z-index', String(SHELL_Z_INDEX))\n\t\t\tsetStyleValue(this, 'border-left', PANEL_BORDER)\n\t\t\tsetStyleValue(\n\t\t\t\tthis,\n\t\t\t\t'transition',\n\t\t\t\tSHELL_LAYOUT_TRANSITION,\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\tsetStyleValue(this, 'position', 'relative')\n\t\tsetStyleValue(this, 'flex', '0 0 0px')\n\t\tsetStyleValue(this, 'width', '0px')\n\t\tsetStyleValue(this, 'min-width', '0px')\n\t\tsetStyleValue(this, 'height', '0px')\n\t\tsetStyleValue(this, 'z-index', String(SHELL_Z_INDEX))\n\t\tresetStyleValue(this, 'border-left')\n\t\tsetStyleValue(\n\t\t\tthis,\n\t\t\t'transition',\n\t\t\tSHELL_LAYOUT_TRANSITION,\n\t\t)\n\t}\n\n\tprivate _composePipTransform(opts: {\n\t\tscrollHide?: boolean\n\t}): string {\n\t\tconst parts: string[] = []\n\t\tif (this._pipPosition === 'bottom-center') parts.push('translateX(-50%)')\n\t\tif (opts.scrollHide) parts.push(`translateY(${PIP_SCROLL_HIDE_OFFSET}px)`)\n\t\treturn parts.length > 0 ? parts.join(' ') : 'none'\n\t}\n\n\tprivate _applyAgentLayout(displayMode: CharDisplayMode): void {\n\t\tif (!this._agent) return\n\n\t\tif (displayMode === 'inline' && !this._isNarrowViewport) {\n\t\t\tthis._detachPipInteractionListeners()\n\t\t\tthis._clearPipCollapseTimer()\n\t\t\tthis._pipExpanded = false\n\t\t\tthis._pipAnimating = false\n\t\t\tthis._hidePipPill()\n\t\t\tsetStyleValue(this._agent, 'position', 'relative')\n\t\t\tresetStyleValue(this._agent, 'top')\n\t\t\tresetStyleValue(this._agent, 'right')\n\t\t\tresetStyleValue(this._agent, 'bottom')\n\t\t\tresetStyleValue(this._agent, 'left')\n\t\t\tresetStyleValue(this._agent, 'transform')\n\t\t\tresetStyleValue(this._agent, 'max-width')\n\t\t\tresetStyleValue(this._agent, 'max-height')\n\t\t\tsetStyleValue(this._agent, 'z-index', 'auto')\n\t\t\tsetStyleValue(this._agent, 'width', '100%')\n\t\t\tsetStyleValue(this._agent, 'height', '100%')\n\t\t\tsetStyleValue(this._agent, 'border-radius', '0')\n\t\t\tsetStyleValue(this._agent, 'overflow', 'hidden')\n\t\t\tresetStyleValue(this._agent, 'transition')\n\t\t\tresetStyleValue(this._agent, 'opacity')\n\t\t\tresetStyleValue(this._agent, 'pointer-events')\n\t\t\treturn\n\t\t}\n\n\t\tif (displayMode === 'fullscreen') {\n\t\t\tthis._detachPipInteractionListeners()\n\t\t\tthis._clearPipCollapseTimer()\n\t\t\tthis._pipExpanded = false\n\t\t\tthis._pipAnimating = false\n\t\t\tthis._hidePipPill()\n\t\t\tsetStyleValue(this._agent, 'position', 'fixed')\n\t\t\tsetStyleValue(this._agent, 'top', '0')\n\t\t\tsetStyleValue(this._agent, 'right', '0')\n\t\t\tsetStyleValue(this._agent, 'bottom', '0')\n\t\t\tsetStyleValue(this._agent, 'left', '0')\n\t\t\tresetStyleValue(this._agent, 'transform')\n\t\t\tresetStyleValue(this._agent, 'max-width')\n\t\t\tresetStyleValue(this._agent, 'max-height')\n\t\t\tsetStyleValue(this._agent, 'z-index', String(SHELL_Z_INDEX))\n\t\t\tsetStyleValue(this._agent, 'width', '100vw')\n\t\t\tsetStyleValue(this._agent, 'height', '100dvh')\n\t\t\tsetStyleValue(this._agent, 'border-radius', '0')\n\t\t\tsetStyleValue(this._agent, 'overflow', 'hidden')\n\t\t\tresetStyleValue(this._agent, 'transition')\n\t\t\tresetStyleValue(this._agent, 'opacity')\n\t\t\tresetStyleValue(this._agent, 'pointer-events')\n\t\t\treturn\n\t\t}\n\n\t\tconst pipPositionStyles = getPipPositionStyles(this._pipPosition)\n\t\tconst expandedWidth = Math.max(PIP_MIN_COLLAPSED_WIDTH, this._pipWidth)\n\t\tconst collapsedWidth = Math.max(\n\t\t\tPIP_MIN_COLLAPSED_WIDTH,\n\t\t\tMath.round(this._pipWidth * PIP_COLLAPSED_WIDTH_RATIO),\n\t\t)\n\t\tconst targetWidth = this._pipExpanded ? expandedWidth : collapsedWidth\n\t\tconst collapsedHeight = Math.max(PIP_MIN_COLLAPSED_HEIGHT, this._pipHeight)\n\t\tconst hasExplicitPipHeight = this.hasAttribute('pip-height')\n\t\tconst measuredHeightFloor =\n\t\t\ttypeof this._pipMeasuredHeight === 'number' ? this._pipMeasuredHeight : 0\n\t\tconst expandedHeight = Math.max(collapsedHeight, measuredHeightFloor)\n\t\tconst collapsedPipHeight = hasExplicitPipHeight ? collapsedHeight : PIP_PILL_HEIGHT\n\t\tconst heightDelta = expandedHeight - collapsedPipHeight\n\n\t\tlet targetHeight: number\n\t\tlet targetBottom: string\n\n\t\tif (this._pipExpanded) {\n\t\t\ttargetHeight = expandedHeight\n\t\t\ttargetBottom = SAFE_BOTTOM\n\t\t} else {\n\t\t\ttargetHeight = collapsedPipHeight\n\t\t\ttargetBottom = heightDelta > 0\n\t\t\t\t? `calc(${heightDelta}px + 16px + env(safe-area-inset-bottom, 0px))`\n\t\t\t\t: SAFE_BOTTOM\n\t\t}\n\n\t\tconst composedTransform = this._composePipTransform({\n\t\t\tscrollHide: this._pipHiddenByScroll,\n\t\t})\n\n\t\tsetStyleValue(this._agent, 'position', 'fixed')\n\t\tresetStyleValue(this._agent, 'top')\n\t\tsetStyleValue(this._agent, 'right', pipPositionStyles.right)\n\t\tsetStyleValue(this._agent, 'left', pipPositionStyles.left)\n\t\tsetStyleValue(this._agent, 'bottom', targetBottom)\n\t\tsetStyleValue(this._agent, 'transform', composedTransform)\n\t\tsetStyleValue(this._agent, 'z-index', String(SHELL_Z_INDEX))\n\t\tsetStyleValue(\n\t\t\tthis._agent,\n\t\t\t'width',\n\t\t\t`min(${targetWidth}px, calc(100vw - 24px))`,\n\t\t)\n\t\tsetStyleValue(this._agent, 'height', `${targetHeight}px`)\n\t\tsetStyleValue(\n\t\t\tthis._agent,\n\t\t\t'max-height',\n\t\t\t'calc(100dvh - 24px - env(safe-area-inset-bottom, 0px))',\n\t\t)\n\t\tsetStyleValue(this._agent, 'max-width', '100vw')\n\t\tsetStyleValue(this._agent, 'border-radius', '16px')\n\t\tsetStyleValue(this._agent, 'overflow', 'hidden')\n\t\tsetStyleValue(\n\t\t\tthis._agent,\n\t\t\t'transition',\n\t\t\tthis._healthState === 'healthy' ? PIP_MORPH_TRANSITION : 'none',\n\t\t)\n\n\t\tif (this._healthState === 'healthy') {\n\t\t\tconst pill = this._ensurePipPill()\n\t\t\tif (!pill.parentNode) {\n\t\t\t\tthis.appendChild(pill)\n\t\t\t}\n\t\t\tthis._updatePipPillPosition(collapsedWidth, heightDelta, collapsedPipHeight)\n\t\t\tthis._attachPipInteractionListeners()\n\t\t\tthis._attachScrollHideListener()\n\t\t\tthis._attachSwipeGestureListeners()\n\t\t\tthis._attachWheelFallbackListener()\n\t\t\tthis._applyPipVisualState()\n\t\t}\n\t}\n\n\tprivate _ensurePipPill(): HTMLDivElement {\n\t\tif (this._pipPillElement) return this._pipPillElement\n\n\t\tconst pill = document.createElement('div')\n\t\tpill.setAttribute('role', 'button')\n\t\tpill.setAttribute('aria-label', 'Open assistant')\n\t\tpill.setAttribute('tabindex', '0')\n\n\t\tconst pipPositionStyles = getPipPositionStyles(this._pipPosition)\n\t\tpill.style.cssText = [\n\t\t\t'position:fixed',\n\t\t\t`left:${pipPositionStyles.left}`,\n\t\t\t`right:${pipPositionStyles.right}`,\n\t\t\t`z-index:${SHELL_Z_INDEX + 1}`,\n\t\t\t'background:transparent',\n\t\t\t'border-radius:16px',\n\t\t\t'cursor:pointer',\n\t\t\t'user-select:none',\n\t\t\t'-webkit-user-select:none',\n\t\t].join(';')\n\n\t\tthis._pipPillElement = pill\n\t\treturn pill\n\t}\n\n\tprivate _updatePipPillPosition(pipWidth: number, heightDelta: number, pillHeight: number): void {\n\t\tif (!this._pipPillElement) return\n\t\tconst collapsedBottom = heightDelta > 0\n\t\t\t? `calc(${heightDelta}px + 16px + env(safe-area-inset-bottom, 0px))`\n\t\t\t: SAFE_BOTTOM\n\t\tsetStyleValue(this._pipPillElement, 'bottom', collapsedBottom)\n\t\tsetStyleValue(this._pipPillElement, 'width', `min(${pipWidth}px, calc(100vw - 24px))`)\n\t\tsetStyleValue(this._pipPillElement, 'height', `${pillHeight}px`)\n\t\tsetStyleValue(\n\t\t\tthis._pipPillElement,\n\t\t\t'transform',\n\t\t\tthis._composePipTransform({\n\t\t\t\tscrollHide: this._pipHiddenByScroll,\n\t\t\t}),\n\t\t)\n\t\tsetStyleValue(\n\t\t\tthis._pipPillElement,\n\t\t\t'transition',\n\t\t\t'transform 280ms ease, width 280ms ease, opacity 200ms ease',\n\t\t)\n\t}\n\n\tprivate _applyPipVisualState(): void {\n\t\tif (!this._agent || !this._pipPillElement) return\n\n\t\tif (this._pipHiddenByScroll) {\n\t\t\tsetStyleValue(this._agent, 'opacity', '0')\n\t\t\tsetStyleValue(this._agent, 'pointer-events', 'none')\n\t\t\tsetStyleValue(this._pipPillElement, 'opacity', '0')\n\t\t\tsetStyleValue(this._pipPillElement, 'pointer-events', 'none')\n\t\t\treturn\n\t\t}\n\n\t\tsetStyleValue(this._agent, 'opacity', '1')\n\t\tif (this._pipExpanded) {\n\t\t\tsetStyleValue(this._agent, 'pointer-events', 'auto')\n\t\t\tsetStyleValue(this._pipPillElement, 'pointer-events', 'none')\n\t\t} else {\n\t\t\tsetStyleValue(this._agent, 'pointer-events', 'none')\n\t\t\tsetStyleValue(this._pipPillElement, 'pointer-events', 'auto')\n\t\t}\n\t}\n\n\tprivate _setPipExpanded(expanded: boolean): void {\n\t\tthis._pipExpanded = expanded\n\t\tthis._clearPipCollapseTimer()\n\t\tthis._applyPipVisualState()\n\n\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\tthis._applyAgentLayout('pip')\n\t\t}\n\n\t\tthis._pipAnimating = true\n\t\tthis._pendingPipMeasuredHeight = null\n\t\tif (this._pipAnimationTimeoutId !== null) {\n\t\t\twindow.clearTimeout(this._pipAnimationTimeoutId)\n\t\t}\n\t\tthis._pipAnimationTimeoutId = window.setTimeout(() => {\n\t\t\tthis._pipAnimating = false\n\t\t\tthis._pipAnimationTimeoutId = null\n\t\t\tthis._flushPendingPipMeasuredHeight()\n\t\t}, PIP_MORPH_DURATION_MS)\n\n\t\tif (expanded) {\n\t\t\tthis._attachTapOutsideListener()\n\t\t} else {\n\t\t\tthis._detachTapOutsideListener()\n\t\t}\n\t}\n\n\tprivate _flushPendingPipMeasuredHeight(): void {\n\t\tconst pending = this._pendingPipMeasuredHeight\n\t\tthis._pendingPipMeasuredHeight = null\n\t\tif (pending === null || pending === this._pipMeasuredHeight) return\n\t\tthis._pipMeasuredHeight = pending\n\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\tthis._applyAgentLayout('pip')\n\t\t}\n\t}\n\n\tprivate _isHoverDevice(): boolean {\n\t\tif (!this._hoverMediaQuery) {\n\t\t\tif (typeof window === 'undefined') return false\n\t\t\tthis._hoverMediaQuery = window.matchMedia('(hover: hover)')\n\t\t}\n\t\treturn this._hoverMediaQuery.matches\n\t}\n\n\tprivate _attachPipInteractionListeners(): void {\n\t\tif (this._pipListenersAttached || !this._agent || !this._pipPillElement) return\n\t\tthis._pipListenersAttached = true\n\t\tconst pill = this._pipPillElement\n\t\tconst agent = this._agent\n\n\t\tif (this._isHoverDevice()) {\n\t\t\tpill.addEventListener('pointerenter', this._handlePipPointerEnter)\n\t\t\tagent.addEventListener('pointerenter', this._handlePipPointerEnter)\n\t\t\tpill.addEventListener('pointerleave', this._handlePipPointerLeave)\n\t\t\tagent.addEventListener('pointerleave', this._handlePipPointerLeave)\n\t\t}\n\n\t\tpill.addEventListener('click', this._handlePillClick)\n\t\tpill.addEventListener('keydown', this._handlePillKeydown)\n\t}\n\n\tprivate _detachPipInteractionListeners(): void {\n\t\tif (!this._pipListenersAttached) return\n\t\tthis._pipListenersAttached = false\n\t\tconst pill = this._pipPillElement\n\t\tconst agent = this._agent\n\n\t\tif (pill) {\n\t\t\tpill.removeEventListener('pointerenter', this._handlePipPointerEnter)\n\t\t\tpill.removeEventListener('pointerleave', this._handlePipPointerLeave)\n\t\t\tpill.removeEventListener('click', this._handlePillClick)\n\t\t\tpill.removeEventListener('keydown', this._handlePillKeydown)\n\t\t}\n\t\tif (agent) {\n\t\t\tagent.removeEventListener('pointerenter', this._handlePipPointerEnter)\n\t\t\tagent.removeEventListener('pointerleave', this._handlePipPointerLeave)\n\t\t}\n\t\tthis._detachTapOutsideListener()\n\t\tthis._detachScrollHideListener()\n\t\tthis._detachSwipeGestureListeners()\n\t\tthis._detachWheelFallbackListener()\n\t}\n\n\tprivate _schedulePipCollapse(): void {\n\t\tthis._clearPipCollapseTimer()\n\t\tthis._pipCollapseTimerId = window.setTimeout(() => {\n\t\t\tthis._pipCollapseTimerId = null\n\t\t\tthis._setPipExpanded(false)\n\t\t}, PIP_COLLAPSE_DELAY_MS)\n\t}\n\n\tprivate _clearPipCollapseTimer(): void {\n\t\tif (this._pipCollapseTimerId !== null) {\n\t\t\twindow.clearTimeout(this._pipCollapseTimerId)\n\t\t\tthis._pipCollapseTimerId = null\n\t\t}\n\t}\n\n\tprivate _attachTapOutsideListener(): void {\n\t\tif (this._tapOutsideListener || this._isHoverDevice()) return\n\t\tthis._tapOutsideListener = (e: Event) => {\n\t\t\tconst target = e.target as Node | null\n\t\t\tif (!target) return\n\t\t\tif (this._pipPillElement?.contains(target)) return\n\t\t\tif (this._agent?.contains(target)) return\n\t\t\tthis._setPipExpanded(false)\n\t\t}\n\t\tdocument.addEventListener('click', this._tapOutsideListener, true)\n\t}\n\n\tprivate _detachTapOutsideListener(): void {\n\t\tif (this._tapOutsideListener) {\n\t\t\tdocument.removeEventListener('click', this._tapOutsideListener, true)\n\t\t\tthis._tapOutsideListener = null\n\t\t}\n\t}\n\n\tprivate _handlePipPointerEnter = (): void => {\n\t\tthis._clearPipCollapseTimer()\n\t\tif (!this._pipExpanded) {\n\t\t\tthis._setPipExpanded(true)\n\t\t}\n\t}\n\n\tprivate _handlePipPointerLeave = (): void => {\n\t\tif (this._pipExpanded) {\n\t\t\tthis._schedulePipCollapse()\n\t\t}\n\t}\n\n\tprivate _attachScrollHideListener(): void {\n\t\tif (this._scrollListener || typeof window === 'undefined') return\n\n\t\tthis._scrollListener = (e: Event) => {\n\t\t\tconst target = e.target\n\t\t\tlet scrollEl: Element | null = null\n\t\t\tif (target === document || target === document.documentElement) {\n\t\t\t\tscrollEl = document.scrollingElement || document.documentElement\n\t\t\t} else if (target instanceof Element) {\n\t\t\t\tscrollEl = target\n\t\t\t}\n\t\t\tif (!scrollEl) return\n\n\t\t\tif (scrollEl.clientHeight < window.innerHeight * 0.3) return\n\n\t\t\tif (this._scrollRafId !== null) return\n\t\t\tthis._scrollRafId = requestAnimationFrame(() => {\n\t\t\t\tthis._scrollRafId = null\n\t\t\t\tthis._evaluateScrollPosition(scrollEl!)\n\t\t\t})\n\t\t}\n\n\t\tdocument.addEventListener('scroll', this._scrollListener, {\n\t\t\tcapture: true,\n\t\t\tpassive: true,\n\t\t} as EventListenerOptions)\n\t}\n\n\tprivate _evaluateScrollPosition(el: Element): void {\n\t\tconst scrollTop = el.scrollTop\n\t\tconst maxScroll = el.scrollHeight - el.clientHeight\n\n\t\t// Reset tracking when a different element starts scrolling\n\t\tif (el !== this._lastScrollEl) {\n\t\t\tthis._lastScrollEl = el\n\t\t\tthis._lastScrollTop = scrollTop\n\t\t\tthis._scrollDelta = 0\n\t\t\treturn\n\t\t}\n\n\t\t// At very top — always show\n\t\tif (scrollTop <= 0) {\n\t\t\tthis._lastScrollTop = 0\n\t\t\tthis._scrollDelta = 0\n\t\t\tif (this._pipHiddenByScroll) {\n\t\t\t\tthis._pipHiddenByScroll = false\n\t\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\t\tthis._applyPipVisualState()\n\t\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// At very bottom — always hide\n\t\tif (maxScroll > 0 && scrollTop >= maxScroll - 2) {\n\t\t\tthis._lastScrollTop = scrollTop\n\t\t\tthis._scrollDelta = 0\n\t\t\tif (!this._pipHiddenByScroll) {\n\t\t\t\tthis._pipHiddenByScroll = true\n\t\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\t\tthis._applyPipVisualState()\n\t\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// First event for this element — just record position\n\t\tif (this._lastScrollTop === null) {\n\t\t\tthis._lastScrollTop = scrollTop\n\t\t\treturn\n\t\t}\n\n\t\tconst delta = scrollTop - this._lastScrollTop\n\t\tthis._lastScrollTop = scrollTop\n\n\t\t// Reset accumulator on direction change\n\t\tif ((delta > 0 && this._scrollDelta < 0) || (delta < 0 && this._scrollDelta > 0)) {\n\t\t\tthis._scrollDelta = 0\n\t\t}\n\t\tthis._scrollDelta += delta\n\n\t\tif (this._scrollDelta > PIP_SCROLL_DIRECTION_THRESHOLD && !this._pipHiddenByScroll) {\n\t\t\tthis._pipHiddenByScroll = true\n\t\t\tthis._scrollDelta = 0\n\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\tthis._applyPipVisualState()\n\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t}\n\t\t} else if (this._scrollDelta < -PIP_SCROLL_DIRECTION_THRESHOLD && this._pipHiddenByScroll) {\n\t\t\tthis._pipHiddenByScroll = false\n\t\t\tthis._scrollDelta = 0\n\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\tthis._applyPipVisualState()\n\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _detachScrollHideListener(): void {\n\t\tif (this._scrollListener) {\n\t\t\tdocument.removeEventListener('scroll', this._scrollListener, true)\n\t\t\tthis._scrollListener = null\n\t\t}\n\t\tif (this._scrollRafId !== null) {\n\t\t\tcancelAnimationFrame(this._scrollRafId)\n\t\t\tthis._scrollRafId = null\n\t\t}\n\t\tthis._pipHiddenByScroll = false\n\t\tthis._lastScrollEl = null\n\t\tthis._lastScrollTop = null\n\t\tthis._scrollDelta = 0\n\t}\n\n\tprivate _attachSwipeGestureListeners(): void {\n\t\tif (this._swipeTouchStartListener || typeof window === 'undefined') return\n\n\t\tthis._swipeTouchStartListener = (e: TouchEvent) => {\n\t\t\tif (e.touches.length !== 1) return\n\t\t\tthis._swipeTouchStartY = e.touches[0].clientY\n\t\t\tconst scrollEl = document.scrollingElement || document.documentElement\n\t\t\tthis._swipeStartAtTop = scrollEl.scrollTop <= 0\n\t\t\tthis._swipeStartAtBottom =\n\t\t\t\tscrollEl.scrollHeight <= scrollEl.clientHeight ||\n\t\t\t\tscrollEl.scrollTop + scrollEl.clientHeight >= scrollEl.scrollHeight - 1\n\t\t}\n\n\t\tthis._swipeTouchEndListener = (e: TouchEvent) => {\n\t\t\tif (this._swipeTouchStartY === null) return\n\t\t\tif (e.changedTouches.length === 0) return\n\t\t\tconst endY = e.changedTouches[0].clientY\n\t\t\tconst deltaY = endY - this._swipeTouchStartY\n\t\t\tthis._swipeTouchStartY = null\n\n\t\t\tif (Math.abs(deltaY) < PIP_SWIPE_THRESHOLD) return\n\n\t\t\tif (deltaY < -PIP_SWIPE_THRESHOLD && this._swipeStartAtTop && this._pipHiddenByScroll) {\n\t\t\t\tthis._pipHiddenByScroll = false\n\t\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\t\tthis._applyPipVisualState()\n\t\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (deltaY > PIP_SWIPE_THRESHOLD && this._swipeStartAtBottom && !this._pipHiddenByScroll) {\n\t\t\t\tthis._pipHiddenByScroll = true\n\t\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\t\tthis._applyPipVisualState()\n\t\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('touchstart', this._swipeTouchStartListener, {\n\t\t\tcapture: true,\n\t\t\tpassive: true,\n\t\t} as EventListenerOptions)\n\t\tdocument.addEventListener('touchend', this._swipeTouchEndListener, {\n\t\t\tcapture: true,\n\t\t\tpassive: true,\n\t\t} as EventListenerOptions)\n\t}\n\n\tprivate _detachSwipeGestureListeners(): void {\n\t\tif (this._swipeTouchStartListener) {\n\t\t\tdocument.removeEventListener('touchstart', this._swipeTouchStartListener, true)\n\t\t\tthis._swipeTouchStartListener = null\n\t\t}\n\t\tif (this._swipeTouchEndListener) {\n\t\t\tdocument.removeEventListener('touchend', this._swipeTouchEndListener, true)\n\t\t\tthis._swipeTouchEndListener = null\n\t\t}\n\t\tthis._swipeTouchStartY = null\n\t}\n\n\tprivate _attachWheelFallbackListener(): void {\n\t\tif (this._wheelListener || typeof window === 'undefined') return\n\n\t\tthis._wheelListener = (e: WheelEvent) => {\n\t\t\tconst scrollEl = document.scrollingElement || document.documentElement\n\t\t\tif (scrollEl.scrollHeight > scrollEl.clientHeight) return\n\n\t\t\tlet deltaY = e.deltaY\n\t\t\tif (e.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n\t\t\t\tdeltaY *= WHEEL_DELTA_LINE_MULTIPLIER\n\t\t\t} else if (e.deltaMode === WheelEvent.DOM_DELTA_PAGE) {\n\t\t\t\tdeltaY *= WHEEL_DELTA_PAGE_MULTIPLIER\n\t\t\t}\n\n\t\t\tif ((deltaY > 0 && this._wheelDelta < 0) || (deltaY < 0 && this._wheelDelta > 0)) {\n\t\t\t\tthis._wheelDelta = 0\n\t\t\t}\n\t\t\tthis._wheelDelta += deltaY\n\n\t\t\tif (this._wheelDelta > PIP_SCROLL_DIRECTION_THRESHOLD && !this._pipHiddenByScroll) {\n\t\t\t\tthis._pipHiddenByScroll = true\n\t\t\t\tthis._wheelDelta = 0\n\t\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\t\tthis._applyPipVisualState()\n\t\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t\t}\n\t\t\t} else if (this._wheelDelta < -PIP_SCROLL_DIRECTION_THRESHOLD && this._pipHiddenByScroll) {\n\t\t\t\tthis._pipHiddenByScroll = false\n\t\t\t\tthis._wheelDelta = 0\n\t\t\t\tif (this._agent?.getAttribute('display-mode') === 'pip') {\n\t\t\t\t\tthis._applyPipVisualState()\n\t\t\t\t\tthis._applyAgentLayout('pip')\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdocument.addEventListener('wheel', this._wheelListener, {\n\t\t\tcapture: true,\n\t\t\tpassive: true,\n\t\t} as EventListenerOptions)\n\t}\n\n\tprivate _detachWheelFallbackListener(): void {\n\t\tif (this._wheelListener) {\n\t\t\tdocument.removeEventListener('wheel', this._wheelListener, true)\n\t\t\tthis._wheelListener = null\n\t\t}\n\t\tthis._wheelDelta = 0\n\t}\n\n\tprivate _handlePillClick = (): void => {\n\t\tif (this._isHoverDevice()) {\n\t\t\tthis.setOpen(true)\n\t\t} else {\n\t\t\tif (this._pipExpanded) {\n\t\t\t\tthis.setOpen(true)\n\t\t\t} else {\n\t\t\t\tthis._setPipExpanded(true)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _handlePillKeydown = (event: Event): void => {\n\t\tconst key = (event as KeyboardEvent).key\n\t\tif (key === 'Enter' || key === ' ') {\n\t\t\tevent.preventDefault()\n\t\t\tthis.setOpen(true)\n\t\t}\n\t}\n\n\tprivate _hidePipPill(): void {\n\t\tif (this._pipPillElement) {\n\t\t\tsetStyleValue(this._pipPillElement, 'opacity', '0')\n\t\t\tsetStyleValue(this._pipPillElement, 'pointer-events', 'none')\n\t\t}\n\t}\n\n\tprivate _resetHostLayoutStyles(): void {\n\t\tfor (const name of [\n\t\t\t'position',\n\t\t\t'flex',\n\t\t\t'width',\n\t\t\t'min-width',\n\t\t\t'height',\n\t\t\t'z-index',\n\t\t\t'border-left',\n\t\t\t'transition',\n\t\t\t'opacity',\n\t\t\t'will-change',\n\t\t]) {\n\t\t\tresetStyleValue(this, name)\n\t\t}\n\t}\n\n\tprivate _resetAgentLayoutStyles(): void {\n\t\tif (!this._agent) return\n\t\tfor (const name of [\n\t\t\t'position',\n\t\t\t'top',\n\t\t\t'right',\n\t\t\t'bottom',\n\t\t\t'left',\n\t\t\t'transform',\n\t\t\t'z-index',\n\t\t\t'width',\n\t\t\t'height',\n\t\t\t'max-width',\n\t\t\t'max-height',\n\t\t\t'border-radius',\n\t\t\t'overflow',\n\t\t\t'transition',\n\t\t\t'opacity',\n\t\t\t'pointer-events',\n\t\t]) {\n\t\t\tresetStyleValue(this._agent, name)\n\t\t}\n\t}\n\n\tprivate _applyUnavailableLayout(): void {\n\t\tthis._cancelRevealFade()\n\t\tthis._detachPipInteractionListeners()\n\t\tthis._detachScrollHideListener()\n\t\tthis._detachSwipeGestureListeners()\n\t\tthis._detachWheelFallbackListener()\n\t\tthis._clearPipCollapseTimer()\n\t\tthis._pipExpanded = false\n\t\tthis._pipAnimating = false\n\t\tthis._hidePipPill()\n\t\tif (this._agent) {\n\t\t\tthis._agent.removeAttribute('display-mode')\n\t\t}\n\t\tthis._resetHostLayoutStyles()\n\t\tthis._resetAgentLayoutStyles()\n\t\tthis.hidden = true\n\t}\n\n\tprivate _applyPreReadyLayout(): void {\n\t\tthis._applyUnavailableLayout()\n\t}\n\n\tprivate _startHealthWait(): void {\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tthis._stopHealthWait()\n\t\tthis._applyPreReadyLayout()\n\t\tthis._healthState = 'waiting'\n\t\tthis._healthTimeoutId = window.setTimeout(() => {\n\t\t\tif (this._healthState !== 'waiting') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis._setUnavailable(\n\t\t\t\t'Initialization timed out before the embedded agent became ready.',\n\t\t\t)\n\t\t}, SHELL_HEALTH_TIMEOUT_MS)\n\t}\n\n\tprivate _stopHealthWait(): void {\n\t\tif (this._healthTimeoutId === null || typeof window === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\twindow.clearTimeout(this._healthTimeoutId)\n\t\tthis._healthTimeoutId = null\n\t}\n\n\tprivate _markHealthy(): void {\n\t\tthis._stopHealthWait()\n\t\tthis._healthState = 'healthy'\n\t\tthis.hidden = false\n\t\tthis._applyDisplayModeAndLayout()\n\t\tthis._startRevealFade()\n\t}\n\n\tprivate _cancelRevealFade(): void {\n\t\tif (this._revealFrameId !== null && typeof window !== 'undefined') {\n\t\t\twindow.cancelAnimationFrame(this._revealFrameId)\n\t\t}\n\t\tthis._revealFrameId = null\n\t\tresetStyleValue(this, 'opacity')\n\t\tresetStyleValue(this, 'will-change')\n\t}\n\n\tprivate _startRevealFade(): void {\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn\n\t\t}\n\t\tthis._cancelRevealFade()\n\t\tsetStyleValue(this, 'opacity', '0')\n\t\tsetStyleValue(this, 'will-change', 'opacity')\n\t\tthis._revealFrameId = window.requestAnimationFrame(() => {\n\t\t\tthis._revealFrameId = null\n\t\t\tsetStyleValue(this, 'opacity', '1')\n\t\t\twindow.setTimeout(() => {\n\t\t\t\tif (this._healthState === 'healthy') {\n\t\t\t\t\tresetStyleValue(this, 'will-change')\n\t\t\t\t}\n\t\t\t}, SHELL_REVEAL_FADE_MS)\n\t\t})\n\t}\n\n\tprivate _setUnavailable(message: string): void {\n\t\tthis._stopHealthWait()\n\t\tthis._healthState = 'unavailable'\n\t\tthis._pendingConnectOptions = null\n\t\tthis._pipMeasuredHeight = null\n\t\tthis._setOpenInternal(false, { emit: true, reflect: true })\n\t\tthis._applyUnavailableLayout()\n\t\tthis.dispatchEvent(\n\t\t\tnew CustomEvent('char-error', {\n\t\t\t\tbubbles: true,\n\t\t\t\tcomposed: true,\n\t\t\t\tdetail: {\n\t\t\t\t\tcode: 'SHELL_UNAVAILABLE',\n\t\t\t\t\tmessage,\n\t\t\t\t} satisfies CharErrorDetail,\n\t\t\t}),\n\t\t)\n\t}\n\n\tprivate _recoverFromUnavailable(): void {\n\t\tif (this._healthState !== 'unavailable') {\n\t\t\treturn\n\t\t}\n\t\tthis._healthState = 'idle'\n\t\tthis._pipMeasuredHeight = null\n\t\tthis._detachForwardedListeners()\n\t\tif (this._agent) {\n\t\t\tthis._agent.remove()\n\t\t\tthis._agent = null\n\t\t}\n\t\tthis._forwardedListenersAttached = false\n\t\tthis._ensureAgent()\n\t\tthis._syncForwardedAttributes()\n\t\tthis._applyPreReadyLayout()\n\t\tconst agent = this._agent as CharAgentElement | null\n\t\tif (Object.keys(this._pendingHostContext).length > 0) {\n\t\t\tif (agent) {\n\t\t\t\tagent.setHostContext(this._pendingHostContext)\n\t\t\t}\n\t\t\tthis._pendingHostContext = {}\n\t\t}\n\t}\n\n\tprivate _setOpenInternal(\n\t\tnextOpen: boolean,\n\t\toptions: { emit: boolean; reflect: boolean },\n\t): void {\n\t\tif (this._healthState === 'unavailable' && nextOpen) {\n\t\t\tthis._reflectOpenAttribute(false)\n\t\t\treturn\n\t\t}\n\n\t\tif (nextOpen === this._open) {\n\t\t\tif (options.reflect) {\n\t\t\t\tthis._reflectOpenAttribute(nextOpen)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tthis._open = nextOpen\n\t\tif (options.reflect) {\n\t\t\tthis._reflectOpenAttribute(nextOpen)\n\t\t}\n\n\t\tthis._applyDisplayModeAndLayout()\n\n\t\tif (options.emit) {\n\t\t\tthis.dispatchEvent(\n\t\t\t\tnew CustomEvent<CharShellOpenChangeDetail>(SHELL_OPEN_CHANGE_EVENT, {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcomposed: true,\n\t\t\t\t\tdetail: { open: nextOpen },\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate _reflectOpenAttribute(open: boolean): void {\n\t\tthis._isApplyingOpenAttribute = true\n\t\tapplyOpenAttribute(this, open)\n\t\tthis._isApplyingOpenAttribute = false\n\t}\n\n\tprivate _flushPendingConnectAndContext(): void {\n\t\tif (!this._agent) return\n\n\t\tif (this._pendingConnectOptions) {\n\t\t\tconst ok = this._agent.connect(this._pendingConnectOptions)\n\t\t\tif (ok) {\n\t\t\t\tthis._startHealthWait()\n\t\t\t}\n\t\t}\n\n\t\tif (Object.keys(this._pendingHostContext).length > 0) {\n\t\t\tthis._agent.setHostContext(this._pendingHostContext)\n\t\t\tthis._pendingHostContext = {}\n\t\t}\n\t}\n\n\tprivate _handleRequestDisplayMode = (event: Event): void => {\n\t\tif (this._healthState === 'unavailable') {\n\t\t\treturn\n\t\t}\n\t\tconst detail = (event as CustomEvent<CharRequestDisplayModeDetail>).detail\n\t\tif (!isDisplayMode(detail?.mode)) {\n\t\t\treturn\n\t\t}\n\n\t\tif (detail.mode === 'pip') {\n\t\t\tthis.setOpen(false)\n\t\t\treturn\n\t\t}\n\t\tthis.setOpen(true)\n\t}\n\n\tprivate _handleClose = (): void => {\n\t\tthis.setOpen(false)\n\t}\n\n\tprivate _handleInitialized = (): void => {\n\t\tthis._markHealthy()\n\t}\n\n\tprivate _handleInnerError = (event: Event): void => {\n\t\tif (this._healthState !== 'waiting') {\n\t\t\treturn\n\t\t}\n\t\tconst detail = (event as CustomEvent<{ message?: string }>).detail\n\t\tthis._setUnavailable(\n\t\t\tdetail?.message ??\n\t\t\t\t'Embedded agent initialization failed before it became available.',\n\t\t)\n\t}\n\n\tprivate _handleInnerSizeChanged = (event: Event): void => {\n\t\tif (!this._agent || this._agent.getAttribute('display-mode') !== 'pip') {\n\t\t\treturn\n\t\t}\n\t\tconst detail = (event as CustomEvent<CharSizeChangedDetail>).detail\n\t\t// Reject size reports from before the iframe applied pip layout.\n\t\tif (detail?.displayMode !== 'pip') {\n\t\t\treturn\n\t\t}\n\n\t\tconst reportedHeight = detail?.height\n\t\tif (typeof reportedHeight !== 'number' || !Number.isFinite(reportedHeight) || reportedHeight <= 0) {\n\t\t\treturn\n\t\t}\n\n\t\tconst nextMeasuredHeight = Math.max(\n\t\t\tPIP_MIN_COLLAPSED_HEIGHT,\n\t\t\tMath.min(Math.round(reportedHeight), PIP_MAX_MEASURED_HEIGHT),\n\t\t)\n\n\t\t// Buffer size reports during animation; they're flushed when the morph ends.\n\t\tif (this._pipAnimating) {\n\t\t\tthis._pendingPipMeasuredHeight = nextMeasuredHeight\n\t\t\treturn\n\t\t}\n\n\t\tif (this._pipMeasuredHeight === nextMeasuredHeight) {\n\t\t\treturn\n\t\t}\n\n\t\tthis._pipMeasuredHeight = nextMeasuredHeight\n\t\tthis._applyAgentLayout('pip')\n\t}\n}\n\n/**\n * Registers the `<char-agent-shell>` custom element.\n *\n * @param tagName - Optional custom tag name override.\n *\n * @public\n */\nexport function registerCharShell(tagName = 'char-agent-shell'): void {\n\tif (typeof window === 'undefined') return\n\tif (!customElements.get(tagName)) {\n\t\tcustomElements.define(tagName, CharAgentShellElement)\n\t}\n}\n\nregisterCharShell()\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'char-agent-shell': CharAgentShellElement\n\t}\n\n\t/* biome-ignore lint/style/noNamespace: JSX intrinsic-elements augmentation uses namespace syntax by TypeScript design. */\n\tnamespace JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'char-agent-shell': {\n\t\t\t\topen?: boolean\n\t\t\t\t'fullscreen-breakpoint'?: number\n\t\t\t\t'panel-width'?: number\n\t\t\t\t'pip-position'?: CharPipPosition\n\t\t\t\t'pip-width'?: number\n\t\t\t\t'pip-height'?: number\n\t\t\t\t'dev-mode'?: string\n\t\t\t\tdevMode?: DevModeConfig\n\t\t\t\t'api-base'?: string\n\t\t\t\tapiBase?: string\n\t\t\t\t'enable-debug-tools'?: boolean\n\t\t\t\tref?: unknown\n\t\t\t\t[key: string]: unknown\n\t\t\t}\n\t\t}\n\t}\n}\n\ndeclare module 'react/jsx-runtime' {\n\t/* biome-ignore lint/style/noNamespace: JSX intrinsic-elements augmentation uses namespace syntax by TypeScript design. */\n\tnamespace JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t'char-agent-shell': {\n\t\t\t\topen?: boolean\n\t\t\t\t'fullscreen-breakpoint'?: number\n\t\t\t\t'panel-width'?: number\n\t\t\t\t'pip-position'?: CharPipPosition\n\t\t\t\t'pip-width'?: number\n\t\t\t\t'pip-height'?: number\n\t\t\t\t'dev-mode'?: string\n\t\t\t\tdevMode?: DevModeConfig\n\t\t\t\t'api-base'?: string\n\t\t\t\tapiBase?: string\n\t\t\t\t'enable-debug-tools'?: boolean\n\t\t\t\tref?: unknown\n\t\t\t\t[key: string]: unknown\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":"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ACA;CAGA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CAGA;CACA;CACA;CACA;AAED,MAAM,8BAA8B;CAEnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CAGA;CAGA;CACA;CACA;CACA;CACA;AAED,MAAa,0BAA0B,CACtC,GAAG,4BACH,GAAG,4BACH;;;;;;;;;;;;AC/MD,MAAa,kCAAkC;CAC9C;CACA;CACA;CACA;;;;;;;;;AAuBD,SAAgB,cACf,OAC2B;AAC3B,QAAO,UAAU,YAAY,UAAU,gBAAgB,UAAU;;;;;;;;;;;;;;;;;AAkBlE,SAAgB,sBAAsB,MAA4C;AACjF,QAAO,SAAS,YAAY,SAAS;;;;;;;;;;;;;;;AAgBtC,SAAgB,4BACf,WACA,iBAA6C,iCAC3B;AAClB,KAAI,eAAe,WAAW,EAC7B,QAAO;AAGR,KAAI,eAAe,SAAS,UAAU,CACrC,QAAO;AAGR,SAAQ,MAAM,wBAAwB,UAAU,4BAA4B,eAAe,KAAK,KAAK,CAAC,YAAY,eAAe,GAAG,GAAG;AACvI,QAAO,eAAe;;;;;;;;;;;;;;;;;;AAmBvB,SAAgB,yBAAyB,SAIrB;CACnB,MAAM,iBAAiB,QAAQ,kBAAkB;AAOjD,QAAO,4BAN4B,QAAQ,OACxC,QAAQ,mBAC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"}