@aomi-labs/react 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +426 -619
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -57
- package/dist/index.d.ts +58 -57
- package/dist/index.js +443 -646
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/runtime/aomi-runtime.tsx","../src/contexts/control-context.tsx","../src/utils/uuid.ts","../src/state/thread-store.ts","../src/contexts/event-context.tsx","../src/state/event-buffer.ts","../src/contexts/notification-context.tsx","../src/contexts/thread-context.tsx","../src/contexts/user-context.tsx","../src/runtime/core.tsx","../src/runtime/orchestrator.ts","../src/runtime/utils.ts","../src/state/backend-state.ts","../src/runtime/message-controller.ts","../src/runtime/polling-controller.ts","../src/runtime/threadlist-adapter.ts","../src/interface.tsx","../src/handlers/wallet-handler.ts","../src/state/wallet-buffer.ts","../src/handlers/notification-handler.ts"],"sourcesContent":["// =============================================================================\n// API Client (re-exported from @aomi-labs/client)\n// =============================================================================\nexport { AomiClient } from \"@aomi-labs/client\";\nexport type { AomiClientOptions } from \"@aomi-labs/client\";\nexport type {\n AomiMessage,\n AomiChatResponse,\n AomiCreateThreadResponse,\n AomiInterruptResponse,\n AomiSSEEvent,\n AomiStateResponse,\n AomiSystemEvent,\n AomiSystemResponse,\n AomiThread,\n} from \"@aomi-labs/client\";\nexport { toViemSignTypedDataArgs } from \"@aomi-labs/client\";\n\n// =============================================================================\n// Runtime Provider\n// =============================================================================\nexport { AomiRuntimeProvider } from \"./runtime/aomi-runtime\";\nexport type { AomiRuntimeProviderProps } from \"./runtime/aomi-runtime\";\n\n// =============================================================================\n// Unified Runtime API\n// =============================================================================\nexport { useAomiRuntime } from \"./interface\";\nexport type { AomiRuntimeApi } from \"./interface\";\n\n// =============================================================================\n// Event System (follows RUNTIME-ARCH.md)\n// =============================================================================\nexport {\n useEventContext,\n EventContextProvider,\n} from \"./contexts/event-context\";\nexport type {\n EventContext,\n EventContextProviderProps,\n} from \"./contexts/event-context\";\n\nexport type {\n InboundEvent,\n OutboundEvent,\n SSEStatus,\n EventSubscriber,\n EventBuffer,\n} from \"./state/event-buffer\";\n\nexport type {\n WalletBuffer,\n} from \"./state/wallet-buffer\";\n\n// =============================================================================\n// Handler Hooks\n// =============================================================================\nexport { useWalletHandler } from \"./handlers/wallet-handler\";\nexport { useNotificationHandler } from \"./handlers/notification-handler\";\nexport type {\n WalletRequest,\n WalletTxPayload,\n WalletEip712Payload,\n WalletRequestKind,\n WalletRequestStatus,\n WalletRequestResult,\n WalletHandlerConfig,\n WalletHandlerApi,\n} from \"./handlers/wallet-handler\";\nexport type {\n NotificationHandlerConfig,\n NotificationApi,\n} from \"./handlers/notification-handler\";\n\n// =============================================================================\n// User Context (wallet/user state)\n// =============================================================================\nexport {\n useUser,\n UserContextProvider,\n type UserState,\n} from \"./contexts/user-context\";\n\n// User config type (for render prop pattern)\nexport type { UserConfig } from \"./runtime/utils\";\n\n// =============================================================================\n// Thread Context (for UI components)\n// =============================================================================\nexport {\n useThreadContext,\n useCurrentThreadMessages,\n useCurrentThreadMetadata,\n ThreadContextProvider,\n} from \"./contexts/thread-context\";\nexport type { ThreadContext } from \"./contexts/thread-context\";\nexport type { ThreadMetadata, ThreadControlState } from \"./state/thread-store\";\nexport { initThreadControl } from \"./state/thread-store\";\n\n// =============================================================================\n// Utilities\n// =============================================================================\nexport {\n cn,\n formatAddress,\n getNetworkName,\n getChainInfo,\n SUPPORTED_CHAINS,\n type ChainInfo,\n} from \"./runtime/utils\";\n\n// =============================================================================\n// Notification Context (for toast UI)\n// =============================================================================\nexport {\n useNotification,\n NotificationContextProvider,\n type Notification,\n type NotificationType,\n type NotificationData as ShowNotificationParams,\n type NotificationContextApi as NotificationContextValue,\n type NotificationContextProviderProps,\n} from \"./contexts/notification-context\";\n\n// =============================================================================\n// Control Context (model/app/api-key state)\n// =============================================================================\nexport {\n useControl,\n ControlContextProvider,\n type ControlState,\n type ControlContextApi,\n type ControlContextProviderProps,\n} from \"./contexts/control-context\";\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { AomiClient } from \"@aomi-labs/client\";\nimport { ControlContextProvider } from \"../contexts/control-context\";\nimport { EventContextProvider } from \"../contexts/event-context\";\nimport { NotificationContextProvider } from \"../contexts/notification-context\";\nimport {\n ThreadContextProvider,\n useThreadContext,\n} from \"../contexts/thread-context\";\nimport { UserContextProvider, useUser } from \"../contexts/user-context\";\nimport { AomiRuntimeCore } from \"./core\";\n\n// =============================================================================\n// Props\n// =============================================================================\n\nexport type AomiRuntimeProviderProps = {\n children: ReactNode;\n backendUrl?: string;\n};\n\n// =============================================================================\n// Provider Shell\n// =============================================================================\n\nexport function AomiRuntimeProvider({\n children,\n backendUrl = \"http://localhost:8080\",\n}: Readonly<AomiRuntimeProviderProps>) {\n const aomiClient = useMemo(() => new AomiClient({ baseUrl: backendUrl }), [backendUrl]);\n\n return (\n <ThreadContextProvider>\n <NotificationContextProvider>\n <UserContextProvider>\n <AomiRuntimeInner aomiClient={aomiClient}>\n {children}\n </AomiRuntimeInner>\n </UserContextProvider>\n </NotificationContextProvider>\n </ThreadContextProvider>\n );\n}\n\n// =============================================================================\n// Inner Provider (needs ThreadContext and UserContext)\n// =============================================================================\n\ntype AomiRuntimeInnerProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n};\n\nfunction AomiRuntimeInner({\n children,\n aomiClient,\n}: Readonly<AomiRuntimeInnerProps>) {\n const threadContext = useThreadContext();\n const { user } = useUser();\n\n return (\n <ControlContextProvider\n aomiClient={aomiClient}\n sessionId={threadContext.currentThreadId}\n publicKey={user.address ?? undefined}\n getThreadMetadata={threadContext.getThreadMetadata}\n updateThreadMetadata={threadContext.updateThreadMetadata}\n >\n <EventContextProvider\n aomiClient={aomiClient}\n sessionId={threadContext.currentThreadId}\n >\n <AomiRuntimeCore aomiClient={aomiClient}>{children}</AomiRuntimeCore>\n </EventContextProvider>\n </ControlContextProvider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n useEffect,\n type ReactNode,\n} from \"react\";\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport type { ThreadMetadata, ThreadControlState } from \"../state/thread-store\";\nimport { initThreadControl } from \"../state/thread-store\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Global control state (shared across all threads) */\nexport type ControlState = {\n /** API key for authenticated requests */\n apiKey: string | null;\n /** Stable client identifier for this browser tab (associates sessions with secrets) */\n clientId: string | null;\n /** Available models fetched from backend */\n availableModels: string[];\n /** Authorized apps fetched from backend */\n authorizedApps: string[];\n /** Default model (first from availableModels) */\n defaultModel: string | null;\n /** Default app (from authorizedApps) */\n defaultApp: string | null;\n};\n\nexport type ControlContextApi = {\n /** Global state (apiKey, clientId, available models/apps) */\n state: ControlState;\n /** Update global state (apiKey only) */\n setApiKey: (apiKey: string | null) => void;\n /** Ingest secrets into the backend vault, returns opaque handles */\n ingestSecrets: (secrets: Record<string, string>) => Promise<Record<string, string>>;\n /** Clear all secrets from the backend vault */\n clearSecrets: () => Promise<void>;\n /** Fetch available models from backend */\n getAvailableModels: () => Promise<string[]>;\n /** Fetch authorized apps from backend */\n getAuthorizedApps: () => Promise<string[]>;\n /** Get current thread's control state */\n getCurrentThreadControl: () => ThreadControlState;\n /** Get the current thread's effective app after auth fallback */\n getCurrentThreadApp: () => string;\n /** Select a model for the current thread (updates metadata + calls backend) */\n onModelSelect: (model: string) => Promise<void>;\n /** Select an app for the current thread (updates metadata only) */\n onAppSelect: (app: string) => void;\n /** Whether the current thread is processing (disables control switching) */\n isProcessing: boolean;\n /** Mark control state as synced (called after chat starts) */\n markControlSynced: () => void;\n /** Get global control state */\n getControlState: () => ControlState;\n /** Subscribe to global state changes */\n onControlStateChange: (callback: (state: ControlState) => void) => () => void;\n\n // Legacy compatibility\n /** @deprecated Use getCurrentThreadControl().app instead */\n setState: (\n updates: Partial<{ app: string | null; apiKey: string | null }>,\n ) => void;\n};\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst API_KEY_STORAGE_KEY = \"aomi_api_key\";\n\nfunction getDefaultApp(apps: string[]): string | null {\n return apps.includes(\"default\") ? \"default\" : (apps[0] ?? null);\n}\n\nfunction resolveAuthorizedApp(\n app: string | null | undefined,\n authorizedApps: string[],\n defaultApp: string | null,\n): string | null {\n if (app && authorizedApps.includes(app)) {\n return app;\n }\n return defaultApp;\n}\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst ControlContext = createContext<ControlContextApi | null>(null);\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useControl(): ControlContextApi {\n const ctx = useContext(ControlContext);\n if (!ctx) {\n throw new Error(\"useControl must be used within ControlContextProvider\");\n }\n return ctx;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport type ControlContextProviderProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n sessionId: string;\n publicKey?: string;\n /** Get metadata for a thread */\n getThreadMetadata: (threadId: string) => ThreadMetadata | undefined;\n /** Update metadata for a thread */\n updateThreadMetadata: (\n threadId: string,\n updates: Partial<ThreadMetadata>,\n ) => void;\n};\n\nexport function ControlContextProvider({\n children,\n aomiClient,\n sessionId,\n publicKey,\n getThreadMetadata,\n updateThreadMetadata,\n}: ControlContextProviderProps) {\n const [state, setStateInternal] = useState<ControlState>(() => ({\n apiKey: null,\n clientId: null,\n availableModels: [],\n authorizedApps: [],\n defaultModel: null,\n defaultApp: null,\n }));\n\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const aomiClientRef = useRef(aomiClient);\n aomiClientRef.current = aomiClient;\n\n const sessionIdRef = useRef(sessionId);\n sessionIdRef.current = sessionId;\n\n const publicKeyRef = useRef(publicKey);\n publicKeyRef.current = publicKey;\n\n const getThreadMetadataRef = useRef(getThreadMetadata);\n getThreadMetadataRef.current = getThreadMetadata;\n\n const updateThreadMetadataRef = useRef(updateThreadMetadata);\n updateThreadMetadataRef.current = updateThreadMetadata;\n\n const callbacks = useRef<Set<(state: ControlState) => void>>(new Set());\n\n // Compute isProcessing from current thread's control state\n const currentThreadMetadata = getThreadMetadata(sessionId);\n const isProcessing = currentThreadMetadata?.control?.isProcessing ?? false;\n\n // Generate a stable client_id for this browser tab on mount\n useEffect(() => {\n const clientId = globalThis.crypto?.randomUUID?.() ?? `client-${Date.now()}`;\n setStateInternal((prev) => ({ ...prev, clientId }));\n }, []);\n\n // Load API key from localStorage on mount\n useEffect(() => {\n try {\n const storedApiKey =\n globalThis.localStorage?.getItem(API_KEY_STORAGE_KEY) ?? null;\n if (storedApiKey) {\n setStateInternal((prev) => ({ ...prev, apiKey: storedApiKey }));\n }\n } catch {\n // localStorage not available\n }\n }, []);\n\n // Persist API key to localStorage\n useEffect(() => {\n try {\n if (state.apiKey) {\n globalThis.localStorage?.setItem(API_KEY_STORAGE_KEY, state.apiKey);\n } else {\n globalThis.localStorage?.removeItem(API_KEY_STORAGE_KEY);\n }\n } catch {\n // localStorage not available\n }\n }, [state.apiKey]);\n\n // Fetch apps whenever the auth context changes\n useEffect(() => {\n const fetchApps = async () => {\n try {\n const apps = await aomiClientRef.current.getApps(\n sessionIdRef.current,\n {\n publicKey: publicKeyRef.current,\n apiKey: stateRef.current.apiKey ?? undefined,\n },\n );\n const defaultApp = getDefaultApp(apps);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: apps,\n defaultApp,\n }));\n } catch (error) {\n console.error(\"Failed to fetch apps:\", error);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: [\"default\"],\n defaultApp: \"default\",\n }));\n }\n };\n void fetchApps();\n }, [state.apiKey, publicKey, sessionId]);\n\n // Fetch models on mount\n useEffect(() => {\n const fetchModels = async () => {\n try {\n const models = await aomiClientRef.current.getModels(\n sessionIdRef.current,\n );\n setStateInternal((prev) => ({\n ...prev,\n availableModels: models,\n defaultModel: models[0] ?? null,\n }));\n } catch (error) {\n console.error(\"Failed to fetch models:\", error);\n }\n };\n void fetchModels();\n }, []);\n\n // ---------------------------------------------------------------------------\n // API Key\n // ---------------------------------------------------------------------------\n const setApiKey = useCallback((apiKey: string | null) => {\n setStateInternal((prev) => {\n const next = { ...prev, apiKey: apiKey === \"\" ? null : apiKey };\n callbacks.current.forEach((cb) => cb(next));\n return next;\n });\n }, []);\n\n // ---------------------------------------------------------------------------\n // Secrets\n // ---------------------------------------------------------------------------\n const ingestSecrets = useCallback(\n async (secrets: Record<string, string>): Promise<Record<string, string>> => {\n const clientId = stateRef.current.clientId;\n if (!clientId) throw new Error(\"clientId not initialized\");\n const { handles } = await aomiClientRef.current.ingestSecrets(\n clientId,\n secrets,\n );\n return handles;\n },\n [],\n );\n\n const clearSecrets = useCallback(async (): Promise<void> => {\n const clientId = stateRef.current.clientId;\n if (!clientId) return;\n await aomiClientRef.current.clearSecrets?.(clientId);\n }, []);\n\n // ---------------------------------------------------------------------------\n // Fetch available options\n // ---------------------------------------------------------------------------\n const getAvailableModels = useCallback(async (): Promise<string[]> => {\n try {\n const models = await aomiClientRef.current.getModels(\n sessionIdRef.current,\n );\n setStateInternal((prev) => ({\n ...prev,\n availableModels: models,\n defaultModel: prev.defaultModel ?? models[0] ?? null,\n }));\n return models;\n } catch (error) {\n console.error(\"Failed to fetch models:\", error);\n return [];\n }\n }, []);\n\n const getAuthorizedApps = useCallback(async (): Promise<string[]> => {\n try {\n const apps = await aomiClientRef.current.getApps(\n sessionIdRef.current,\n {\n publicKey: publicKeyRef.current,\n apiKey: stateRef.current.apiKey ?? undefined,\n },\n );\n const defaultApp = getDefaultApp(apps);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: apps,\n defaultApp,\n }));\n return apps;\n } catch (error) {\n console.error(\"Failed to fetch apps:\", error);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: [\"default\"],\n defaultApp: \"default\",\n }));\n return [\"default\"];\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Per-thread control state\n // ---------------------------------------------------------------------------\n const getCurrentThreadControl = useCallback((): ThreadControlState => {\n const metadata = getThreadMetadataRef.current(sessionIdRef.current);\n return metadata?.control ?? initThreadControl();\n }, []);\n\n const getCurrentThreadApp = useCallback((): string => {\n const currentControl =\n getThreadMetadataRef.current(sessionIdRef.current)?.control ??\n initThreadControl();\n return (\n resolveAuthorizedApp(\n currentControl.app,\n stateRef.current.authorizedApps,\n stateRef.current.defaultApp,\n ) ?? \"default\"\n );\n }, []);\n\n const onModelSelect = useCallback(async (model: string) => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n const isProcessing = currentControl.isProcessing;\n\n console.log(\"[control-context] onModelSelect called\", {\n model,\n isProcessing,\n threadId,\n });\n\n if (isProcessing) {\n console.warn(\"[control-context] Cannot switch model while processing\");\n return;\n }\n\n const app =\n resolveAuthorizedApp(\n currentControl.app,\n stateRef.current.authorizedApps,\n stateRef.current.defaultApp,\n ) ?? \"default\";\n\n console.log(\"[control-context] onModelSelect updating metadata\", {\n threadId,\n model,\n app,\n currentControl,\n });\n\n // Update thread metadata with new model and mark as dirty\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...currentControl,\n model,\n app,\n controlDirty: true,\n },\n });\n\n console.log(\"[control-context] onModelSelect calling backend setModel\", {\n threadId,\n model,\n app,\n backendUrl: aomiClientRef.current,\n });\n\n try {\n const result = await aomiClientRef.current.setModel(\n threadId,\n model,\n { app, apiKey: stateRef.current.apiKey ?? undefined },\n );\n console.log(\"[control-context] onModelSelect backend result\", result);\n } catch (err) {\n console.error(\"[control-context] setModel failed:\", err);\n throw err;\n }\n }, []);\n\n const onAppSelect = useCallback((app: string) => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n const isProcessing = currentControl.isProcessing;\n\n console.log(\"[control-context] onAppSelect called\", {\n app,\n isProcessing,\n threadId,\n });\n\n if (isProcessing) {\n console.warn(\n \"[control-context] Cannot switch app while processing\",\n );\n return;\n }\n\n if (\n stateRef.current.authorizedApps.length > 0 &&\n !stateRef.current.authorizedApps.includes(app)\n ) {\n console.warn(\"[control-context] Cannot select unauthorized app\", { app });\n return;\n }\n\n console.log(\"[control-context] onAppSelect updating metadata\", {\n threadId,\n app,\n currentControl,\n });\n\n // Update thread metadata with new app and mark as dirty\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...currentControl,\n app,\n controlDirty: true,\n },\n });\n\n console.log(\"[control-context] onAppSelect metadata updated\");\n }, []);\n\n const markControlSynced = useCallback(() => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n\n if (currentControl.controlDirty) {\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...currentControl,\n controlDirty: false,\n },\n });\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Global state access\n // ---------------------------------------------------------------------------\n const getControlState = useCallback(() => stateRef.current, []);\n\n const onControlStateChange = useCallback(\n (callback: (state: ControlState) => void) => {\n callbacks.current.add(callback);\n return () => {\n callbacks.current.delete(callback);\n };\n },\n [],\n );\n\n // ---------------------------------------------------------------------------\n // Legacy compatibility\n // ---------------------------------------------------------------------------\n const setState = useCallback(\n (updates: Partial<{ app: string | null; apiKey: string | null }>) => {\n if (\"apiKey\" in updates) {\n setApiKey(updates.apiKey ?? null);\n }\n if (\n \"app\" in updates &&\n updates.app !== undefined &&\n updates.app !== null\n ) {\n onAppSelect(updates.app);\n }\n },\n [setApiKey, onAppSelect],\n );\n\n return (\n <ControlContext.Provider\n value={{\n state,\n setApiKey,\n ingestSecrets,\n clearSecrets,\n getAvailableModels,\n getAuthorizedApps,\n getCurrentThreadControl,\n getCurrentThreadApp,\n onModelSelect,\n onAppSelect,\n isProcessing,\n markControlSynced,\n getControlState,\n onControlStateChange,\n setState,\n }}\n >\n {children}\n </ControlContext.Provider>\n );\n}\n","// UUID polyfill for Safari and older browsers\nexport function generateUUID(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n\n // Fallback for browsers without crypto.randomUUID\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { generateUUID } from \"../utils/uuid\";\nimport type { SetStateAction } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\nimport { ThreadContext } from \"../contexts/thread-context\";\n\nconst shouldLogThreadUpdates = process.env.NODE_ENV !== \"production\";\n\nconst logThreadMetadataChange = (\n source: string,\n threadId: string,\n prev: ThreadMetadata | undefined,\n next: ThreadMetadata | undefined,\n) => {\n if (!shouldLogThreadUpdates) return;\n if (!prev && !next) return;\n if (!prev || !next) {\n console.debug(`[aomi][thread:${source}]`, { threadId, prev, next });\n return;\n }\n if (\n prev.title !== next.title ||\n prev.status !== next.status ||\n prev.lastActiveAt !== next.lastActiveAt\n ) {\n console.debug(`[aomi][thread:${source}]`, { threadId, prev, next });\n }\n};\n\nexport type ThreadStatus = \"regular\" | \"archived\";\n\nexport type ThreadControlState = {\n /** Selected model for this thread (human-readable label) */\n model: string | null;\n /** Selected app for this thread */\n app: string | null;\n /** Whether control state has changed but chat hasn't started yet */\n controlDirty: boolean;\n /** Whether this thread is currently processing (assistant generating) */\n isProcessing: boolean;\n};\n\nexport type ThreadMetadata = {\n title: string;\n status: ThreadStatus;\n lastActiveAt?: string | number;\n /** Per-thread control state (model, app selection) */\n control: ThreadControlState;\n};\n\n/** Create default control state for a new thread */\nexport function initThreadControl(): ThreadControlState {\n return {\n model: null,\n app: null,\n controlDirty: false,\n isProcessing: false,\n };\n}\n\ntype ThreadStoreState = {\n currentThreadId: string;\n threadViewKey: number;\n threadCnt: number;\n threads: Map<string, ThreadMessageLike[]>;\n threadMetadata: Map<string, ThreadMetadata>;\n};\n\ntype ThreadStoreOptions = {\n initialThreadId?: string;\n};\n\nexport class ThreadStore {\n private state: ThreadStoreState;\n private listeners = new Set<() => void>();\n private snapshot: ThreadContext;\n\n constructor(options?: ThreadStoreOptions) {\n const initialThreadId = options?.initialThreadId ?? generateUUID();\n this.state = {\n currentThreadId: initialThreadId,\n threadViewKey: 0,\n threadCnt: 1,\n threads: new Map([[initialThreadId, []]]),\n threadMetadata: new Map([\n [\n initialThreadId,\n {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n },\n ],\n ]),\n };\n\n this.snapshot = this.buildSnapshot();\n }\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): ThreadContext => this.snapshot;\n\n private emit() {\n for (const listener of this.listeners) {\n listener();\n }\n }\n\n private resolveStateAction<T>(updater: SetStateAction<T>, current: T): T {\n return typeof updater === \"function\"\n ? (updater as (prev: T) => T)(current)\n : updater;\n }\n\n private ensureThreadExists(threadId: string) {\n if (!this.state.threadMetadata.has(threadId)) {\n const nextMetadata = new Map(this.state.threadMetadata);\n nextMetadata.set(threadId, {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n });\n this.state = { ...this.state, threadMetadata: nextMetadata };\n }\n\n if (!this.state.threads.has(threadId)) {\n const nextThreads = new Map(this.state.threads);\n nextThreads.set(threadId, []);\n this.state = { ...this.state, threads: nextThreads };\n }\n }\n\n private updateState(partial: Partial<ThreadStoreState>) {\n this.state = { ...this.state, ...partial };\n this.snapshot = this.buildSnapshot();\n this.emit();\n }\n\n private buildSnapshot(): ThreadContext {\n return {\n currentThreadId: this.state.currentThreadId,\n setCurrentThreadId: this.setCurrentThreadId,\n threadViewKey: this.state.threadViewKey,\n bumpThreadViewKey: this.bumpThreadViewKey,\n allThreads: this.state.threads,\n setThreads: this.setThreads,\n allThreadsMetadata: this.state.threadMetadata,\n setThreadMetadata: this.setThreadMetadata,\n threadCnt: this.state.threadCnt,\n setThreadCnt: this.setThreadCnt,\n getThreadMessages: this.getThreadMessages,\n setThreadMessages: this.setThreadMessages,\n getThreadMetadata: this.getThreadMetadata,\n updateThreadMetadata: this.updateThreadMetadata,\n };\n }\n\n setCurrentThreadId = (threadId: string) => {\n this.ensureThreadExists(threadId);\n this.updateState({ currentThreadId: threadId });\n };\n\n bumpThreadViewKey = () => {\n this.updateState({ threadViewKey: this.state.threadViewKey + 1 });\n };\n\n setThreadCnt = (updater: SetStateAction<number>) => {\n const nextCnt = this.resolveStateAction(updater, this.state.threadCnt);\n this.updateState({ threadCnt: nextCnt });\n };\n\n setThreads = (updater: SetStateAction<Map<string, ThreadMessageLike[]>>) => {\n const nextThreads = this.resolveStateAction(updater, this.state.threads);\n this.updateState({ threads: new Map(nextThreads) });\n };\n\n setThreadMetadata = (\n updater: SetStateAction<Map<string, ThreadMetadata>>,\n ) => {\n const prevMetadata = this.state.threadMetadata;\n const nextMetadata = this.resolveStateAction(updater, prevMetadata);\n for (const [threadId, next] of nextMetadata.entries()) {\n logThreadMetadataChange(\n \"setThreadMetadata\",\n threadId,\n prevMetadata.get(threadId),\n next,\n );\n }\n for (const [threadId, prev] of prevMetadata.entries()) {\n if (!nextMetadata.has(threadId)) {\n logThreadMetadataChange(\"setThreadMetadata\", threadId, prev, undefined);\n }\n }\n this.updateState({ threadMetadata: new Map(nextMetadata) });\n };\n\n setThreadMessages = (threadId: string, messages: ThreadMessageLike[]) => {\n this.ensureThreadExists(threadId);\n const nextThreads = new Map(this.state.threads);\n nextThreads.set(threadId, messages);\n this.updateState({ threads: nextThreads });\n };\n\n getThreadMessages = (threadId: string): ThreadMessageLike[] => {\n return this.state.threads.get(threadId) ?? [];\n };\n\n getThreadMetadata = (threadId: string): ThreadMetadata | undefined => {\n return this.state.threadMetadata.get(threadId);\n };\n\n updateThreadMetadata = (\n threadId: string,\n updates: Partial<ThreadMetadata>,\n ) => {\n const existing = this.state.threadMetadata.get(threadId);\n if (!existing) {\n return;\n }\n const next = { ...existing, ...updates };\n const nextMetadata = new Map(this.state.threadMetadata);\n nextMetadata.set(threadId, next);\n logThreadMetadataChange(\"updateThreadMetadata\", threadId, existing, next);\n this.updateState({ threadMetadata: nextMetadata });\n };\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport type { AomiClient, AomiSSEEvent, AomiSystemEvent } from \"@aomi-labs/client\";\nimport {\n isInlineCall,\n isSystemNotice,\n isSystemError,\n isAsyncCallback,\n} from \"@aomi-labs/client\";\nimport {\n createEventBuffer,\n dispatch,\n enqueueInbound,\n setSSEStatus,\n subscribe as subscribeToBuffer,\n type EventBuffer,\n type EventSubscriber,\n type InboundEvent,\n type OutboundEvent,\n type SSEStatus,\n} from \"../state/event-buffer\";\n// =============================================================================\n// Context Type\n// =============================================================================\n\nexport type EventContext = {\n /** Subscribe to inbound events by type. Returns unsubscribe function. */\n subscribe: (type: string, callback: EventSubscriber) => () => void;\n /** Send an outbound event to backend immediately */\n sendOutboundSystem: (event: Omit<OutboundEvent, \"timestamp\">) => Promise<void>;\n /** Dispatch system events from HTTP polling into the event buffer */\n dispatchInboundSystem: (sessionId: string, events: AomiSystemEvent[]) => void;\n /** Current SSE connection status */\n sseStatus: SSEStatus;\n};\n\nconst EventContextState = createContext<EventContext | null>(null);\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useEventContext(): EventContext {\n const context = useContext(EventContextState);\n if (!context) {\n throw new Error(\n \"useEventContext must be used within EventContextProvider. \" +\n \"Wrap your app with <EventContextProvider>...</EventContextProvider>\",\n );\n }\n return context;\n}\n\n// =============================================================================\n// Provider Props\n// =============================================================================\n\nexport type EventContextProviderProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n sessionId: string;\n};\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport function EventContextProvider({\n children,\n aomiClient,\n sessionId,\n}: EventContextProviderProps) {\n const bufferRef = useRef<EventBuffer | null>(null);\n if (!bufferRef.current) {\n bufferRef.current = createEventBuffer();\n }\n const buffer = bufferRef.current!;\n\n const [sseStatus, setSseStatus] = useState<SSEStatus>(\"disconnected\");\n\n // ---------------------------------------------------------------------------\n // SSE Subscription (reconnects when sessionId changes)\n // ---------------------------------------------------------------------------\n useEffect(() => {\n setSSEStatus(buffer, \"connecting\");\n setSseStatus(\"connecting\");\n\n const unsubscribe = aomiClient.subscribeSSE(\n sessionId,\n (event: AomiSSEEvent) => {\n enqueueInbound(buffer, {\n type: event.type,\n sessionId: event.session_id,\n payload: event,\n });\n\n const inboundEvent: InboundEvent = {\n type: event.type,\n sessionId: event.session_id,\n payload: event,\n status: \"fetched\",\n timestamp: Date.now(),\n };\n dispatch(buffer, inboundEvent);\n },\n (error) => {\n console.error(\"SSE error:\", error);\n setSSEStatus(buffer, \"disconnected\");\n setSseStatus(\"disconnected\");\n },\n );\n\n setSSEStatus(buffer, \"connected\");\n setSseStatus(\"connected\");\n\n return () => {\n unsubscribe();\n setSSEStatus(buffer, \"disconnected\");\n setSseStatus(\"disconnected\");\n };\n }, [aomiClient, sessionId, buffer]);\n\n // ---------------------------------------------------------------------------\n // Context Value\n // ---------------------------------------------------------------------------\n const subscribeCallback = useCallback(\n (type: string, callback: EventSubscriber) => {\n return subscribeToBuffer(buffer, type, callback);\n },\n [buffer],\n );\n\n const sendOutbound = useCallback(\n async (event: Omit<OutboundEvent, \"timestamp\">) => {\n try {\n const message = JSON.stringify({\n type: event.type,\n payload: event.payload,\n });\n await aomiClient.sendSystemMessage(event.sessionId, message);\n } catch (error) {\n console.error(\"Failed to send outbound event:\", error);\n }\n },\n [aomiClient],\n );\n\n const dispatchSystemEvents = useCallback(\n (sessionId: string, events: AomiSystemEvent[]) => {\n for (const event of events) {\n let eventType: string;\n let payload: unknown;\n\n // Unwrap the tagged enum from backend serialization\n if (isInlineCall(event)) {\n // InlineCall has inner type like \"wallet_tx_request\"\n eventType = event.InlineCall.type;\n payload = event.InlineCall.payload ?? event.InlineCall;\n } else if (isSystemNotice(event)) {\n eventType = \"system_notice\";\n payload = { message: event.SystemNotice };\n } else if (isSystemError(event)) {\n eventType = \"system_error\";\n payload = { message: event.SystemError };\n } else if (isAsyncCallback(event)) {\n eventType = \"async_callback\";\n payload = event.AsyncCallback;\n } else {\n console.warn(\"Unknown system event type:\", event);\n continue;\n }\n\n const inboundEvent: InboundEvent = {\n type: eventType,\n sessionId,\n payload,\n status: \"fetched\",\n timestamp: Date.now(),\n };\n enqueueInbound(buffer, {\n type: eventType,\n sessionId,\n payload,\n });\n dispatch(buffer, inboundEvent);\n }\n },\n [buffer],\n );\n\n const contextValue: EventContext = {\n subscribe: subscribeCallback,\n sendOutboundSystem: sendOutbound,\n dispatchInboundSystem: dispatchSystemEvents,\n sseStatus,\n };\n\n return (\n <EventContextState.Provider value={contextValue}>\n {children}\n </EventContextState.Provider>\n );\n}\n","export type InboundEvent = {\n type: string;\n sessionId: string;\n payload?: unknown;\n status: \"pending\" | \"fetched\";\n timestamp: number;\n};\n\nexport type OutboundEvent = {\n type: string;\n sessionId: string;\n payload: unknown;\n timestamp: number;\n};\n\nexport type SSEStatus = \"connected\" | \"connecting\" | \"disconnected\";\n\nexport type EventSubscriber = (event: InboundEvent) => void;\n\nexport type EventBuffer = {\n inboundQueue: InboundEvent[];\n outboundQueue: OutboundEvent[];\n sseStatus: SSEStatus;\n lastEventId: string | null;\n subscribers: Map<string, Set<EventSubscriber>>;\n};\n\nexport function createEventBuffer(): EventBuffer {\n return {\n inboundQueue: [],\n outboundQueue: [],\n sseStatus: \"disconnected\",\n lastEventId: null,\n subscribers: new Map(),\n };\n}\n\n// =============================================================================\n// Inbound Queue Helpers\n// =============================================================================\n\nexport function enqueueInbound(\n state: EventBuffer,\n event: Omit<InboundEvent, \"status\" | \"timestamp\">,\n): void {\n state.inboundQueue.push({\n ...event,\n status: \"pending\",\n timestamp: Date.now(),\n });\n}\n\nexport function dequeueInbound(state: EventBuffer): InboundEvent | null {\n return state.inboundQueue.shift() ?? null;\n}\n\nexport function peekInbound(state: EventBuffer): InboundEvent | null {\n return state.inboundQueue[0] ?? null;\n}\n\nexport function markFetched(\n state: EventBuffer,\n event: InboundEvent,\n payload: unknown,\n): void {\n event.status = \"fetched\";\n event.payload = payload;\n}\n\nexport function hasInbound(state: EventBuffer): boolean {\n return state.inboundQueue.length > 0;\n}\n\n// =============================================================================\n// Outbound Queue Helpers\n// =============================================================================\n\nexport function enqueueOutbound(\n state: EventBuffer,\n event: Omit<OutboundEvent, \"timestamp\">,\n): void {\n state.outboundQueue.push({\n ...event,\n timestamp: Date.now(),\n });\n}\n\nexport function drainOutbound(state: EventBuffer): OutboundEvent[] {\n const events = [...state.outboundQueue];\n state.outboundQueue = [];\n return events;\n}\n\nexport function hasOutbound(state: EventBuffer): boolean {\n return state.outboundQueue.length > 0;\n}\n\n// =============================================================================\n// Subscription Helpers\n// =============================================================================\n\nexport function subscribe(\n state: EventBuffer,\n type: string,\n callback: EventSubscriber,\n): () => void {\n if (!state.subscribers.has(type)) {\n state.subscribers.set(type, new Set());\n }\n state.subscribers.get(type)!.add(callback);\n\n // Return unsubscribe function\n return () => {\n state.subscribers.get(type)?.delete(callback);\n };\n}\n\nexport function subscribeAll(\n state: EventBuffer,\n callback: EventSubscriber,\n): () => void {\n return subscribe(state, \"*\", callback);\n}\n\nexport function dispatch(state: EventBuffer, event: InboundEvent): void {\n // Dispatch to specific type subscribers\n const typeSubscribers = state.subscribers.get(event.type);\n if (typeSubscribers) {\n for (const callback of typeSubscribers) {\n callback(event);\n }\n }\n\n // Dispatch to wildcard subscribers\n const allSubscribers = state.subscribers.get(\"*\");\n if (allSubscribers) {\n for (const callback of allSubscribers) {\n callback(event);\n }\n }\n}\n\n// =============================================================================\n// SSE Status Helpers\n// =============================================================================\n\nexport function setSSEStatus(state: EventBuffer, status: SSEStatus): void {\n state.sseStatus = status;\n}\n\nexport function setLastEventId(state: EventBuffer, id: string): void {\n state.lastEventId = id;\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useState,\n type ReactNode,\n} from \"react\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type NotificationType = \"notice\" | \"success\" | \"error\" | \"wallet\";\n\nexport type Notification = {\n id: string;\n type: NotificationType;\n title: string;\n message?: string;\n duration?: number;\n timestamp: number;\n};\n\nexport type NotificationData = Omit<Notification, \"id\" | \"timestamp\">;\n\nexport type NotificationContextApi = {\n /** All active notifications */\n notifications: Notification[];\n /** Show a new notification */\n showNotification: (params: NotificationData) => string;\n /** Dismiss a notification by ID */\n dismissNotification: (id: string) => void;\n /** Clear all notifications */\n clearAll: () => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst NotificationContext = createContext<NotificationContextApi | null>(null);\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useNotification(): NotificationContextApi {\n const context = useContext(NotificationContext);\n if (!context) {\n throw new Error(\n \"useNotification must be used within NotificationContextProvider\",\n );\n }\n return context;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nlet notificationIdCounter = 0;\nfunction generateId(): string {\n return `notif-${Date.now()}-${++notificationIdCounter}`;\n}\n\nexport type NotificationContextProviderProps = {\n children: ReactNode;\n};\n\nexport function NotificationContextProvider({\n children,\n}: NotificationContextProviderProps) {\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n const showNotification = useCallback((params: NotificationData) => {\n const id = generateId();\n const notification: Notification = {\n ...params,\n id,\n timestamp: Date.now(),\n };\n setNotifications((prev) => [notification, ...prev]);\n return id;\n }, []);\n\n const dismissNotification = useCallback((id: string) => {\n setNotifications((prev) => prev.filter((n) => n.id !== id));\n }, []);\n\n const clearAll = useCallback(() => {\n setNotifications([]);\n }, []);\n\n const value: NotificationContextApi = {\n notifications,\n showNotification,\n dismissNotification,\n clearAll,\n };\n\n return (\n <NotificationContext.Provider value={value}>\n {children}\n </NotificationContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport type { ReactNode, SetStateAction } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\nimport { ThreadMetadata, ThreadStore } from \"../state/thread-store\";\n\nexport type ThreadContext = {\n currentThreadId: string;\n setCurrentThreadId: (id: string) => void;\n threadViewKey: number;\n bumpThreadViewKey: () => void;\n allThreads: Map<string, ThreadMessageLike[]>;\n setThreads: (\n updater: SetStateAction<Map<string, ThreadMessageLike[]>>,\n ) => void;\n allThreadsMetadata: Map<string, ThreadMetadata>;\n setThreadMetadata: (\n updater: SetStateAction<Map<string, ThreadMetadata>>,\n ) => void;\n threadCnt: number;\n setThreadCnt: (updater: SetStateAction<number>) => void;\n getThreadMessages: (threadId: string) => ThreadMessageLike[];\n setThreadMessages: (threadId: string, messages: ThreadMessageLike[]) => void;\n getThreadMetadata: (threadId: string) => ThreadMetadata | undefined;\n updateThreadMetadata: (\n threadId: string,\n updates: Partial<ThreadMetadata>,\n ) => void;\n};\n\nexport type ThreadContextProviderProps = {\n children: ReactNode;\n initialThreadId?: string;\n};\n\nconst ThreadContextState = createContext<ThreadContext | null>(null);\n\nexport function useThreadContext(): ThreadContext {\n const context = useContext(ThreadContextState);\n if (!context) {\n throw new Error(\n \"useThreadContext must be used within ThreadContextProvider. \" +\n \"Wrap your app with <ThreadContextProvider>...</ThreadContextProvider>\",\n );\n }\n return context;\n}\n\nexport function ThreadContextProvider({\n children,\n initialThreadId,\n}: ThreadContextProviderProps) {\n const storeRef = useRef<ThreadStore | null>(null);\n if (!storeRef.current) {\n storeRef.current = new ThreadStore({ initialThreadId });\n }\n const store = storeRef.current;\n const value = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n\n return (\n <ThreadContextState.Provider value={value}>\n {children}\n </ThreadContextState.Provider>\n );\n}\n\nexport function useCurrentThreadMessages(): ThreadMessageLike[] {\n const { currentThreadId, getThreadMessages } = useThreadContext();\n return useMemo(\n () => getThreadMessages(currentThreadId),\n [currentThreadId, getThreadMessages],\n );\n}\n\nexport function useCurrentThreadMetadata(): ThreadMetadata | undefined {\n const { currentThreadId, getThreadMetadata } = useThreadContext();\n return useMemo(\n () => getThreadMetadata(currentThreadId),\n [currentThreadId, getThreadMetadata],\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nexport type UserState = {\n address?: string;\n chainId?: number;\n isConnected: boolean;\n ensName?: string;\n ext?: Record<string, unknown>;\n};\n\ntype UserContextValue = {\n user: UserState;\n setUser: (data: Partial<UserState>) => void;\n addExtValue: (key: string, value: unknown) => void;\n removeExtValue: (key: string) => void;\n getUserState: () => UserState;\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n};\n\nconst UserContext = createContext<UserContextValue | undefined>(undefined);\n\nexport function useUser() {\n const context = useContext(UserContext);\n if (!context) {\n throw new Error(\"useUser must be used within UserContextProvider\");\n }\n // Return only the public API\n return {\n user: context.user,\n setUser: context.setUser,\n addExtValue: context.addExtValue,\n removeExtValue: context.removeExtValue,\n getUserState: context.getUserState,\n onUserStateChange: context.onUserStateChange,\n };\n}\n\n// ==================== Provider ====================\n\nexport function UserContextProvider({ children }: { children: ReactNode }) {\n const [user, setUserState] = useState<UserState>({\n isConnected: false,\n address: undefined,\n chainId: undefined,\n ensName: undefined,\n ext: undefined,\n });\n\n // Refs for stable getter functions\n const userRef = useRef(user);\n userRef.current = user;\n\n // Store callbacks in a ref\n const StateChangeCallbacks = useRef<Set<(user: UserState) => void>>(\n new Set(),\n );\n\n const setUser = useCallback((data: Partial<UserState>) => {\n setUserState((prev) => {\n const next = { ...prev, ...data };\n\n // Notify all subscribers\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n\n return next;\n });\n }, []);\n\n const addExtValue = useCallback((key: string, value: unknown) => {\n setUserState((prev) => {\n const next = {\n ...prev,\n ext: {\n ...(prev.ext ?? {}),\n [key]: value,\n },\n };\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n return next;\n });\n }, []);\n\n const removeExtValue = useCallback((key: string) => {\n setUserState((prev) => {\n if (!prev.ext || !(key in prev.ext)) {\n return prev;\n }\n const nextExt = { ...prev.ext };\n delete nextExt[key];\n const next = {\n ...prev,\n ext: Object.keys(nextExt).length > 0 ? nextExt : undefined,\n };\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n return next;\n });\n }, []);\n\n // Stable getters that runtime classes can call\n const getUserState = useCallback(() => userRef.current, []);\n\n // Subscribe to user state changes\n const onUserStateChange = useCallback(\n (callback: (user: UserState) => void) => {\n StateChangeCallbacks.current.add(callback);\n\n // Return unsubscribe function\n return () => {\n StateChangeCallbacks.current.delete(callback);\n };\n },\n [],\n );\n\n return (\n <UserContext.Provider\n value={{\n user,\n setUser,\n addExtValue,\n removeExtValue,\n getUserState,\n onUserStateChange,\n }}\n >\n {children}\n </UserContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {\n AssistantRuntimeProvider,\n useExternalStoreRuntime,\n type AppendMessage,\n} from \"@assistant-ui/react\";\n\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport { useControl } from \"../contexts/control-context\";\nimport { useEventContext } from \"../contexts/event-context\";\nimport { useUser } from \"../contexts/user-context\";\nimport { useThreadContext } from \"../contexts/thread-context\";\nimport { useNotification } from \"../contexts/notification-context\";\nimport { useRuntimeOrchestrator } from \"./orchestrator\";\nimport {\n isThreadRunning,\n resolveThreadId,\n} from \"../state/backend-state\";\nimport { isPlaceholderTitle } from \"./utils\";\nimport { buildThreadListAdapter } from \"./threadlist-adapter\";\nimport { AomiRuntimeApiProvider, type AomiRuntimeApi } from \"../interface\";\nimport { initThreadControl } from \"../state/thread-store\";\nimport { useWalletHandler } from \"../handlers/wallet-handler\";\n\n// =============================================================================\n// Core Props\n// =============================================================================\n\nexport type AomiRuntimeCoreProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n};\n\n// =============================================================================\n// Core Component\n// =============================================================================\n\nexport function AomiRuntimeCore({\n children,\n aomiClient,\n}: Readonly<AomiRuntimeCoreProps>) {\n const threadContext = useThreadContext();\n const eventContext = useEventContext();\n const notificationContext = useNotification();\n const { dispatchInboundSystem: dispatchSystemEvents } = eventContext;\n const { user, onUserStateChange, getUserState } = useUser();\n const { getControlState, getCurrentThreadApp, clearSecrets } = useControl();\n\n const {\n backendStateRef,\n polling,\n messageController,\n isRunning,\n setIsRunning,\n ensureInitialState,\n aomiClientRef,\n } = useRuntimeOrchestrator(aomiClient, {\n onSyncEvents: dispatchSystemEvents,\n getPublicKey: () => getUserState().address,\n getUserState,\n getApp: getCurrentThreadApp,\n getApiKey: () => getControlState().apiKey,\n getClientId: () => getControlState().clientId ?? undefined,\n });\n\n const walletSnapshot = useCallback(\n (nextUser: ReturnType<typeof getUserState>) => ({\n address: nextUser.address,\n chainId: nextUser.chainId,\n isConnected: nextUser.isConnected,\n ensName: nextUser.ensName,\n }),\n [getUserState],\n );\n\n const lastWalletStateRef = useRef(walletSnapshot(getUserState()));\n\n // ---------------------------------------------------------------------------\n // Send wallet state changes to backend\n // ---------------------------------------------------------------------------\n useEffect(() => {\n lastWalletStateRef.current = walletSnapshot(getUserState());\n\n const unsubscribe = onUserStateChange(async (newUser) => {\n const nextWalletState = walletSnapshot(newUser);\n const prevWalletState = lastWalletStateRef.current;\n if (\n prevWalletState.address === nextWalletState.address &&\n prevWalletState.chainId === nextWalletState.chainId &&\n prevWalletState.isConnected === nextWalletState.isConnected &&\n prevWalletState.ensName === nextWalletState.ensName\n ) {\n return;\n }\n\n lastWalletStateRef.current = nextWalletState;\n const sessionId = threadContext.currentThreadId;\n const message = JSON.stringify({\n type: \"wallet:state_changed\",\n payload: nextWalletState,\n });\n await aomiClientRef.current.sendSystemMessage(sessionId, message);\n });\n\n return unsubscribe;\n }, [\n onUserStateChange,\n aomiClientRef,\n threadContext.currentThreadId,\n getUserState,\n walletSnapshot,\n ]);\n\n // ---------------------------------------------------------------------------\n // Refs for stable access\n // ---------------------------------------------------------------------------\n const threadContextRef = useRef(threadContext);\n threadContextRef.current = threadContext;\n\n const currentThreadIdRef = useRef(threadContext.currentThreadId);\n useEffect(() => {\n currentThreadIdRef.current = threadContext.currentThreadId;\n }, [threadContext.currentThreadId]);\n\n // ---------------------------------------------------------------------------\n // Wallet handler (queue management for tx + eip712 requests)\n // ---------------------------------------------------------------------------\n const onWalletRequestComplete = useCallback(() => {\n polling.start(currentThreadIdRef.current);\n }, [polling]);\n\n const walletHandler = useWalletHandler({\n sessionId: threadContext.currentThreadId,\n onRequestComplete: onWalletRequestComplete,\n });\n\n // ---------------------------------------------------------------------------\n // Respond to user_state_request from backend\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = eventContext.subscribe(\n \"user_state_request\",\n () => {\n eventContext.sendOutboundSystem({\n type: \"user_state_response\",\n sessionId: threadContext.currentThreadId,\n payload: getUserState(),\n });\n },\n );\n return unsubscribe;\n }, [eventContext, threadContext.currentThreadId, getUserState]);\n\n // ---------------------------------------------------------------------------\n // Initial state fetch on thread change\n // ---------------------------------------------------------------------------\n useEffect(() => {\n void ensureInitialState(threadContext.currentThreadId);\n }, [ensureInitialState, threadContext.currentThreadId]);\n\n useEffect(() => {\n const threadId = threadContext.currentThreadId;\n setIsRunning(isThreadRunning(backendStateRef.current, threadId));\n }, [backendStateRef, setIsRunning, threadContext.currentThreadId]);\n\n // Sync isRunning to thread metadata for control context\n useEffect(() => {\n const threadId = threadContext.currentThreadId;\n const currentMeta = threadContext.getThreadMetadata(threadId);\n if (currentMeta && currentMeta.control.isProcessing !== isRunning) {\n threadContext.updateThreadMetadata(threadId, {\n control: {\n ...currentMeta.control,\n isProcessing: isRunning,\n },\n });\n }\n }, [isRunning, threadContext]);\n\n const currentMessages = threadContext.getThreadMessages(\n threadContext.currentThreadId,\n );\n\n // ---------------------------------------------------------------------------\n // Fetch thread list when user connects\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const userAddress = user.address;\n if (!userAddress) return;\n\n const fetchThreadList = async () => {\n try {\n const threadList =\n await aomiClientRef.current.listThreads(userAddress);\n const currentContext = threadContextRef.current;\n const newMetadata = new Map(currentContext.allThreadsMetadata);\n let maxChatNum = currentContext.threadCnt;\n\n for (const thread of threadList) {\n const rawTitle = thread.title ?? \"\";\n const title = isPlaceholderTitle(rawTitle) ? \"\" : rawTitle;\n const lastActive =\n newMetadata.get(thread.session_id)?.lastActiveAt ||\n new Date().toISOString();\n const existingControl = newMetadata.get(thread.session_id)?.control;\n newMetadata.set(thread.session_id, {\n title,\n status: thread.is_archived ? \"archived\" : \"regular\",\n lastActiveAt: lastActive,\n control: existingControl ?? initThreadControl(),\n });\n\n const match = title.match(/^Chat (\\d+)$/);\n if (match) {\n const num = parseInt(match[1], 10);\n if (num > maxChatNum) {\n maxChatNum = num;\n }\n }\n }\n\n currentContext.setThreadMetadata(newMetadata);\n if (maxChatNum > currentContext.threadCnt) {\n currentContext.setThreadCnt(maxChatNum);\n }\n } catch (error) {\n console.error(\"Failed to fetch thread list:\", error);\n }\n };\n\n void fetchThreadList();\n }, [user.address, aomiClientRef]);\n\n // ---------------------------------------------------------------------------\n // Thread list adapter\n // ---------------------------------------------------------------------------\n const threadListAdapter = useMemo(\n () =>\n buildThreadListAdapter({\n backendStateRef,\n aomiClientRef,\n threadContext,\n currentThreadIdRef,\n polling,\n userAddress: user.address,\n setIsRunning,\n getApp: getCurrentThreadApp,\n getApiKey: () => getControlState().apiKey,\n getUserState,\n }),\n [\n aomiClientRef,\n polling,\n user.address,\n backendStateRef,\n setIsRunning,\n threadContext,\n threadContext.currentThreadId,\n threadContext.allThreadsMetadata,\n getControlState,\n getCurrentThreadApp,\n getUserState,\n ],\n );\n\n // ---------------------------------------------------------------------------\n // Listen for title changes via EventContext (shares the single SSE connection)\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const backendState = backendStateRef.current;\n\n const unsubscribe = eventContext.subscribe(\"title_changed\", (event) => {\n const sessionId = event.sessionId;\n const payload = event.payload as { new_title?: string } | undefined;\n const newTitle = payload?.new_title;\n if (typeof newTitle !== \"string\") return;\n\n const targetThreadId = resolveThreadId(backendState, sessionId);\n const normalizedTitle = isPlaceholderTitle(newTitle) ? \"\" : newTitle;\n\n if (process.env.NODE_ENV !== \"production\") {\n console.debug(\"[aomi][sse] title_changed\", {\n sessionId,\n newTitle,\n normalizedTitle,\n currentThreadId: threadContextRef.current.currentThreadId,\n targetThreadId,\n });\n }\n\n threadContextRef.current.setThreadMetadata((prev) => {\n const next = new Map(prev);\n const existing = next.get(targetThreadId);\n const nextStatus =\n existing?.status === \"archived\" ? \"archived\" : \"regular\";\n next.set(targetThreadId, {\n title: normalizedTitle,\n status: nextStatus,\n lastActiveAt: existing?.lastActiveAt ?? new Date().toISOString(),\n control: existing?.control ?? initThreadControl(),\n });\n return next;\n });\n });\n\n return unsubscribe;\n }, [eventContext, backendStateRef]);\n\n // ---------------------------------------------------------------------------\n // Show notifications for tool updates/completions (SSE events)\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const showToolNotification =\n (eventType: \"tool_update\" | \"tool_complete\") =>\n (event: { payload?: unknown }) => {\n const payload = event.payload as Record<string, unknown> | undefined;\n const toolName =\n typeof payload?.tool_name === \"string\"\n ? payload.tool_name\n : undefined;\n const title = toolName\n ? `${eventType === \"tool_update\" ? \"Tool update\" : \"Tool complete\"}: ${toolName}`\n : eventType === \"tool_update\"\n ? \"Tool update\"\n : \"Tool complete\";\n const message =\n typeof payload?.message === \"string\"\n ? payload.message\n : typeof payload?.result === \"string\"\n ? payload.result\n : undefined;\n\n notificationContext.showNotification({\n type: \"notice\",\n title,\n message,\n });\n };\n\n const unsubscribeUpdate = eventContext.subscribe(\n \"tool_update\",\n showToolNotification(\"tool_update\"),\n );\n const unsubscribeComplete = eventContext.subscribe(\n \"tool_complete\",\n showToolNotification(\"tool_complete\"),\n );\n\n return () => {\n unsubscribeUpdate();\n unsubscribeComplete();\n };\n }, [eventContext, notificationContext]);\n\n // ---------------------------------------------------------------------------\n // Show notifications for system notices (SSE events)\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = eventContext.subscribe(\"system_notice\", (event) => {\n const payload = event.payload as { message?: string } | undefined;\n const message = payload?.message;\n\n // TODO: Disable it for now, we don't need async execution\n // notificationContext.showNotification({\n // type: \"notice\",\n // title: \"System notice\",\n // message,\n // });\n });\n\n return unsubscribe;\n }, [eventContext, notificationContext]);\n\n // ---------------------------------------------------------------------------\n // External store runtime\n // ---------------------------------------------------------------------------\n const runtime = useExternalStoreRuntime({\n messages: currentMessages,\n setMessages: (msgs) =>\n threadContext.setThreadMessages(threadContext.currentThreadId, [...msgs]),\n isRunning,\n onNew: (message: AppendMessage) =>\n messageController.outbound(message, threadContext.currentThreadId),\n onCancel: () => messageController.cancel(threadContext.currentThreadId),\n convertMessage: (msg) => msg,\n adapters: { threadList: threadListAdapter },\n });\n\n // ---------------------------------------------------------------------------\n // Cleanup polling and secrets on unmount\n // ---------------------------------------------------------------------------\n useEffect(() => {\n return () => {\n polling.stopAll();\n void clearSecrets();\n };\n }, [polling, clearSecrets]);\n\n // ---------------------------------------------------------------------------\n // Build AomiRuntimeApi\n // ---------------------------------------------------------------------------\n const userContext = useUser();\n\n const sendMessage = useCallback(\n async (text: string) => {\n // Build a minimal AppendMessage - the message controller only extracts text from content\n // Using unknown cast because AppendMessage has complex metadata requirements we don't need\n const appendMessage = {\n role: \"user\",\n content: [{ type: \"text\", text }],\n } as unknown as AppendMessage;\n await messageController.outbound(\n appendMessage,\n threadContext.currentThreadId,\n );\n },\n [messageController, threadContext.currentThreadId],\n );\n\n const cancelGeneration = useCallback(() => {\n messageController.cancel(threadContext.currentThreadId);\n }, [messageController, threadContext.currentThreadId]);\n\n const getMessages = useCallback(\n (threadId?: string) => {\n const id = threadId ?? threadContext.currentThreadId;\n return threadContext.getThreadMessages(id);\n },\n [threadContext],\n );\n\n const createThread = useCallback(async (): Promise<string> => {\n await threadListAdapter.onSwitchToNewThread();\n return threadContextRef.current.currentThreadId;\n }, [threadListAdapter]);\n\n const deleteThread = useCallback(\n async (threadId: string) => {\n await threadListAdapter.onDelete(threadId);\n },\n [threadListAdapter],\n );\n\n const renameThread = useCallback(\n async (threadId: string, title: string) => {\n await threadListAdapter.onRename(threadId, title);\n },\n [threadListAdapter],\n );\n\n const archiveThread = useCallback(\n async (threadId: string) => {\n await threadListAdapter.onArchive(threadId);\n },\n [threadListAdapter],\n );\n\n const selectThread = useCallback(\n (threadId: string) => {\n // Check if thread exists\n if (threadContext.allThreadsMetadata.has(threadId)) {\n threadListAdapter.onSwitchToThread(threadId);\n } else {\n // Thread doesn't exist, create a new one\n void threadListAdapter.onSwitchToNewThread();\n }\n },\n [threadContext.allThreadsMetadata, threadListAdapter],\n );\n\n const aomiRuntimeApi: AomiRuntimeApi = useMemo(\n () => ({\n // User API\n user: userContext.user,\n getUserState: userContext.getUserState,\n setUser: userContext.setUser,\n addExtValue: userContext.addExtValue,\n removeExtValue: userContext.removeExtValue,\n onUserStateChange: userContext.onUserStateChange,\n\n // Thread API\n currentThreadId: threadContext.currentThreadId,\n threadViewKey: threadContext.threadViewKey,\n threadMetadata: threadContext.allThreadsMetadata,\n getThreadMetadata: threadContext.getThreadMetadata,\n createThread,\n deleteThread,\n renameThread,\n archiveThread,\n selectThread,\n\n // Chat API\n isRunning,\n getMessages,\n sendMessage,\n cancelGeneration,\n\n // Notification API\n notifications: notificationContext.notifications,\n showNotification: notificationContext.showNotification,\n dismissNotification: notificationContext.dismissNotification,\n clearAllNotifications: notificationContext.clearAll,\n\n // Wallet API\n pendingWalletRequests: walletHandler.pendingRequests,\n startWalletRequest: walletHandler.startProcessing,\n resolveWalletRequest: walletHandler.resolveRequest,\n rejectWalletRequest: walletHandler.rejectRequest,\n\n // Event API\n subscribe: eventContext.subscribe,\n sendSystemCommand: eventContext.sendOutboundSystem,\n sseStatus: eventContext.sseStatus,\n }),\n [\n userContext,\n threadContext.currentThreadId,\n threadContext.threadViewKey,\n threadContext.allThreadsMetadata,\n threadContext.getThreadMetadata,\n createThread,\n deleteThread,\n renameThread,\n archiveThread,\n selectThread,\n isRunning,\n getMessages,\n sendMessage,\n cancelGeneration,\n notificationContext,\n walletHandler,\n eventContext,\n ],\n );\n\n return (\n <AomiRuntimeApiProvider value={aomiRuntimeApi}>\n <AssistantRuntimeProvider runtime={runtime}>\n {children}\n </AssistantRuntimeProvider>\n </AomiRuntimeApiProvider>\n );\n}\n","import type { MutableRefObject } from \"react\";\nimport { useCallback, useRef, useState } from \"react\";\n\nimport type { AomiClient, AomiMessage, AomiSystemEvent } from \"@aomi-labs/client\";\nimport type { UserState } from \"../contexts/user-context\";\nimport {\n useThreadContext,\n type ThreadContext,\n} from \"../contexts/thread-context\";\nimport { MessageController } from \"./message-controller\";\nimport { PollingController } from \"./polling-controller\";\nimport {\n createBackendState,\n resolveThreadId,\n type BackendState,\n} from \"../state/backend-state\";\n\ntype OrchestratorOptions = {\n getPublicKey?: () => string | undefined;\n getUserState?: () => UserState;\n getApp: () => string;\n getApiKey?: () => string | null;\n getClientId?: () => string | undefined;\n onSyncEvents?: (sessionId: string, events: AomiSystemEvent[]) => void;\n};\n\nexport function useRuntimeOrchestrator(\n aomiClient: AomiClient,\n options: OrchestratorOptions,\n) {\n const threadContext = useThreadContext();\n const threadContextRef = useRef<ThreadContext>(threadContext);\n threadContextRef.current = threadContext;\n const aomiClientRef = useRef(aomiClient);\n aomiClientRef.current = aomiClient;\n const backendStateRef = useRef<BackendState>(createBackendState());\n\n const [isRunning, setIsRunning] = useState(false);\n\n const messageControllerRef: MutableRefObject<MessageController | null> =\n useRef(null);\n const pollingRef: MutableRefObject<PollingController | null> = useRef(null);\n const pendingFetches = useRef<Set<string>>(new Set());\n\n if (!pollingRef.current) {\n pollingRef.current = new PollingController({\n aomiClientRef,\n backendStateRef,\n applyMessages: (threadId: string, msgs?: AomiMessage[] | null) => {\n messageControllerRef.current?.inbound(threadId, msgs);\n },\n onSyncEvents: options.onSyncEvents,\n getUserState: options.getUserState,\n getClientId: options.getClientId,\n onStart: (threadId: string) => {\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(true);\n }\n },\n onStop: (threadId: string) => {\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(false);\n }\n },\n });\n }\n\n if (!messageControllerRef.current) {\n messageControllerRef.current = new MessageController({\n aomiClientRef,\n backendStateRef,\n threadContextRef,\n polling: pollingRef.current,\n setGlobalIsRunning: setIsRunning,\n getPublicKey: options.getPublicKey,\n getApp: options.getApp,\n getApiKey: options.getApiKey,\n getClientId: options.getClientId,\n getUserState: options.getUserState,\n onSyncEvents: options.onSyncEvents,\n });\n }\n\n const ensureInitialState = useCallback(async (threadId: string) => {\n // Skip if already fetching this thread\n if (pendingFetches.current.has(threadId)) return;\n\n const backendThreadId = resolveThreadId(backendStateRef.current, threadId);\n pendingFetches.current.add(threadId);\n\n try {\n const userState = options.getUserState?.();\n const clientId = options.getClientId?.();\n const state = await aomiClientRef.current.fetchState(\n backendThreadId,\n userState,\n clientId,\n );\n messageControllerRef.current?.inbound(threadId, state.messages);\n if (state.system_events?.length && options.onSyncEvents) {\n options.onSyncEvents(backendThreadId, state.system_events);\n }\n\n if (threadContextRef.current.currentThreadId === threadId) {\n if (state.is_processing) {\n setIsRunning(true);\n pollingRef.current?.start(threadId);\n } else {\n setIsRunning(false);\n }\n }\n } catch (error) {\n console.error(\"Failed to fetch initial state:\", error);\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(false);\n }\n } finally {\n pendingFetches.current.delete(threadId);\n }\n }, []);\n\n return {\n backendStateRef,\n polling: pollingRef.current!,\n messageController: messageControllerRef.current!,\n isRunning,\n setIsRunning,\n ensureInitialState,\n aomiClientRef,\n };\n}\n","import type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { AomiMessage } from \"@aomi-labs/client\";\nimport type { UserState } from \"../contexts/user-context\";\n\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge Tailwind CSS classes with conflict resolution.\n * Combines clsx for conditional classes and tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n// ==================== Thread Utilities ====================\n\nexport const parseTimestamp = (value?: string | number) => {\n if (value === undefined || value === null) return 0;\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? (value < 1e12 ? value * 1000 : value) : 0;\n }\n\n const numeric = Number(value);\n if (!Number.isNaN(numeric)) {\n return numeric < 1e12 ? numeric * 1000 : numeric;\n }\n\n const ts = Date.parse(value);\n return Number.isNaN(ts) ? 0 : ts;\n};\n\nexport const isPlaceholderTitle = (title?: string) => {\n const normalized = title?.trim() ?? \"\";\n return !normalized || normalized.startsWith(\"#[\");\n};\n\n// ==================== Message Conversion ====================\n\ntype MessageContentPart =\n Exclude<ThreadMessageLike[\"content\"], string> extends readonly (infer U)[]\n ? U\n : never;\n\nexport function toInboundMessage(msg: AomiMessage): ThreadMessageLike | null {\n if (msg.sender === \"system\") return null;\n\n const content: MessageContentPart[] = [];\n const role: ThreadMessageLike[\"role\"] =\n msg.sender === \"user\" ? \"user\" : \"assistant\";\n\n if (msg.content) {\n content.push({ type: \"text\" as const, text: msg.content });\n }\n\n const [topic, toolContent] = parseToolPayload(msg) ?? [];\n if (topic && toolContent) {\n content.push({\n type: \"tool-call\" as const,\n toolCallId: `tool_${Date.now()}`,\n toolName: topic,\n args: undefined,\n result: (() => {\n try {\n return JSON.parse(toolContent);\n } catch {\n return { args: toolContent };\n }\n })(),\n });\n }\n\n const threadMessage = {\n role,\n content: (content.length > 0\n ? content\n : [{ type: \"text\" as const, text: \"\" }]) as ThreadMessageLike[\"content\"],\n ...(msg.timestamp && { createdAt: new Date(msg.timestamp) }),\n } satisfies ThreadMessageLike;\n\n return threadMessage;\n}\n\nfunction parseToolPayload(msg: AomiMessage): [string, string] | null {\n return parseToolResult(msg.tool_result);\n}\n\nexport function constructUITool(): string {\n return \"\";\n}\n\nfunction parseMessageTimestamp(timestamp?: string) {\n if (!timestamp) return undefined;\n const parsed = new Date(timestamp);\n return Number.isNaN(parsed.valueOf()) ? undefined : parsed;\n}\n\nfunction parseToolResult(\n toolResult: AomiMessage[\"tool_result\"],\n): [string, string] | null {\n if (!toolResult) return null;\n\n if (Array.isArray(toolResult) && toolResult.length === 2) {\n const [topic, content] = toolResult;\n return [String(topic), String(content ?? \"\")];\n }\n\n return null;\n}\n\n// ==================== Wallet Utilities ====================\n\n/**\n * User configuration props for footer components.\n * Provides user state and setter from UserContext.\n */\nexport type UserConfig = {\n user: UserState;\n setUser: (data: Partial<UserState>) => void;\n};\n\nexport type Eip1193Provider = {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n};\n\nexport const getNetworkName = (\n chainId: number | string | undefined,\n): string => {\n if (chainId === undefined) return \"\";\n const id = typeof chainId === \"string\" ? Number(chainId) : chainId;\n switch (id) {\n case 1:\n return \"ethereum\";\n case 137:\n return \"polygon\";\n case 42161:\n return \"arbitrum\";\n case 8453:\n return \"base\";\n case 10:\n return \"optimism\";\n case 11155111:\n return \"sepolia\";\n case 1337:\n case 31337:\n return \"testnet\";\n case 59140:\n return \"linea-sepolia\";\n case 59144:\n return \"linea\";\n default:\n return \"testnet\";\n }\n};\n\nexport const formatAddress = (addr?: string): string =>\n addr ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : \"Connect Wallet\";\n\n// ==================== Chain Metadata ====================\n\n/** Static metadata for a supported chain */\nexport type ChainInfo = { id: number; name: string; ticker: string };\n\n/** All chains supported by the application. Single source of truth. */\nexport const SUPPORTED_CHAINS: ChainInfo[] = [\n { id: 1, name: \"Ethereum\", ticker: \"ETH\" },\n { id: 137, name: \"Polygon\", ticker: \"MATIC\" },\n { id: 42161, name: \"Arbitrum\", ticker: \"ARB\" },\n { id: 8453, name: \"Base\", ticker: \"BASE\" },\n { id: 10, name: \"Optimism\", ticker: \"OP\" },\n { id: 11155111, name: \"Sepolia\", ticker: \"SEP\" },\n];\n\n/** Look up ChainInfo by chain ID. Returns undefined for unknown chains. */\nexport const getChainInfo = (\n chainId: number | undefined,\n): ChainInfo | undefined =>\n chainId === undefined\n ? undefined\n : SUPPORTED_CHAINS.find((c) => c.id === chainId);\n\nexport function normalizeWalletError(error: unknown): {\n rejected: boolean;\n message: string;\n} {\n const e = error as {\n code?: unknown;\n name?: unknown;\n message?: unknown;\n shortMessage?: unknown;\n cause?: unknown;\n };\n const cause = (e?.cause ?? null) as {\n code?: unknown;\n name?: unknown;\n message?: unknown;\n shortMessage?: unknown;\n } | null;\n\n const code =\n (typeof e?.code === \"number\" ? e.code : undefined) ??\n (typeof cause?.code === \"number\" ? cause.code : undefined);\n const name =\n (typeof e?.name === \"string\" ? e.name : undefined) ??\n (typeof cause?.name === \"string\" ? cause.name : undefined);\n const msg =\n (typeof e?.shortMessage === \"string\" ? e.shortMessage : undefined) ??\n (typeof cause?.shortMessage === \"string\"\n ? cause.shortMessage\n : undefined) ??\n (typeof e?.message === \"string\" ? e.message : undefined) ??\n (typeof cause?.message === \"string\" ? cause.message : undefined) ??\n \"Unknown wallet error\";\n\n const rejected =\n code === 4001 ||\n name === \"UserRejectedRequestError\" ||\n name === \"RejectedRequestError\" ||\n /user rejected|rejected the request|denied|request rejected|canceled|cancelled/i.test(\n msg,\n );\n\n return { rejected, message: msg };\n}\n\nexport function toHexQuantity(value: string): string {\n const trimmed = value.trim();\n const asBigInt = BigInt(trimmed);\n return `0x${asBigInt.toString(16)}`;\n}\n\nexport async function pickInjectedProvider(\n publicKey?: string,\n): Promise<Eip1193Provider | undefined> {\n const ethereum = (globalThis as unknown as { ethereum?: unknown })\n .ethereum as (Eip1193Provider & { providers?: unknown[] }) | undefined;\n if (!ethereum?.request) return undefined;\n\n const candidates: Eip1193Provider[] = Array.isArray(ethereum.providers)\n ? (ethereum.providers.filter(\n (p): p is Eip1193Provider => !!(p as Eip1193Provider)?.request,\n ) as Eip1193Provider[])\n : [ethereum];\n\n const target = publicKey?.toLowerCase();\n if (target) {\n for (const candidate of candidates) {\n try {\n const accounts = (await candidate.request({\n method: \"eth_accounts\",\n })) as unknown;\n const list = Array.isArray(accounts)\n ? (accounts as unknown[]).map((a) => String(a).toLowerCase())\n : [];\n if (list.includes(target)) return candidate;\n } catch {\n // Ignore providers that error on eth_accounts.\n }\n }\n }\n\n return candidates[0];\n}\n","export type BackendState = {\n runningThreads: Set<string>;\n};\n\nexport function createBackendState(): BackendState {\n return {\n runningThreads: new Set(),\n };\n}\n\nexport function resolveThreadId(\n _state: BackendState,\n threadId: string,\n): string {\n return threadId;\n}\n\nexport function setThreadRunning(\n state: BackendState,\n threadId: string,\n running: boolean,\n) {\n if (running) {\n state.runningThreads.add(threadId);\n } else {\n state.runningThreads.delete(threadId);\n }\n}\n\nexport function isThreadRunning(\n state: BackendState,\n threadId: string,\n): boolean {\n return state.runningThreads.has(threadId);\n}\n","import type { MutableRefObject } from \"react\";\nimport type { AppendMessage, ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { AomiClient, AomiMessage, AomiSystemEvent } from \"@aomi-labs/client\";\nimport { toInboundMessage } from \"./utils\";\nimport type { ThreadContext } from \"../contexts/thread-context\";\nimport type { PollingController } from \"./polling-controller\";\nimport type { UserState } from \"../contexts/user-context\";\nimport {\n resolveThreadId,\n setThreadRunning,\n type BackendState,\n} from \"../state/backend-state\";\n\ntype MessageControllerConfig = {\n aomiClientRef: MutableRefObject<AomiClient>;\n backendStateRef: MutableRefObject<BackendState>;\n threadContextRef: MutableRefObject<ThreadContext>;\n polling: PollingController;\n setGlobalIsRunning?: (running: boolean) => void;\n getPublicKey?: () => string | undefined;\n getApp: () => string;\n getApiKey?: () => string | null;\n getClientId?: () => string | undefined;\n getUserState?: () => UserState;\n onSyncEvents?: (sessionId: string, events: AomiSystemEvent[]) => void;\n};\n\ntype ThreadContextApi = Pick<\n ThreadContext,\n \"getThreadMessages\" | \"setThreadMessages\" | \"updateThreadMetadata\"\n>;\n\nexport class MessageController {\n constructor(private readonly config: MessageControllerConfig) {}\n\n inbound(threadId: string, msgs?: AomiMessage[] | null) {\n if (!msgs) return;\n\n const threadMessages: ThreadMessageLike[] = [];\n for (const msg of msgs) {\n const threadMessage = toInboundMessage(msg);\n if (threadMessage) {\n threadMessages.push(threadMessage);\n }\n }\n\n this.getThreadContextApi().setThreadMessages(threadId, threadMessages);\n }\n\n async outbound(message: AppendMessage, threadId: string) {\n const backendState = this.config.backendStateRef.current;\n const text = message.content\n .filter(\n (part): part is Extract<typeof part, { type: \"text\" }> =>\n part.type === \"text\",\n )\n .map(\n (part: Extract<(typeof message.content)[number], { type: \"text\" }>) =>\n part.text,\n )\n .join(\"\\n\");\n\n if (!text) return;\n\n const threadState = this.getThreadContextApi();\n const existingMessages = threadState.getThreadMessages(threadId);\n const userMessage: ThreadMessageLike = {\n role: \"user\",\n content: [{ type: \"text\", text }],\n createdAt: new Date(),\n };\n\n threadState.setThreadMessages(threadId, [...existingMessages, userMessage]);\n threadState.updateThreadMetadata(threadId, {\n lastActiveAt: new Date().toISOString(),\n });\n\n const backendThreadId = resolveThreadId(backendState, threadId);\n const app = this.config.getApp();\n const publicKey = this.config.getPublicKey?.();\n const apiKey = this.config.getApiKey?.() ?? undefined;\n const clientId = this.config.getClientId?.();\n const userState = this.config.getUserState?.();\n\n try {\n this.markRunning(threadId, true);\n const response = await this.config.aomiClientRef.current.sendMessage(\n backendThreadId,\n text,\n { app, publicKey, apiKey, userState, clientId },\n );\n\n // Apply the latest messages immediately so sync tool results appear without waiting for polling.\n if (response?.messages) {\n this.inbound(threadId, response.messages);\n }\n\n if (response?.system_events?.length && this.config.onSyncEvents) {\n this.config.onSyncEvents(backendThreadId, response.system_events);\n }\n\n if (response?.is_processing) {\n this.config.polling.start(threadId);\n } else if (!this.config.polling.isPolling(threadId)) {\n this.markRunning(threadId, false);\n }\n } catch (error) {\n console.error(\"Failed to send message:\", error);\n this.markRunning(threadId, false);\n }\n }\n\n async cancel(threadId: string) {\n this.config.polling.stop(threadId);\n const backendState = this.config.backendStateRef.current;\n const backendThreadId = resolveThreadId(backendState, threadId);\n try {\n const response =\n await this.config.aomiClientRef.current.interrupt(backendThreadId);\n if (response?.messages) {\n this.inbound(threadId, response.messages);\n }\n if (response?.system_events?.length && this.config.onSyncEvents) {\n this.config.onSyncEvents(backendThreadId, response.system_events);\n }\n this.markRunning(threadId, false);\n } catch (error) {\n console.error(\"Failed to cancel:\", error);\n }\n }\n\n private markRunning(threadId: string, running: boolean) {\n setThreadRunning(this.config.backendStateRef.current, threadId, running);\n if (this.config.threadContextRef.current.currentThreadId === threadId) {\n this.config.setGlobalIsRunning?.(running);\n }\n }\n\n private getThreadContextApi(): ThreadContextApi {\n const { getThreadMessages, setThreadMessages, updateThreadMetadata } =\n this.config.threadContextRef.current;\n return { getThreadMessages, setThreadMessages, updateThreadMetadata };\n }\n}\n","import type { MutableRefObject } from \"react\";\n\nimport type {\n AomiClient,\n AomiMessage,\n AomiStateResponse,\n AomiSystemEvent,\n} from \"@aomi-labs/client\";\nimport type { UserState } from \"../contexts/user-context\";\nimport {\n resolveThreadId,\n setThreadRunning,\n type BackendState,\n} from \"../state/backend-state\";\n\ntype PollingConfig = {\n aomiClientRef: MutableRefObject<AomiClient>;\n backendStateRef: MutableRefObject<BackendState>;\n applyMessages: (threadId: string, messages?: AomiMessage[] | null) => void;\n onSyncEvents?: (sessionId: string, events: AomiSystemEvent[]) => void;\n getUserState?: () => UserState;\n getClientId?: () => string | undefined;\n onStart?: (threadId: string) => void;\n onStop?: (threadId: string) => void;\n intervalMs?: number;\n};\n\nexport class PollingController {\n private intervals = new Map<string, ReturnType<typeof setInterval>>();\n private intervalMs: number;\n\n constructor(private readonly config: PollingConfig) {\n this.intervalMs = config.intervalMs ?? 500;\n }\n\n start(threadId: string) {\n const backendState = this.config.backendStateRef.current;\n if (this.intervals.has(threadId)) return;\n\n const backendThreadId = resolveThreadId(backendState, threadId);\n setThreadRunning(backendState, threadId, true);\n\n const tick = async () => {\n if (!this.intervals.has(threadId)) return;\n\n try {\n console.log(\n \"[PollingController] Fetching state for threadId:\",\n threadId,\n );\n const userState = this.config.getUserState?.();\n const clientId = this.config.getClientId?.();\n const state = await this.config.aomiClientRef.current.fetchState(\n backendThreadId,\n userState,\n clientId,\n );\n\n if (!this.intervals.has(threadId)) return;\n\n this.handleState(threadId, state);\n } catch (error) {\n console.error(\"Polling error:\", error);\n this.stop(threadId);\n }\n };\n\n const intervalId = setInterval(tick, this.intervalMs);\n this.intervals.set(threadId, intervalId);\n\n this.config.onStart?.(threadId);\n }\n\n stop(threadId: string) {\n const intervalId = this.intervals.get(threadId);\n if (intervalId) {\n clearInterval(intervalId);\n this.intervals.delete(threadId);\n }\n setThreadRunning(this.config.backendStateRef.current, threadId, false);\n this.config.onStop?.(threadId);\n }\n\n isPolling(threadId: string): boolean {\n return this.intervals.has(threadId);\n }\n\n stopAll() {\n for (const threadId of this.intervals.keys()) {\n this.stop(threadId);\n }\n }\n\n private handleState(threadId: string, state: AomiStateResponse) {\n // Dispatch system events (wallet_tx_request, errors, etc.)\n if (state.system_events?.length && this.config.onSyncEvents) {\n const backendState = this.config.backendStateRef.current;\n const sessionId = resolveThreadId(backendState, threadId);\n this.config.onSyncEvents(sessionId, state.system_events);\n }\n\n this.config.applyMessages(threadId, state.messages);\n\n if (!state.is_processing) {\n this.stop(threadId);\n }\n }\n}\n","import { generateUUID } from \"../utils/uuid\";\nimport type { MutableRefObject } from \"react\";\nimport type { ExternalStoreThreadData } from \"@assistant-ui/react\";\n\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport type { ThreadContext } from \"../contexts/thread-context\";\nimport type { UserState } from \"../contexts/user-context\";\nimport { initThreadControl, type ThreadMetadata } from \"../state/thread-store\";\nimport type { BackendState } from \"../state/backend-state\";\nimport type { PollingController } from \"./polling-controller\";\nimport { isPlaceholderTitle, parseTimestamp } from \"./utils\";\n\n// =============================================================================\n// Thread List Helpers\n// =============================================================================\n\nconst sortByLastActiveDesc = (\n [, metaA]: [string, ThreadMetadata],\n [, metaB]: [string, ThreadMetadata],\n) => {\n const tsA = parseTimestamp(metaA.lastActiveAt);\n const tsB = parseTimestamp(metaB.lastActiveAt);\n return tsB - tsA;\n};\n\nfunction buildThreadLists(threadMetadata: Map<string, ThreadMetadata>) {\n const entries = Array.from(threadMetadata.entries()).filter(\n ([, meta]) => !isPlaceholderTitle(meta.title),\n );\n\n const regularThreads = entries\n .filter(([, meta]) => meta.status !== \"archived\")\n .sort(sortByLastActiveDesc)\n .map(\n ([id, meta]): ExternalStoreThreadData<\"regular\"> => ({\n id,\n title: meta.title || \"New Chat\",\n status: \"regular\",\n }),\n );\n\n const archivedThreads = entries\n .filter(([, meta]) => meta.status === \"archived\")\n .sort(sortByLastActiveDesc)\n .map(\n ([id, meta]): ExternalStoreThreadData<\"archived\"> => ({\n id,\n title: meta.title || \"New Chat\",\n status: \"archived\",\n }),\n );\n\n return { regularThreads, archivedThreads };\n}\n\n// =============================================================================\n// Adapter Builder\n// =============================================================================\n\nexport type ThreadListAdapterConfig = {\n backendStateRef: MutableRefObject<BackendState>;\n aomiClientRef: MutableRefObject<AomiClient>;\n threadContext: ThreadContext;\n currentThreadIdRef: MutableRefObject<string>;\n polling: PollingController;\n userAddress?: string;\n setIsRunning: (running: boolean) => void;\n getApp: () => string;\n getApiKey?: () => string | null;\n getUserState?: () => UserState;\n};\n\nexport function buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n}: ThreadListAdapterConfig) {\n const { regularThreads, archivedThreads } = buildThreadLists(\n threadContext.allThreadsMetadata,\n );\n\n return {\n threadId: threadContext.currentThreadId,\n threads: regularThreads,\n archivedThreads,\n\n onSwitchToNewThread: () => {\n const threadId = generateUUID();\n threadContext.setThreadMetadata((prev) =>\n new Map(prev).set(threadId, {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n }),\n );\n threadContext.setThreadMessages(threadId, []);\n threadContext.setCurrentThreadId(threadId);\n setIsRunning(false);\n threadContext.bumpThreadViewKey();\n },\n\n onSwitchToThread: (threadId: string) => {\n threadContext.setCurrentThreadId(threadId);\n threadContext.bumpThreadViewKey();\n },\n\n onRename: async (threadId: string, newTitle: string) => {\n const previousTitle =\n threadContext.getThreadMetadata(threadId)?.title ?? \"\";\n const normalizedTitle = isPlaceholderTitle(newTitle) ? \"\" : newTitle;\n threadContext.updateThreadMetadata(threadId, {\n title: normalizedTitle,\n });\n\n try {\n await aomiClientRef.current.renameThread(threadId, newTitle);\n } catch (error) {\n console.error(\"Failed to rename thread:\", error);\n threadContext.updateThreadMetadata(threadId, {\n title: previousTitle,\n });\n }\n },\n\n onArchive: async (threadId: string) => {\n threadContext.updateThreadMetadata(threadId, { status: \"archived\" });\n\n try {\n await aomiClientRef.current.archiveThread(threadId);\n } catch (error) {\n console.error(\"Failed to archive thread:\", error);\n threadContext.updateThreadMetadata(threadId, { status: \"regular\" });\n }\n },\n\n onUnarchive: async (threadId: string) => {\n threadContext.updateThreadMetadata(threadId, { status: \"regular\" });\n\n try {\n await aomiClientRef.current.unarchiveThread(threadId);\n } catch (error) {\n console.error(\"Failed to unarchive thread:\", error);\n threadContext.updateThreadMetadata(threadId, { status: \"archived\" });\n }\n },\n\n onDelete: async (threadId: string) => {\n try {\n await aomiClientRef.current.deleteThread(threadId);\n\n threadContext.setThreadMetadata((prev) => {\n const next = new Map(prev);\n next.delete(threadId);\n return next;\n });\n threadContext.setThreads((prev) => {\n const next = new Map(prev);\n next.delete(threadId);\n return next;\n });\n\n if (threadContext.currentThreadId === threadId) {\n const firstRegularThread = Array.from(\n threadContext.allThreadsMetadata.entries(),\n ).find(([id, meta]) => meta.status === \"regular\" && id !== threadId);\n\n if (firstRegularThread) {\n threadContext.setCurrentThreadId(firstRegularThread[0]);\n } else {\n const defaultId = \"default-session\";\n threadContext.setThreadMetadata((prev) =>\n new Map(prev).set(defaultId, {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n }),\n );\n threadContext.setThreadMessages(defaultId, []);\n threadContext.setCurrentThreadId(defaultId);\n }\n }\n } catch (error) {\n console.error(\"Failed to delete thread:\", error);\n throw error;\n }\n },\n };\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { UserState } from \"./contexts/user-context\";\nimport type { ThreadMetadata } from \"./state/thread-store\";\nimport type {\n EventSubscriber,\n OutboundEvent,\n SSEStatus,\n} from \"./state/event-buffer\";\nimport type {\n Notification,\n NotificationData,\n} from \"./contexts/notification-context\";\nimport type {\n WalletRequest,\n WalletRequestResult,\n} from \"./handlers/wallet-handler\";\n\n// =============================================================================\n// AomiRuntimeApi Type\n// =============================================================================\n\nexport type AomiRuntimeApi = {\n // -------------------------------------------------------------------------\n // USER API\n // -------------------------------------------------------------------------\n /** Current user state (wallet connection, address, chain, etc.) */\n user: UserState;\n /** Get current user state synchronously (useful in callbacks) */\n getUserState: () => UserState;\n /** Update user state (partial updates merged with existing state) */\n setUser: (data: Partial<UserState>) => void;\n /** Add or overwrite a value in user_state.ext */\n addExtValue: (key: string, value: unknown) => void;\n /** Remove a value from user_state.ext */\n removeExtValue: (key: string) => void;\n /** Subscribe to user state changes. Returns unsubscribe function. */\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n\n // -------------------------------------------------------------------------\n // THREAD API\n // -------------------------------------------------------------------------\n /** ID of the currently active thread */\n currentThreadId: string;\n /** Key that changes when thread view should remount (use for React key prop) */\n threadViewKey: number;\n /** Metadata for all threads (title, status, lastActiveAt) */\n threadMetadata: Map<string, ThreadMetadata>;\n /** Get metadata for a specific thread */\n getThreadMetadata: (threadId: string) => ThreadMetadata | undefined;\n /** Create a new thread and return its ID */\n createThread: () => Promise<string>;\n /** Delete a thread by ID */\n deleteThread: (threadId: string) => Promise<void>;\n /** Rename a thread */\n renameThread: (threadId: string, title: string) => Promise<void>;\n /** Archive a thread */\n archiveThread: (threadId: string) => Promise<void>;\n /** Switch to a thread. If thread doesn't exist, creates a new one. */\n selectThread: (threadId: string) => void;\n\n // -------------------------------------------------------------------------\n // CHAT API\n // -------------------------------------------------------------------------\n /** Whether the assistant is currently generating a response */\n isRunning: boolean;\n /** Get messages for a thread (defaults to currentThreadId) */\n getMessages: (threadId?: string) => ThreadMessageLike[];\n /** Send a message to the current thread */\n sendMessage: (text: string) => Promise<void>;\n /** Cancel the current generation */\n cancelGeneration: () => void;\n\n // -------------------------------------------------------------------------\n // NOTIFICATION API\n // -------------------------------------------------------------------------\n /** All active notifications */\n notifications: Notification[];\n /** Show a notification. Returns the notification ID. */\n showNotification: (params: NotificationData) => string;\n /** Dismiss a notification by ID */\n dismissNotification: (id: string) => void;\n /** Clear all notifications */\n clearAllNotifications: () => void;\n\n // -------------------------------------------------------------------------\n // WALLET API\n // -------------------------------------------------------------------------\n /** All queued wallet requests (tx + eip712 signing) */\n pendingWalletRequests: WalletRequest[];\n /** Mark a wallet request as being processed */\n startWalletRequest: (id: string) => void;\n /** Complete a wallet request — dequeues + sends response to backend */\n resolveWalletRequest: (id: string, result: WalletRequestResult) => void;\n /** Fail a wallet request — dequeues + sends error to backend */\n rejectWalletRequest: (id: string, error?: string) => void;\n\n // -------------------------------------------------------------------------\n // EVENT API\n // -------------------------------------------------------------------------\n /** Subscribe to inbound events by type. Returns unsubscribe function. */\n subscribe: (type: string, callback: EventSubscriber) => () => void;\n /** Send a system command to the backend */\n sendSystemCommand: (event: Omit<OutboundEvent, \"timestamp\">) => Promise<void>;\n /** Current SSE connection status */\n sseStatus: SSEStatus;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst AomiRuntimeContext = createContext<AomiRuntimeApi | null>(null);\n\nexport const AomiRuntimeApiProvider = AomiRuntimeContext.Provider;\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Unified hook that provides access to all Aomi runtime APIs.\n *\n * This is the primary way to interact with the Aomi runtime from consumer code.\n * It combines user, thread, chat, notification, and event APIs into a single interface.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const aomi = useAomiRuntime();\n *\n * // User API\n * const { user, setUser } = aomi;\n *\n * // Thread API\n * const { currentThreadId, createThread, selectThread } = aomi;\n *\n * // Chat API\n * const { isRunning, sendMessage, cancelGeneration } = aomi;\n *\n * // Notification API\n * const { showNotification } = aomi;\n *\n * // Event API\n * const { subscribe, sendSystemCommand } = aomi;\n * }\n * ```\n */\nexport function useAomiRuntime(): AomiRuntimeApi {\n const context = useContext(AomiRuntimeContext);\n if (!context) {\n throw new Error(\n \"useAomiRuntime must be used within AomiRuntimeProvider. \" +\n \"Wrap your app with <AomiRuntimeProvider>...</AomiRuntimeProvider>\",\n );\n }\n return context;\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n normalizeEip712Payload,\n normalizeTxPayload,\n type WalletEip712Payload,\n type WalletTxPayload,\n} from \"@aomi-labs/client\";\nimport { useEventContext } from \"../contexts/event-context\";\nimport type { InboundEvent } from \"../state/event-buffer\";\nimport {\n createWalletBuffer,\n enqueue,\n dequeue,\n markProcessing,\n getAll,\n type WalletBuffer,\n type WalletRequest,\n} from \"../state/wallet-buffer\";\n\n// Re-export types consumers need\nexport type { WalletRequest, WalletTxPayload, WalletEip712Payload };\nexport type {\n WalletRequestKind,\n WalletRequestStatus,\n} from \"../state/wallet-buffer\";\n\nexport type WalletRequestResult = {\n txHash?: string;\n signature?: string;\n amount?: string;\n};\n\nexport type WalletHandlerConfig = {\n sessionId: string;\n /** Called after a wallet request is resolved/rejected and the outbound event is sent.\n * Used by core.tsx to start polling for the AI's response. */\n onRequestComplete?: () => void;\n};\n\nexport type WalletHandlerApi = {\n /** All queued wallet requests (tx + eip712) */\n pendingRequests: WalletRequest[];\n /** Mark a request as being processed */\n startProcessing: (id: string) => void;\n /** Complete a request successfully — dequeues + sends response to backend */\n resolveRequest: (\n id: string,\n result: WalletRequestResult,\n ) => void;\n /** Fail a request — dequeues + sends error to backend */\n rejectRequest: (id: string, error?: string) => void;\n};\n\nexport function useWalletHandler({\n sessionId,\n onRequestComplete,\n}: WalletHandlerConfig): WalletHandlerApi {\n const { subscribe, sendOutboundSystem: sendOutbound } = useEventContext();\n const bufferRef = useRef<WalletBuffer>(createWalletBuffer());\n const [pendingRequests, setPendingRequests] = useState<WalletRequest[]>([]);\n\n // Sync React state from buffer\n const syncState = useCallback(() => {\n setPendingRequests(getAll(bufferRef.current));\n }, []);\n\n // ---------------------------------------------------------------------------\n // Subscribe to wallet_tx_request events\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = subscribe(\n \"wallet_tx_request\",\n (event: InboundEvent) => {\n const payload = normalizeTxPayload(event.payload);\n if (!payload) {\n console.warn(\"[aomi][wallet] Ignoring tx request with invalid payload\", event.payload);\n return;\n }\n enqueue(bufferRef.current, \"transaction\", payload);\n syncState();\n },\n );\n return unsubscribe;\n }, [subscribe, syncState]);\n\n // ---------------------------------------------------------------------------\n // Subscribe to EIP-712 signing requests\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = subscribe(\n \"wallet_eip712_request\",\n (event: InboundEvent) => {\n const payload = normalizeEip712Payload(event.payload ?? {});\n enqueue(bufferRef.current, \"eip712_sign\", payload);\n syncState();\n },\n );\n return unsubscribe;\n }, [subscribe, syncState]);\n\n // ---------------------------------------------------------------------------\n // Mark a request as processing\n // ---------------------------------------------------------------------------\n const startProcessingCb = useCallback(\n (id: string) => {\n markProcessing(bufferRef.current, id);\n syncState();\n },\n [syncState],\n );\n\n // ---------------------------------------------------------------------------\n // Resolve a request — dequeues + sends appropriate backend response\n // ---------------------------------------------------------------------------\n const resolveRequest = useCallback(\n (id: string, result: WalletRequestResult) => {\n const removed = dequeue(bufferRef.current, id);\n if (!removed) return;\n\n let outbound: Promise<void>;\n if (removed.kind === \"transaction\") {\n outbound = sendOutbound({\n type: \"wallet:tx_complete\",\n sessionId,\n payload: {\n txHash: result.txHash ?? \"\",\n status: \"success\",\n amount: result.amount,\n },\n });\n } else {\n const eip712Payload = removed.payload as WalletEip712Payload;\n outbound = sendOutbound({\n type: \"wallet_eip712_response\",\n sessionId,\n payload: {\n status: \"success\",\n signature: result.signature,\n description: eip712Payload.description,\n },\n });\n }\n\n outbound.then(() => onRequestComplete?.());\n syncState();\n },\n [sendOutbound, sessionId, syncState, onRequestComplete],\n );\n\n // ---------------------------------------------------------------------------\n // Reject a request — dequeues + sends error to backend\n // ---------------------------------------------------------------------------\n const rejectRequest = useCallback(\n (id: string, error?: string) => {\n const removed = dequeue(bufferRef.current, id);\n if (!removed) return;\n\n let outbound: Promise<void>;\n if (removed.kind === \"transaction\") {\n outbound = sendOutbound({\n type: \"wallet:tx_complete\",\n sessionId,\n payload: {\n txHash: \"\",\n status: \"failed\",\n },\n });\n } else {\n const eip712Payload = removed.payload as WalletEip712Payload;\n outbound = sendOutbound({\n type: \"wallet_eip712_response\",\n sessionId,\n payload: {\n status: \"failed\",\n error: error ?? \"EIP-712 signing failed\",\n description: eip712Payload.description,\n },\n });\n }\n\n outbound.then(() => onRequestComplete?.());\n syncState();\n },\n [sendOutbound, sessionId, syncState, onRequestComplete],\n );\n\n return {\n pendingRequests,\n startProcessing: startProcessingCb,\n resolveRequest,\n rejectRequest,\n };\n}\n","// =============================================================================\n// Wallet Request Types\n// =============================================================================\n\nimport type {\n WalletEip712Payload,\n WalletTxPayload,\n} from \"@aomi-labs/client\";\n\nexport type { WalletEip712Payload, WalletTxPayload };\n\nexport type WalletRequestKind = \"transaction\" | \"eip712_sign\";\n\nexport type WalletRequestStatus = \"pending\" | \"processing\";\n\nexport type WalletRequest = {\n id: string;\n kind: WalletRequestKind;\n payload: WalletTxPayload | WalletEip712Payload;\n status: WalletRequestStatus;\n timestamp: number;\n};\n\n// =============================================================================\n// Buffer State\n// =============================================================================\n\nexport type WalletBuffer = {\n queue: WalletRequest[];\n nextId: number;\n};\n\nexport function createWalletBuffer(): WalletBuffer {\n return { queue: [], nextId: 1 };\n}\n\n// =============================================================================\n// Queue Operations\n// =============================================================================\n\nexport function enqueue(\n buffer: WalletBuffer,\n kind: WalletRequestKind,\n payload: WalletTxPayload | WalletEip712Payload,\n): WalletRequest {\n const request: WalletRequest = {\n id: `wreq-${buffer.nextId++}`,\n kind,\n payload,\n status: \"pending\",\n timestamp: Date.now(),\n };\n buffer.queue.push(request);\n return request;\n}\n\nexport function dequeue(\n buffer: WalletBuffer,\n id: string,\n): WalletRequest | null {\n const index = buffer.queue.findIndex((r) => r.id === id);\n if (index === -1) return null;\n return buffer.queue.splice(index, 1)[0];\n}\n\nexport function peek(buffer: WalletBuffer): WalletRequest | null {\n return buffer.queue.find((r) => r.status === \"pending\") ?? null;\n}\n\nexport function markProcessing(buffer: WalletBuffer, id: string): boolean {\n const request = buffer.queue.find((r) => r.id === id);\n if (!request || request.status !== \"pending\") return false;\n request.status = \"processing\";\n return true;\n}\n\nexport function getAll(buffer: WalletBuffer): WalletRequest[] {\n return [...buffer.queue];\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useEventContext } from \"../contexts/event-context\";\nimport type { InboundEvent } from \"../state/event-buffer\";\n\nexport type Notification = {\n id: string;\n type: string;\n title: string;\n body?: unknown; // Could be JSON object or string\n handled: boolean;\n timestamp: number;\n sessionId: string;\n};\n\nexport type NotificationHandlerConfig = {\n /** Callback when new notification arrives */\n onNotification?: (notification: Notification) => void;\n};\n\nexport type NotificationApi = {\n /** All notifications */\n notifications: Notification[];\n /** Unhandled count */\n unhandledCount: number;\n /** Mark notification as handled */\n markDone: (id: string) => void;\n};\n\nlet notificationIdCounter = 0;\nfunction generateNotificationId(): string {\n return `notif-${Date.now()}-${++notificationIdCounter}`;\n}\n\nexport function useNotificationHandler({\n onNotification,\n}: NotificationHandlerConfig = {}): NotificationApi {\n const { subscribe } = useEventContext();\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n // ---------------------------------------------------------------------------\n // Subscribe to notification events\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = subscribe(\"notification\", (event: InboundEvent) => {\n const payload = event.payload as Record<string, unknown>;\n\n const notification: Notification = {\n id: generateNotificationId(),\n type: (payload.type as string) ?? \"notification\",\n title: (payload.title as string) ?? \"Notification\",\n body: payload.body,\n handled: false,\n timestamp: event.timestamp,\n sessionId: event.sessionId,\n };\n\n setNotifications((prev) => [notification, ...prev]);\n onNotification?.(notification);\n });\n\n return unsubscribe;\n }, [subscribe, onNotification]);\n\n // ---------------------------------------------------------------------------\n // Computed: unhandled count\n // ---------------------------------------------------------------------------\n const unhandledCount = notifications.filter((n) => !n.handled).length;\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n const markHandled = useCallback((id: string) => {\n setNotifications((prev) =>\n prev.map((n) => (n.id === id ? { ...n, handled: true } : n)),\n );\n }, []);\n\n return {\n notifications,\n unhandledCount,\n markDone: markHandled,\n };\n}\n"],"mappings":"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","names":["import_client","import_react","import_client","_a","_b","isProcessing","import_react","import_jsx_runtime","sessionId","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","_a","_b","import_react","import_react","import_client","subscribe","import_jsx_runtime","import_jsx_runtime","import_react","notificationIdCounter","subscribe"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/runtime/aomi-runtime.tsx","../src/contexts/control-context.tsx","../src/utils/uuid.ts","../src/state/thread-store.ts","../src/contexts/event-context.tsx","../src/contexts/notification-context.tsx","../src/contexts/thread-context.tsx","../src/contexts/user-context.tsx","../src/runtime/core.tsx","../src/runtime/orchestrator.ts","../src/runtime/session-manager.ts","../src/runtime/utils.ts","../src/runtime/threadlist-adapter.ts","../src/interface.tsx","../src/handlers/wallet-handler.ts","../src/handlers/notification-handler.ts"],"sourcesContent":["// =============================================================================\n// API Client (re-exported from @aomi-labs/client)\n// =============================================================================\nexport { AomiClient } from \"@aomi-labs/client\";\nexport type { AomiClientOptions } from \"@aomi-labs/client\";\nexport type {\n AomiMessage,\n AomiChatResponse,\n AomiCreateThreadResponse,\n AomiInterruptResponse,\n AomiSSEEvent,\n AomiStateResponse,\n AomiSystemEvent,\n AomiSystemResponse,\n AomiThread,\n} from \"@aomi-labs/client\";\nexport { toViemSignTypedDataArgs } from \"@aomi-labs/client\";\n\n// =============================================================================\n// Runtime Provider\n// =============================================================================\nexport { AomiRuntimeProvider } from \"./runtime/aomi-runtime\";\nexport type { AomiRuntimeProviderProps } from \"./runtime/aomi-runtime\";\n\n// =============================================================================\n// Unified Runtime API\n// =============================================================================\nexport { useAomiRuntime } from \"./interface\";\nexport type { AomiRuntimeApi } from \"./interface\";\n\n// =============================================================================\n// Event System (follows RUNTIME-ARCH.md)\n// =============================================================================\nexport {\n useEventContext,\n EventContextProvider,\n} from \"./contexts/event-context\";\nexport type {\n EventContext,\n EventContextProviderProps,\n} from \"./contexts/event-context\";\n\nexport type {\n InboundEvent,\n SSEStatus,\n EventSubscriber,\n} from \"./contexts/event-context\";\n\n// =============================================================================\n// Handler Hooks\n// =============================================================================\nexport { useWalletHandler } from \"./handlers/wallet-handler\";\nexport { useNotificationHandler } from \"./handlers/notification-handler\";\nexport type {\n WalletRequest,\n WalletTxPayload,\n WalletEip712Payload,\n WalletRequestKind,\n WalletRequestStatus,\n WalletRequestResult,\n WalletHandlerConfig,\n WalletHandlerApi,\n} from \"./handlers/wallet-handler\";\nexport type {\n NotificationHandlerConfig,\n NotificationApi,\n} from \"./handlers/notification-handler\";\n\n// =============================================================================\n// User Context (wallet/user state)\n// =============================================================================\nexport {\n useUser,\n UserContextProvider,\n type UserState,\n} from \"./contexts/user-context\";\n\n// User config type (for render prop pattern)\nexport type { UserConfig } from \"./runtime/utils\";\n\n// =============================================================================\n// Thread Context (for UI components)\n// =============================================================================\nexport {\n useThreadContext,\n useCurrentThreadMessages,\n useCurrentThreadMetadata,\n ThreadContextProvider,\n} from \"./contexts/thread-context\";\nexport type { ThreadContext } from \"./contexts/thread-context\";\nexport type { ThreadMetadata, ThreadControlState } from \"./state/thread-store\";\nexport { initThreadControl } from \"./state/thread-store\";\n\n// =============================================================================\n// Utilities\n// =============================================================================\nexport {\n cn,\n formatAddress,\n getNetworkName,\n getChainInfo,\n SUPPORTED_CHAINS,\n type ChainInfo,\n} from \"./runtime/utils\";\n\n// =============================================================================\n// Notification Context (for toast UI)\n// =============================================================================\nexport {\n useNotification,\n NotificationContextProvider,\n type Notification,\n type NotificationType,\n type NotificationData as ShowNotificationParams,\n type NotificationContextApi as NotificationContextValue,\n type NotificationContextProviderProps,\n} from \"./contexts/notification-context\";\n\n// =============================================================================\n// Control Context (model/app/api-key state)\n// =============================================================================\nexport {\n useControl,\n ControlContextProvider,\n type ControlState,\n type ControlContextApi,\n type ControlContextProviderProps,\n type StoredProviderKey,\n} from \"./contexts/control-context\";\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { AomiClient } from \"@aomi-labs/client\";\nimport { ControlContextProvider } from \"../contexts/control-context\";\nimport { EventContextProvider } from \"../contexts/event-context\";\nimport { NotificationContextProvider } from \"../contexts/notification-context\";\nimport {\n ThreadContextProvider,\n useThreadContext,\n} from \"../contexts/thread-context\";\nimport { UserContextProvider, useUser } from \"../contexts/user-context\";\nimport { AomiRuntimeCore } from \"./core\";\n\n// =============================================================================\n// Props\n// =============================================================================\n\nexport type AomiRuntimeProviderProps = {\n children: ReactNode;\n backendUrl?: string;\n};\n\n// =============================================================================\n// Provider Shell\n// =============================================================================\n\nexport function AomiRuntimeProvider({\n children,\n backendUrl = \"http://localhost:8080\",\n}: Readonly<AomiRuntimeProviderProps>) {\n const aomiClient = useMemo(() => new AomiClient({ baseUrl: backendUrl }), [backendUrl]);\n\n return (\n <ThreadContextProvider>\n <NotificationContextProvider>\n <UserContextProvider>\n <AomiRuntimeInner aomiClient={aomiClient}>\n {children}\n </AomiRuntimeInner>\n </UserContextProvider>\n </NotificationContextProvider>\n </ThreadContextProvider>\n );\n}\n\n// =============================================================================\n// Inner Provider (needs ThreadContext and UserContext)\n// =============================================================================\n\ntype AomiRuntimeInnerProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n};\n\nfunction AomiRuntimeInner({\n children,\n aomiClient,\n}: Readonly<AomiRuntimeInnerProps>) {\n const threadContext = useThreadContext();\n const { user } = useUser();\n\n return (\n <ControlContextProvider\n aomiClient={aomiClient}\n sessionId={threadContext.currentThreadId}\n publicKey={user.address ?? undefined}\n getThreadMetadata={threadContext.getThreadMetadata}\n updateThreadMetadata={threadContext.updateThreadMetadata}\n >\n <EventContextProvider\n aomiClient={aomiClient}\n sessionId={threadContext.currentThreadId}\n >\n <AomiRuntimeCore aomiClient={aomiClient}>{children}</AomiRuntimeCore>\n </EventContextProvider>\n </ControlContextProvider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n useEffect,\n type ReactNode,\n} from \"react\";\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport type { ThreadMetadata, ThreadControlState } from \"../state/thread-store\";\nimport { initThreadControl } from \"../state/thread-store\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** A stored provider API key (BYOK) */\nexport type StoredProviderKey = {\n apiKey: string;\n keyPrefix: string;\n label?: string;\n};\n\n/** Global control state (shared across all threads) */\nexport type ControlState = {\n /** API key for authenticated requests */\n apiKey: string | null;\n /** Stable client identifier for this browser profile (associates sessions with secrets) */\n clientId: string | null;\n /** Available models fetched from backend */\n availableModels: string[];\n /** Authorized apps fetched from backend */\n authorizedApps: string[];\n /** Default model (first from availableModels) */\n defaultModel: string | null;\n /** Default app (from authorizedApps) */\n defaultApp: string | null;\n /** Provider API keys stored locally (BYOK) — keyed by provider name */\n providerKeys: Record<string, StoredProviderKey>;\n};\n\nexport type ControlContextApi = {\n /** Global state (apiKey, clientId, available models/apps) */\n state: ControlState;\n /** Update global state (apiKey only) */\n setApiKey: (apiKey: string | null) => void;\n /** Ingest secrets into the backend vault, returns opaque handles */\n ingestSecrets: (secrets: Record<string, string>) => Promise<Record<string, string>>;\n /** Clear all secrets from the backend vault */\n clearSecrets: () => Promise<void>;\n /** Store a provider API key (BYOK) in localStorage and ingest into backend vault */\n setProviderKey: (provider: string, apiKey: string, label?: string) => Promise<void>;\n /** Remove a provider API key from localStorage and backend vault */\n removeProviderKey: (provider: string) => Promise<void>;\n /** Get all stored provider keys (metadata only — keys are in state.providerKeys) */\n getProviderKeys: () => Record<string, StoredProviderKey>;\n /** Check if a provider key is stored */\n hasProviderKey: (provider?: string) => boolean;\n /** Fetch available models from backend */\n getAvailableModels: () => Promise<string[]>;\n /** Fetch authorized apps from backend */\n getAuthorizedApps: () => Promise<string[]>;\n /** Get current thread's control state */\n getCurrentThreadControl: () => ThreadControlState;\n /** Get the current thread's effective app after auth fallback */\n getCurrentThreadApp: () => string;\n /** Select a model for the current thread (updates metadata + calls backend) */\n onModelSelect: (model: string) => Promise<void>;\n /** Select an app for the current thread (updates metadata only) */\n onAppSelect: (app: string) => void;\n /** Whether the current thread is processing (disables control switching) */\n isProcessing: boolean;\n /** Mark control state as synced (called after chat starts) */\n markControlSynced: () => void;\n /** Get global control state */\n getControlState: () => ControlState;\n /** Subscribe to global state changes */\n onControlStateChange: (callback: (state: ControlState) => void) => () => void;\n\n // Legacy compatibility\n /** @deprecated Use getCurrentThreadControl().app instead */\n setState: (\n updates: Partial<{ app: string | null; apiKey: string | null }>,\n ) => void;\n};\n\n// =============================================================================\n// Constants\n// =============================================================================\n\nconst API_KEY_STORAGE_KEY = \"aomi_api_key\";\nconst CLIENT_ID_STORAGE_KEY = \"aomi_client_id\";\nconst PROVIDER_KEYS_STORAGE_KEY = \"aomi_provider_keys\";\nconst PROVIDER_KEY_SECRET_PREFIX = \"PROVIDER_KEY:\";\n\nfunction getOrCreateClientId(): string {\n try {\n const storedClientId = globalThis.localStorage?.getItem(CLIENT_ID_STORAGE_KEY);\n if (storedClientId && storedClientId.trim().length > 0) {\n return storedClientId;\n }\n } catch {\n // localStorage not available\n }\n\n const clientId = globalThis.crypto?.randomUUID?.() ?? `client-${Date.now()}`;\n try {\n globalThis.localStorage?.setItem(CLIENT_ID_STORAGE_KEY, clientId);\n } catch {\n // localStorage not available\n }\n return clientId;\n}\n\nfunction getDefaultApp(apps: string[]): string | null {\n return apps.includes(\"default\") ? \"default\" : (apps[0] ?? null);\n}\n\nfunction resolveAuthorizedApp(\n app: string | null | undefined,\n authorizedApps: string[],\n defaultApp: string | null,\n): string | null {\n if (app && authorizedApps.includes(app)) {\n return app;\n }\n return defaultApp;\n}\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst ControlContext = createContext<ControlContextApi | null>(null);\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useControl(): ControlContextApi {\n const ctx = useContext(ControlContext);\n if (!ctx) {\n throw new Error(\"useControl must be used within ControlContextProvider\");\n }\n return ctx;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport type ControlContextProviderProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n sessionId: string;\n publicKey?: string;\n /** Get metadata for a thread */\n getThreadMetadata: (threadId: string) => ThreadMetadata | undefined;\n /** Update metadata for a thread */\n updateThreadMetadata: (\n threadId: string,\n updates: Partial<ThreadMetadata>,\n ) => void;\n};\n\nexport function ControlContextProvider({\n children,\n aomiClient,\n sessionId,\n publicKey,\n getThreadMetadata,\n updateThreadMetadata,\n}: ControlContextProviderProps) {\n const [state, setStateInternal] = useState<ControlState>(() => ({\n apiKey: null,\n clientId: getOrCreateClientId(),\n availableModels: [],\n authorizedApps: [],\n defaultModel: null,\n defaultApp: null,\n providerKeys: {},\n }));\n\n const stateRef = useRef(state);\n stateRef.current = state;\n\n const aomiClientRef = useRef(aomiClient);\n aomiClientRef.current = aomiClient;\n\n const sessionIdRef = useRef(sessionId);\n sessionIdRef.current = sessionId;\n\n const publicKeyRef = useRef(publicKey);\n publicKeyRef.current = publicKey;\n\n const getThreadMetadataRef = useRef(getThreadMetadata);\n getThreadMetadataRef.current = getThreadMetadata;\n\n const updateThreadMetadataRef = useRef(updateThreadMetadata);\n updateThreadMetadataRef.current = updateThreadMetadata;\n\n const callbacks = useRef<Set<(state: ControlState) => void>>(new Set());\n\n // Compute isProcessing from current thread's control state\n const currentThreadMetadata = getThreadMetadata(sessionId);\n const isProcessing = currentThreadMetadata?.control?.isProcessing ?? false;\n\n // Persist client id to localStorage so the settings page and chat runtime\n // share the same backend vault namespace.\n useEffect(() => {\n try {\n if (state.clientId) {\n globalThis.localStorage?.setItem(CLIENT_ID_STORAGE_KEY, state.clientId);\n }\n } catch {\n // localStorage not available\n }\n }, [state.clientId]);\n\n // Load API key from localStorage on mount\n useEffect(() => {\n try {\n const storedApiKey =\n globalThis.localStorage?.getItem(API_KEY_STORAGE_KEY) ?? null;\n if (storedApiKey) {\n setStateInternal((prev) => ({ ...prev, apiKey: storedApiKey }));\n }\n } catch {\n // localStorage not available\n }\n }, []);\n\n // Load provider keys from localStorage on mount\n useEffect(() => {\n try {\n const raw = globalThis.localStorage?.getItem(PROVIDER_KEYS_STORAGE_KEY);\n if (raw) {\n const parsed = JSON.parse(raw) as Record<string, StoredProviderKey>;\n setStateInternal((prev) => ({ ...prev, providerKeys: parsed }));\n }\n } catch {\n // localStorage not available or invalid JSON\n }\n }, []);\n\n // Persist API key to localStorage\n useEffect(() => {\n try {\n if (state.apiKey) {\n globalThis.localStorage?.setItem(API_KEY_STORAGE_KEY, state.apiKey);\n } else {\n globalThis.localStorage?.removeItem(API_KEY_STORAGE_KEY);\n }\n } catch {\n // localStorage not available\n }\n }, [state.apiKey]);\n\n // Persist provider keys to localStorage\n useEffect(() => {\n try {\n const keys = state.providerKeys;\n if (Object.keys(keys).length > 0) {\n globalThis.localStorage?.setItem(\n PROVIDER_KEYS_STORAGE_KEY,\n JSON.stringify(keys),\n );\n } else {\n globalThis.localStorage?.removeItem(PROVIDER_KEYS_STORAGE_KEY);\n }\n } catch {\n // localStorage not available\n }\n }, [state.providerKeys]);\n\n // Auto-ingest provider keys into backend vault when the client id or stored key set changes.\n useEffect(() => {\n if (!state.clientId) return;\n const keys = stateRef.current.providerKeys;\n if (Object.keys(keys).length === 0) return;\n\n const secrets: Record<string, string> = {};\n for (const [provider, entry] of Object.entries(keys)) {\n secrets[`${PROVIDER_KEY_SECRET_PREFIX}${provider}`] = entry.apiKey;\n }\n\n void aomiClientRef.current.ingestSecrets(state.clientId, secrets).catch((err: unknown) => {\n console.error(\"Failed to auto-ingest provider keys:\", err);\n });\n }, [state.clientId, state.providerKeys]);\n\n // Fetch apps whenever the auth context changes\n useEffect(() => {\n const fetchApps = async () => {\n try {\n const apps = await aomiClientRef.current.getApps(\n sessionIdRef.current,\n {\n publicKey: publicKeyRef.current,\n apiKey: stateRef.current.apiKey ?? undefined,\n },\n );\n const defaultApp = getDefaultApp(apps);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: apps,\n defaultApp,\n }));\n } catch (error) {\n console.error(\"Failed to fetch apps:\", error);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: [\"default\"],\n defaultApp: \"default\",\n }));\n }\n };\n void fetchApps();\n }, [state.apiKey, publicKey, sessionId]);\n\n // Fetch models on mount\n useEffect(() => {\n const fetchModels = async () => {\n try {\n const models = await aomiClientRef.current.getModels(\n sessionIdRef.current,\n );\n setStateInternal((prev) => ({\n ...prev,\n availableModels: models,\n defaultModel: models[0] ?? null,\n }));\n } catch (error) {\n console.error(\"Failed to fetch models:\", error);\n }\n };\n void fetchModels();\n }, []);\n\n // ---------------------------------------------------------------------------\n // API Key\n // ---------------------------------------------------------------------------\n const setApiKey = useCallback((apiKey: string | null) => {\n setStateInternal((prev) => {\n const next = { ...prev, apiKey: apiKey === \"\" ? null : apiKey };\n callbacks.current.forEach((cb) => cb(next));\n return next;\n });\n }, []);\n\n // ---------------------------------------------------------------------------\n // Secrets\n // ---------------------------------------------------------------------------\n const ingestSecrets = useCallback(\n async (secrets: Record<string, string>): Promise<Record<string, string>> => {\n const clientId = stateRef.current.clientId;\n if (!clientId) throw new Error(\"clientId not initialized\");\n const { handles } = await aomiClientRef.current.ingestSecrets(\n clientId,\n secrets,\n );\n return handles;\n },\n [],\n );\n\n const clearSecrets = useCallback(async (): Promise<void> => {\n const clientId = stateRef.current.clientId;\n if (!clientId) return;\n await aomiClientRef.current.clearSecrets?.(clientId);\n }, []);\n\n // ---------------------------------------------------------------------------\n // Provider Keys (BYOK)\n // ---------------------------------------------------------------------------\n const setProviderKey = useCallback(\n async (provider: string, apiKey: string, label?: string): Promise<void> => {\n const trimmed = apiKey.trim();\n if (!trimmed) return;\n\n const entry: StoredProviderKey = {\n apiKey: trimmed,\n keyPrefix: trimmed.slice(0, 7),\n label,\n };\n\n setStateInternal((prev) => {\n const next = {\n ...prev,\n providerKeys: { ...prev.providerKeys, [provider]: entry },\n };\n callbacks.current.forEach((cb) => cb(next));\n return next;\n });\n\n // Ingest into backend vault\n const clientId = stateRef.current.clientId;\n if (clientId) {\n try {\n await aomiClientRef.current.ingestSecrets(clientId, {\n [`${PROVIDER_KEY_SECRET_PREFIX}${provider}`]: trimmed,\n });\n } catch (err) {\n console.error(\"Failed to ingest provider key:\", err);\n }\n }\n },\n [],\n );\n\n const removeProviderKey = useCallback(\n async (provider: string): Promise<void> => {\n const clientId = stateRef.current.clientId;\n if (clientId) {\n await aomiClientRef.current.deleteSecret(\n clientId,\n `${PROVIDER_KEY_SECRET_PREFIX}${provider}`,\n );\n }\n\n setStateInternal((prev) => {\n const { [provider]: _, ...rest } = prev.providerKeys;\n const next = { ...prev, providerKeys: rest };\n callbacks.current.forEach((cb) => cb(next));\n return next;\n });\n },\n [],\n );\n\n const getProviderKeys = useCallback(\n (): Record<string, StoredProviderKey> => stateRef.current.providerKeys,\n [],\n );\n\n const hasProviderKey = useCallback(\n (provider?: string): boolean => {\n const keys = stateRef.current.providerKeys;\n if (provider) return provider in keys;\n return Object.keys(keys).length > 0;\n },\n [],\n );\n\n // ---------------------------------------------------------------------------\n // Fetch available options\n // ---------------------------------------------------------------------------\n const getAvailableModels = useCallback(async (): Promise<string[]> => {\n try {\n const models = await aomiClientRef.current.getModels(\n sessionIdRef.current,\n );\n setStateInternal((prev) => ({\n ...prev,\n availableModels: models,\n defaultModel: prev.defaultModel ?? models[0] ?? null,\n }));\n return models;\n } catch (error) {\n console.error(\"Failed to fetch models:\", error);\n return [];\n }\n }, []);\n\n const getAuthorizedApps = useCallback(async (): Promise<string[]> => {\n try {\n const apps = await aomiClientRef.current.getApps(\n sessionIdRef.current,\n {\n publicKey: publicKeyRef.current,\n apiKey: stateRef.current.apiKey ?? undefined,\n },\n );\n const defaultApp = getDefaultApp(apps);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: apps,\n defaultApp,\n }));\n return apps;\n } catch (error) {\n console.error(\"Failed to fetch apps:\", error);\n setStateInternal((prev) => ({\n ...prev,\n authorizedApps: [\"default\"],\n defaultApp: \"default\",\n }));\n return [\"default\"];\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Per-thread control state\n // ---------------------------------------------------------------------------\n const getCurrentThreadControl = useCallback((): ThreadControlState => {\n const metadata = getThreadMetadataRef.current(sessionIdRef.current);\n return metadata?.control ?? initThreadControl();\n }, []);\n\n const getCurrentThreadApp = useCallback((): string => {\n const currentControl =\n getThreadMetadataRef.current(sessionIdRef.current)?.control ??\n initThreadControl();\n return (\n resolveAuthorizedApp(\n currentControl.app,\n stateRef.current.authorizedApps,\n stateRef.current.defaultApp,\n ) ?? \"default\"\n );\n }, []);\n\n const onModelSelect = useCallback(async (model: string) => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n const isProcessing = currentControl.isProcessing;\n\n console.log(\"[control-context] onModelSelect called\", {\n model,\n isProcessing,\n threadId,\n });\n\n if (isProcessing) {\n console.warn(\"[control-context] Cannot switch model while processing\");\n return;\n }\n\n const app =\n resolveAuthorizedApp(\n currentControl.app,\n stateRef.current.authorizedApps,\n stateRef.current.defaultApp,\n ) ?? \"default\";\n\n console.log(\"[control-context] onModelSelect updating metadata\", {\n threadId,\n model,\n app,\n currentControl,\n });\n\n // Update thread metadata with new model and mark as dirty\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...currentControl,\n model,\n app,\n controlDirty: true,\n },\n });\n\n console.log(\"[control-context] onModelSelect calling backend setModel\", {\n threadId,\n model,\n app,\n backendUrl: aomiClientRef.current,\n });\n\n try {\n const result = await aomiClientRef.current.setModel(\n threadId,\n model,\n {\n app,\n apiKey: stateRef.current.apiKey ?? undefined,\n clientId: stateRef.current.clientId ?? undefined,\n },\n );\n console.log(\"[control-context] onModelSelect backend result\", result);\n } catch (err) {\n console.error(\"[control-context] setModel failed:\", err);\n throw err;\n }\n }, []);\n\n const onAppSelect = useCallback((app: string) => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n const isProcessing = currentControl.isProcessing;\n\n console.log(\"[control-context] onAppSelect called\", {\n app,\n isProcessing,\n threadId,\n });\n\n if (isProcessing) {\n console.warn(\n \"[control-context] Cannot switch app while processing\",\n );\n return;\n }\n\n if (\n stateRef.current.authorizedApps.length > 0 &&\n !stateRef.current.authorizedApps.includes(app)\n ) {\n console.warn(\"[control-context] Cannot select unauthorized app\", { app });\n return;\n }\n\n console.log(\"[control-context] onAppSelect updating metadata\", {\n threadId,\n app,\n currentControl,\n });\n\n // Update thread metadata with new app and mark as dirty\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...currentControl,\n app,\n controlDirty: true,\n },\n });\n\n console.log(\"[control-context] onAppSelect metadata updated\");\n }, []);\n\n const markControlSynced = useCallback(() => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n\n if (currentControl.controlDirty) {\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...currentControl,\n controlDirty: false,\n },\n });\n }\n }, []);\n\n // ---------------------------------------------------------------------------\n // Global state access\n // ---------------------------------------------------------------------------\n const getControlState = useCallback(() => stateRef.current, []);\n\n const onControlStateChange = useCallback(\n (callback: (state: ControlState) => void) => {\n callbacks.current.add(callback);\n return () => {\n callbacks.current.delete(callback);\n };\n },\n [],\n );\n\n // ---------------------------------------------------------------------------\n // Legacy compatibility\n // ---------------------------------------------------------------------------\n const setState = useCallback(\n (updates: Partial<{ app: string | null; apiKey: string | null }>) => {\n if (\"apiKey\" in updates) {\n setApiKey(updates.apiKey ?? null);\n }\n if (\n \"app\" in updates &&\n updates.app !== undefined &&\n updates.app !== null\n ) {\n onAppSelect(updates.app);\n }\n },\n [setApiKey, onAppSelect],\n );\n\n return (\n <ControlContext.Provider\n value={{\n state,\n setApiKey,\n ingestSecrets,\n clearSecrets,\n setProviderKey,\n removeProviderKey,\n getProviderKeys,\n hasProviderKey,\n getAvailableModels,\n getAuthorizedApps,\n getCurrentThreadControl,\n getCurrentThreadApp,\n onModelSelect,\n onAppSelect,\n isProcessing,\n markControlSynced,\n getControlState,\n onControlStateChange,\n setState,\n }}\n >\n {children}\n </ControlContext.Provider>\n );\n}\n","// UUID polyfill for Safari and older browsers\nexport function generateUUID(): string {\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n\n // Fallback for browsers without crypto.randomUUID\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","import { generateUUID } from \"../utils/uuid\";\nimport type { SetStateAction } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\nimport { ThreadContext } from \"../contexts/thread-context\";\n\nconst shouldLogThreadUpdates = process.env.NODE_ENV !== \"production\";\n\nconst logThreadMetadataChange = (\n source: string,\n threadId: string,\n prev: ThreadMetadata | undefined,\n next: ThreadMetadata | undefined,\n) => {\n if (!shouldLogThreadUpdates) return;\n if (!prev && !next) return;\n if (!prev || !next) {\n console.debug(`[aomi][thread:${source}]`, { threadId, prev, next });\n return;\n }\n if (\n prev.title !== next.title ||\n prev.status !== next.status ||\n prev.lastActiveAt !== next.lastActiveAt\n ) {\n console.debug(`[aomi][thread:${source}]`, { threadId, prev, next });\n }\n};\n\nexport type ThreadStatus = \"regular\" | \"archived\";\n\nexport type ThreadControlState = {\n /** Selected model for this thread (human-readable label) */\n model: string | null;\n /** Selected app for this thread */\n app: string | null;\n /** Whether control state has changed but chat hasn't started yet */\n controlDirty: boolean;\n /** Whether this thread is currently processing (assistant generating) */\n isProcessing: boolean;\n};\n\nexport type ThreadMetadata = {\n title: string;\n status: ThreadStatus;\n lastActiveAt?: string | number;\n /** Per-thread control state (model, app selection) */\n control: ThreadControlState;\n};\n\n/** Create default control state for a new thread */\nexport function initThreadControl(): ThreadControlState {\n return {\n model: null,\n app: null,\n controlDirty: false,\n isProcessing: false,\n };\n}\n\ntype ThreadStoreState = {\n currentThreadId: string;\n threadViewKey: number;\n threadCnt: number;\n threads: Map<string, ThreadMessageLike[]>;\n threadMetadata: Map<string, ThreadMetadata>;\n};\n\ntype ThreadStoreOptions = {\n initialThreadId?: string;\n};\n\nexport class ThreadStore {\n private state: ThreadStoreState;\n private listeners = new Set<() => void>();\n private snapshot: ThreadContext;\n\n constructor(options?: ThreadStoreOptions) {\n const initialThreadId = options?.initialThreadId ?? generateUUID();\n this.state = {\n currentThreadId: initialThreadId,\n threadViewKey: 0,\n threadCnt: 1,\n threads: new Map([[initialThreadId, []]]),\n threadMetadata: new Map([\n [\n initialThreadId,\n {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n },\n ],\n ]),\n };\n\n this.snapshot = this.buildSnapshot();\n }\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): ThreadContext => this.snapshot;\n\n private emit() {\n for (const listener of this.listeners) {\n listener();\n }\n }\n\n private resolveStateAction<T>(updater: SetStateAction<T>, current: T): T {\n return typeof updater === \"function\"\n ? (updater as (prev: T) => T)(current)\n : updater;\n }\n\n private ensureThreadExists(threadId: string) {\n if (!this.state.threadMetadata.has(threadId)) {\n const nextMetadata = new Map(this.state.threadMetadata);\n nextMetadata.set(threadId, {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n });\n this.state = { ...this.state, threadMetadata: nextMetadata };\n }\n\n if (!this.state.threads.has(threadId)) {\n const nextThreads = new Map(this.state.threads);\n nextThreads.set(threadId, []);\n this.state = { ...this.state, threads: nextThreads };\n }\n }\n\n private updateState(partial: Partial<ThreadStoreState>) {\n this.state = { ...this.state, ...partial };\n this.snapshot = this.buildSnapshot();\n this.emit();\n }\n\n private buildSnapshot(): ThreadContext {\n return {\n currentThreadId: this.state.currentThreadId,\n setCurrentThreadId: this.setCurrentThreadId,\n threadViewKey: this.state.threadViewKey,\n bumpThreadViewKey: this.bumpThreadViewKey,\n allThreads: this.state.threads,\n setThreads: this.setThreads,\n allThreadsMetadata: this.state.threadMetadata,\n setThreadMetadata: this.setThreadMetadata,\n threadCnt: this.state.threadCnt,\n setThreadCnt: this.setThreadCnt,\n getThreadMessages: this.getThreadMessages,\n setThreadMessages: this.setThreadMessages,\n getThreadMetadata: this.getThreadMetadata,\n updateThreadMetadata: this.updateThreadMetadata,\n };\n }\n\n setCurrentThreadId = (threadId: string) => {\n this.ensureThreadExists(threadId);\n this.updateState({ currentThreadId: threadId });\n };\n\n bumpThreadViewKey = () => {\n this.updateState({ threadViewKey: this.state.threadViewKey + 1 });\n };\n\n setThreadCnt = (updater: SetStateAction<number>) => {\n const nextCnt = this.resolveStateAction(updater, this.state.threadCnt);\n this.updateState({ threadCnt: nextCnt });\n };\n\n setThreads = (updater: SetStateAction<Map<string, ThreadMessageLike[]>>) => {\n const nextThreads = this.resolveStateAction(updater, this.state.threads);\n this.updateState({ threads: new Map(nextThreads) });\n };\n\n setThreadMetadata = (\n updater: SetStateAction<Map<string, ThreadMetadata>>,\n ) => {\n const prevMetadata = this.state.threadMetadata;\n const nextMetadata = this.resolveStateAction(updater, prevMetadata);\n for (const [threadId, next] of nextMetadata.entries()) {\n logThreadMetadataChange(\n \"setThreadMetadata\",\n threadId,\n prevMetadata.get(threadId),\n next,\n );\n }\n for (const [threadId, prev] of prevMetadata.entries()) {\n if (!nextMetadata.has(threadId)) {\n logThreadMetadataChange(\"setThreadMetadata\", threadId, prev, undefined);\n }\n }\n this.updateState({ threadMetadata: new Map(nextMetadata) });\n };\n\n setThreadMessages = (threadId: string, messages: ThreadMessageLike[]) => {\n this.ensureThreadExists(threadId);\n const nextThreads = new Map(this.state.threads);\n nextThreads.set(threadId, messages);\n this.updateState({ threads: nextThreads });\n };\n\n getThreadMessages = (threadId: string): ThreadMessageLike[] => {\n return this.state.threads.get(threadId) ?? [];\n };\n\n getThreadMetadata = (threadId: string): ThreadMetadata | undefined => {\n return this.state.threadMetadata.get(threadId);\n };\n\n updateThreadMetadata = (\n threadId: string,\n updates: Partial<ThreadMetadata>,\n ) => {\n const existing = this.state.threadMetadata.get(threadId);\n if (!existing) {\n return;\n }\n const next = { ...existing, ...updates };\n const nextMetadata = new Map(this.state.threadMetadata);\n nextMetadata.set(threadId, next);\n logThreadMetadataChange(\"updateThreadMetadata\", threadId, existing, next);\n this.updateState({ threadMetadata: nextMetadata });\n };\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n} from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport type { AomiClient } from \"@aomi-labs/client\";\n\n// =============================================================================\n// Lightweight event subscriber types (replaces event-buffer.ts)\n// =============================================================================\n\nexport type InboundEvent = {\n type: string;\n sessionId: string;\n payload?: unknown;\n};\n\nexport type SSEStatus = \"connected\" | \"connecting\" | \"disconnected\";\n\nexport type EventSubscriber = (event: InboundEvent) => void;\n\n// =============================================================================\n// Context Type\n// =============================================================================\n\nexport type EventContext = {\n /** Subscribe to events by type. Returns unsubscribe function. */\n subscribe: (type: string, callback: EventSubscriber) => () => void;\n /** Dispatch an event to all matching subscribers (used by orchestrator) */\n dispatch: (event: InboundEvent) => void;\n /** Send an outbound system message to backend */\n sendOutboundSystem: (event: { type: string; sessionId: string; payload: unknown }) => Promise<void>;\n /** Current SSE connection status */\n sseStatus: SSEStatus;\n};\n\nconst EventContextState = createContext<EventContext | null>(null);\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useEventContext(): EventContext {\n const context = useContext(EventContextState);\n if (!context) {\n throw new Error(\n \"useEventContext must be used within EventContextProvider. \" +\n \"Wrap your app with <EventContextProvider>...</EventContextProvider>\",\n );\n }\n return context;\n}\n\n// =============================================================================\n// Provider Props\n// =============================================================================\n\nexport type EventContextProviderProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n sessionId: string;\n};\n\n// =============================================================================\n// Provider\n// =============================================================================\n\n/**\n * Simplified EventContext — a pure pub/sub relay.\n *\n * SSE subscription and system event unwrapping are now handled by ClientSession\n * in the orchestrator. This provider just maintains the subscriber registry\n * and sendOutboundSystem for direct system messages.\n */\nexport function EventContextProvider({\n children,\n aomiClient,\n sessionId,\n}: EventContextProviderProps) {\n const subscribersRef = useRef<Map<string, Set<EventSubscriber>>>(new Map());\n\n const subscribe = useCallback(\n (type: string, callback: EventSubscriber) => {\n const subs = subscribersRef.current;\n if (!subs.has(type)) {\n subs.set(type, new Set());\n }\n subs.get(type)!.add(callback);\n return () => {\n subs.get(type)?.delete(callback);\n };\n },\n [],\n );\n\n const dispatchEvent = useCallback((event: InboundEvent) => {\n const subs = subscribersRef.current;\n\n // Type-specific subscribers\n const typeSubs = subs.get(event.type);\n if (typeSubs) {\n for (const cb of typeSubs) cb(event);\n }\n\n // Wildcard subscribers\n const wildcardSubs = subs.get(\"*\");\n if (wildcardSubs) {\n for (const cb of wildcardSubs) cb(event);\n }\n }, []);\n\n const sendOutbound = useCallback(\n async (event: { type: string; sessionId: string; payload: unknown }) => {\n try {\n const message = JSON.stringify({\n type: event.type,\n payload: event.payload,\n });\n await aomiClient.sendSystemMessage(event.sessionId, message);\n } catch (error) {\n console.error(\"Failed to send outbound event:\", error);\n }\n },\n [aomiClient],\n );\n\n const contextValue: EventContext = {\n subscribe,\n dispatch: dispatchEvent,\n sendOutboundSystem: sendOutbound,\n // SSE is managed by ClientSession now — status is always \"connected\"\n // when sessions are active. Individual session status can be queried\n // from the session manager if needed.\n sseStatus: \"connected\",\n };\n\n return (\n <EventContextState.Provider value={contextValue}>\n {children}\n </EventContextState.Provider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useState,\n type ReactNode,\n} from \"react\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type NotificationType = \"notice\" | \"success\" | \"error\" | \"wallet\";\n\nexport type Notification = {\n id: string;\n type: NotificationType;\n title: string;\n message?: string;\n duration?: number;\n timestamp: number;\n};\n\nexport type NotificationData = Omit<Notification, \"id\" | \"timestamp\">;\n\nexport type NotificationContextApi = {\n /** All active notifications */\n notifications: Notification[];\n /** Show a new notification */\n showNotification: (params: NotificationData) => string;\n /** Dismiss a notification by ID */\n dismissNotification: (id: string) => void;\n /** Clear all notifications */\n clearAll: () => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst NotificationContext = createContext<NotificationContextApi | null>(null);\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useNotification(): NotificationContextApi {\n const context = useContext(NotificationContext);\n if (!context) {\n throw new Error(\n \"useNotification must be used within NotificationContextProvider\",\n );\n }\n return context;\n}\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nlet notificationIdCounter = 0;\nfunction generateId(): string {\n return `notif-${Date.now()}-${++notificationIdCounter}`;\n}\n\nexport type NotificationContextProviderProps = {\n children: ReactNode;\n};\n\nexport function NotificationContextProvider({\n children,\n}: NotificationContextProviderProps) {\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n const showNotification = useCallback((params: NotificationData) => {\n const id = generateId();\n const notification: Notification = {\n ...params,\n id,\n timestamp: Date.now(),\n };\n setNotifications((prev) => [notification, ...prev]);\n return id;\n }, []);\n\n const dismissNotification = useCallback((id: string) => {\n setNotifications((prev) => prev.filter((n) => n.id !== id));\n }, []);\n\n const clearAll = useCallback(() => {\n setNotifications([]);\n }, []);\n\n const value: NotificationContextApi = {\n notifications,\n showNotification,\n dismissNotification,\n clearAll,\n };\n\n return (\n <NotificationContext.Provider value={value}>\n {children}\n </NotificationContext.Provider>\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport type { ReactNode, SetStateAction } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\nimport { ThreadMetadata, ThreadStore } from \"../state/thread-store\";\n\nexport type ThreadContext = {\n currentThreadId: string;\n setCurrentThreadId: (id: string) => void;\n threadViewKey: number;\n bumpThreadViewKey: () => void;\n allThreads: Map<string, ThreadMessageLike[]>;\n setThreads: (\n updater: SetStateAction<Map<string, ThreadMessageLike[]>>,\n ) => void;\n allThreadsMetadata: Map<string, ThreadMetadata>;\n setThreadMetadata: (\n updater: SetStateAction<Map<string, ThreadMetadata>>,\n ) => void;\n threadCnt: number;\n setThreadCnt: (updater: SetStateAction<number>) => void;\n getThreadMessages: (threadId: string) => ThreadMessageLike[];\n setThreadMessages: (threadId: string, messages: ThreadMessageLike[]) => void;\n getThreadMetadata: (threadId: string) => ThreadMetadata | undefined;\n updateThreadMetadata: (\n threadId: string,\n updates: Partial<ThreadMetadata>,\n ) => void;\n};\n\nexport type ThreadContextProviderProps = {\n children: ReactNode;\n initialThreadId?: string;\n};\n\nconst ThreadContextState = createContext<ThreadContext | null>(null);\n\nexport function useThreadContext(): ThreadContext {\n const context = useContext(ThreadContextState);\n if (!context) {\n throw new Error(\n \"useThreadContext must be used within ThreadContextProvider. \" +\n \"Wrap your app with <ThreadContextProvider>...</ThreadContextProvider>\",\n );\n }\n return context;\n}\n\nexport function ThreadContextProvider({\n children,\n initialThreadId,\n}: ThreadContextProviderProps) {\n const storeRef = useRef<ThreadStore | null>(null);\n if (!storeRef.current) {\n storeRef.current = new ThreadStore({ initialThreadId });\n }\n const store = storeRef.current;\n const value = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getSnapshot,\n );\n\n return (\n <ThreadContextState.Provider value={value}>\n {children}\n </ThreadContextState.Provider>\n );\n}\n\nexport function useCurrentThreadMessages(): ThreadMessageLike[] {\n const { currentThreadId, getThreadMessages } = useThreadContext();\n return useMemo(\n () => getThreadMessages(currentThreadId),\n [currentThreadId, getThreadMessages],\n );\n}\n\nexport function useCurrentThreadMetadata(): ThreadMetadata | undefined {\n const { currentThreadId, getThreadMetadata } = useThreadContext();\n return useMemo(\n () => getThreadMetadata(currentThreadId),\n [currentThreadId, getThreadMetadata],\n );\n}\n","\"use client\";\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\n\nexport type UserState = {\n address?: string;\n chainId?: number;\n isConnected: boolean;\n ensName?: string;\n ext?: Record<string, unknown>;\n};\n\ntype UserContextValue = {\n user: UserState;\n setUser: (data: Partial<UserState>) => void;\n addExtValue: (key: string, value: unknown) => void;\n removeExtValue: (key: string) => void;\n getUserState: () => UserState;\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n};\n\nconst UserContext = createContext<UserContextValue | undefined>(undefined);\n\nexport function useUser() {\n const context = useContext(UserContext);\n if (!context) {\n throw new Error(\"useUser must be used within UserContextProvider\");\n }\n // Return only the public API\n return {\n user: context.user,\n setUser: context.setUser,\n addExtValue: context.addExtValue,\n removeExtValue: context.removeExtValue,\n getUserState: context.getUserState,\n onUserStateChange: context.onUserStateChange,\n };\n}\n\n// ==================== Provider ====================\n\nexport function UserContextProvider({ children }: { children: ReactNode }) {\n const [user, setUserState] = useState<UserState>({\n isConnected: false,\n address: undefined,\n chainId: undefined,\n ensName: undefined,\n ext: undefined,\n });\n\n // Refs for stable getter functions\n const userRef = useRef(user);\n userRef.current = user;\n\n // Store callbacks in a ref\n const StateChangeCallbacks = useRef<Set<(user: UserState) => void>>(\n new Set(),\n );\n\n const setUser = useCallback((data: Partial<UserState>) => {\n setUserState((prev) => {\n const next = { ...prev, ...data };\n\n // Notify all subscribers\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n\n return next;\n });\n }, []);\n\n const addExtValue = useCallback((key: string, value: unknown) => {\n setUserState((prev) => {\n const next = {\n ...prev,\n ext: {\n ...(prev.ext ?? {}),\n [key]: value,\n },\n };\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n return next;\n });\n }, []);\n\n const removeExtValue = useCallback((key: string) => {\n setUserState((prev) => {\n if (!prev.ext || !(key in prev.ext)) {\n return prev;\n }\n const nextExt = { ...prev.ext };\n delete nextExt[key];\n const next = {\n ...prev,\n ext: Object.keys(nextExt).length > 0 ? nextExt : undefined,\n };\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n return next;\n });\n }, []);\n\n // Stable getters that runtime classes can call\n const getUserState = useCallback(() => userRef.current, []);\n\n // Subscribe to user state changes\n const onUserStateChange = useCallback(\n (callback: (user: UserState) => void) => {\n StateChangeCallbacks.current.add(callback);\n\n // Return unsubscribe function\n return () => {\n StateChangeCallbacks.current.delete(callback);\n };\n },\n [],\n );\n\n return (\n <UserContext.Provider\n value={{\n user,\n setUser,\n addExtValue,\n removeExtValue,\n getUserState,\n onUserStateChange,\n }}\n >\n {children}\n </UserContext.Provider>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {\n AssistantRuntimeProvider,\n useExternalStoreRuntime,\n type AppendMessage,\n} from \"@assistant-ui/react\";\n\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport { useControl } from \"../contexts/control-context\";\nimport { useEventContext } from \"../contexts/event-context\";\nimport { useUser } from \"../contexts/user-context\";\nimport { useThreadContext } from \"../contexts/thread-context\";\nimport { useNotification } from \"../contexts/notification-context\";\nimport { useRuntimeOrchestrator } from \"./orchestrator\";\nimport { isPlaceholderTitle } from \"./utils\";\nimport { buildThreadListAdapter } from \"./threadlist-adapter\";\nimport { AomiRuntimeApiProvider, type AomiRuntimeApi } from \"../interface\";\nimport { initThreadControl } from \"../state/thread-store\";\nimport { useWalletHandler } from \"../handlers/wallet-handler\";\n\n// =============================================================================\n// Core Props\n// =============================================================================\n\nexport type AomiRuntimeCoreProps = {\n children: ReactNode;\n aomiClient: AomiClient;\n};\n\n// =============================================================================\n// Core Component\n// =============================================================================\n\nexport function AomiRuntimeCore({\n children,\n aomiClient,\n}: Readonly<AomiRuntimeCoreProps>) {\n const threadContext = useThreadContext();\n const eventContext = useEventContext();\n const notificationContext = useNotification();\n const { user, onUserStateChange, getUserState } = useUser();\n const { getControlState, getCurrentThreadApp, clearSecrets } = useControl();\n\n // ---------------------------------------------------------------------------\n // Wallet handler (receives requests from orchestrator)\n // ---------------------------------------------------------------------------\n const sessionManagerRef = useRef<ReturnType<typeof useRuntimeOrchestrator>[\"sessionManager\"] | null>(null);\n\n const walletHandler = useWalletHandler({\n getSession: () => sessionManagerRef.current?.get(threadContext.currentThreadId),\n });\n\n // ---------------------------------------------------------------------------\n // Orchestrator (manages ClientSession per thread)\n // ---------------------------------------------------------------------------\n const {\n sessionManager,\n getSession,\n isRunning,\n setIsRunning,\n ensureInitialState,\n sendMessage: orchestratorSendMessage,\n cancelGeneration: orchestratorCancel,\n aomiClientRef,\n } = useRuntimeOrchestrator(aomiClient, {\n getPublicKey: () => getUserState().address,\n getUserState,\n getApp: getCurrentThreadApp,\n getApiKey: () => getControlState().apiKey,\n getClientId: () => getControlState().clientId ?? undefined,\n onWalletRequest: (request) => walletHandler.enqueueRequest(request),\n onEvent: (event) => eventContext.dispatch(event),\n });\n\n sessionManagerRef.current = sessionManager;\n\n // ---------------------------------------------------------------------------\n // Send wallet state changes to backend\n // ---------------------------------------------------------------------------\n const walletSnapshot = useCallback(\n (nextUser: ReturnType<typeof getUserState>) => ({\n address: nextUser.address,\n chainId: nextUser.chainId,\n isConnected: nextUser.isConnected,\n ensName: nextUser.ensName,\n }),\n [getUserState],\n );\n\n const lastWalletStateRef = useRef(walletSnapshot(getUserState()));\n\n useEffect(() => {\n lastWalletStateRef.current = walletSnapshot(getUserState());\n\n const unsubscribe = onUserStateChange(async (newUser) => {\n const nextWalletState = walletSnapshot(newUser);\n const prevWalletState = lastWalletStateRef.current;\n if (\n prevWalletState.address === nextWalletState.address &&\n prevWalletState.chainId === nextWalletState.chainId &&\n prevWalletState.isConnected === nextWalletState.isConnected &&\n prevWalletState.ensName === nextWalletState.ensName\n ) {\n return;\n }\n\n lastWalletStateRef.current = nextWalletState;\n const sessionId = threadContext.currentThreadId;\n const message = JSON.stringify({\n type: \"wallet:state_changed\",\n payload: nextWalletState,\n });\n await aomiClientRef.current.sendSystemMessage(sessionId, message);\n });\n\n return unsubscribe;\n }, [\n onUserStateChange,\n aomiClientRef,\n threadContext.currentThreadId,\n getUserState,\n walletSnapshot,\n ]);\n\n // ---------------------------------------------------------------------------\n // Refs for stable access\n // ---------------------------------------------------------------------------\n const threadContextRef = useRef(threadContext);\n threadContextRef.current = threadContext;\n\n const currentThreadIdRef = useRef(threadContext.currentThreadId);\n useEffect(() => {\n currentThreadIdRef.current = threadContext.currentThreadId;\n }, [threadContext.currentThreadId]);\n\n // ---------------------------------------------------------------------------\n // Respond to user_state_request from backend\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = eventContext.subscribe(\n \"user_state_request\",\n () => {\n eventContext.sendOutboundSystem({\n type: \"user_state_response\",\n sessionId: threadContext.currentThreadId,\n payload: getUserState(),\n });\n },\n );\n return unsubscribe;\n }, [eventContext, threadContext.currentThreadId, getUserState]);\n\n // ---------------------------------------------------------------------------\n // Initial state fetch on thread change\n // ---------------------------------------------------------------------------\n useEffect(() => {\n void ensureInitialState(threadContext.currentThreadId);\n }, [ensureInitialState, threadContext.currentThreadId]);\n\n // Sync isRunning to thread metadata for control context\n useEffect(() => {\n const threadId = threadContext.currentThreadId;\n const currentMeta = threadContext.getThreadMetadata(threadId);\n if (currentMeta && currentMeta.control.isProcessing !== isRunning) {\n threadContext.updateThreadMetadata(threadId, {\n control: {\n ...currentMeta.control,\n isProcessing: isRunning,\n },\n });\n }\n }, [isRunning, threadContext]);\n\n const currentMessages = threadContext.getThreadMessages(\n threadContext.currentThreadId,\n );\n\n // ---------------------------------------------------------------------------\n // Fetch thread list when user connects\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const userAddress = user.address;\n if (!userAddress) return;\n\n const fetchThreadList = async () => {\n try {\n const threadList =\n await aomiClientRef.current.listThreads(userAddress);\n const currentContext = threadContextRef.current;\n const newMetadata = new Map(currentContext.allThreadsMetadata);\n let maxChatNum = currentContext.threadCnt;\n\n for (const thread of threadList) {\n const rawTitle = thread.title ?? \"\";\n const title = isPlaceholderTitle(rawTitle) ? \"\" : rawTitle;\n const lastActive =\n newMetadata.get(thread.session_id)?.lastActiveAt ||\n new Date().toISOString();\n const existingControl = newMetadata.get(thread.session_id)?.control;\n newMetadata.set(thread.session_id, {\n title,\n status: thread.is_archived ? \"archived\" : \"regular\",\n lastActiveAt: lastActive,\n control: existingControl ?? initThreadControl(),\n });\n\n const match = title.match(/^Chat (\\d+)$/);\n if (match) {\n const num = parseInt(match[1], 10);\n if (num > maxChatNum) {\n maxChatNum = num;\n }\n }\n }\n\n currentContext.setThreadMetadata(newMetadata);\n if (maxChatNum > currentContext.threadCnt) {\n currentContext.setThreadCnt(maxChatNum);\n }\n } catch (error) {\n console.error(\"Failed to fetch thread list:\", error);\n }\n };\n\n void fetchThreadList();\n }, [user.address, aomiClientRef]);\n\n // ---------------------------------------------------------------------------\n // Thread list adapter\n // ---------------------------------------------------------------------------\n const threadListAdapter = useMemo(\n () =>\n buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n }),\n [\n aomiClientRef,\n setIsRunning,\n threadContext,\n threadContext.currentThreadId,\n threadContext.allThreadsMetadata,\n ],\n );\n\n // ---------------------------------------------------------------------------\n // Show notifications for tool updates/completions\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const showToolNotification =\n (eventType: \"tool_update\" | \"tool_complete\") =>\n (event: { payload?: unknown }) => {\n const payload = event.payload as Record<string, unknown> | undefined;\n const toolName =\n typeof payload?.tool_name === \"string\"\n ? payload.tool_name\n : undefined;\n const title = toolName\n ? `${eventType === \"tool_update\" ? \"Tool update\" : \"Tool complete\"}: ${toolName}`\n : eventType === \"tool_update\"\n ? \"Tool update\"\n : \"Tool complete\";\n const message =\n typeof payload?.message === \"string\"\n ? payload.message\n : typeof payload?.result === \"string\"\n ? payload.result\n : undefined;\n\n notificationContext.showNotification({\n type: \"notice\",\n title,\n message,\n });\n };\n\n const unsubscribeUpdate = eventContext.subscribe(\n \"tool_update\",\n showToolNotification(\"tool_update\"),\n );\n const unsubscribeComplete = eventContext.subscribe(\n \"tool_complete\",\n showToolNotification(\"tool_complete\"),\n );\n\n return () => {\n unsubscribeUpdate();\n unsubscribeComplete();\n };\n }, [eventContext, notificationContext]);\n\n // ---------------------------------------------------------------------------\n // Show notifications for system notices\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = eventContext.subscribe(\"system_notice\", (_event) => {\n // TODO: Disable it for now, we don't need async execution\n });\n\n return unsubscribe;\n }, [eventContext, notificationContext]);\n\n // ---------------------------------------------------------------------------\n // External store runtime\n // ---------------------------------------------------------------------------\n const runtime = useExternalStoreRuntime({\n messages: currentMessages,\n setMessages: (msgs) =>\n threadContext.setThreadMessages(threadContext.currentThreadId, [...msgs]),\n isRunning,\n onNew: async (message: AppendMessage) => {\n const text = message.content\n .filter(\n (part): part is Extract<typeof part, { type: \"text\" }> =>\n part.type === \"text\",\n )\n .map((part) => part.text)\n .join(\"\\n\");\n if (text) {\n await orchestratorSendMessage(text, threadContext.currentThreadId);\n }\n },\n onCancel: async () => {\n await orchestratorCancel(threadContext.currentThreadId);\n },\n convertMessage: (msg) => msg,\n adapters: { threadList: threadListAdapter },\n });\n\n // ---------------------------------------------------------------------------\n // Cleanup on unmount.\n // ---------------------------------------------------------------------------\n useEffect(() => {\n return () => {\n sessionManager.closeAll();\n void clearSecrets();\n };\n }, [sessionManager, clearSecrets]);\n\n // ---------------------------------------------------------------------------\n // Build AomiRuntimeApi\n // ---------------------------------------------------------------------------\n const userContext = useUser();\n\n const sendMessage = useCallback(\n async (text: string) => {\n await orchestratorSendMessage(text, threadContext.currentThreadId);\n },\n [orchestratorSendMessage, threadContext.currentThreadId],\n );\n\n const cancelGeneration = useCallback(() => {\n void orchestratorCancel(threadContext.currentThreadId);\n }, [orchestratorCancel, threadContext.currentThreadId]);\n\n const getMessages = useCallback(\n (threadId?: string) => {\n const id = threadId ?? threadContext.currentThreadId;\n return threadContext.getThreadMessages(id);\n },\n [threadContext],\n );\n\n const createThread = useCallback(async (): Promise<string> => {\n await threadListAdapter.onSwitchToNewThread();\n return threadContextRef.current.currentThreadId;\n }, [threadListAdapter]);\n\n const deleteThread = useCallback(\n async (threadId: string) => {\n sessionManager.close(threadId);\n await threadListAdapter.onDelete(threadId);\n },\n [threadListAdapter, sessionManager],\n );\n\n const renameThread = useCallback(\n async (threadId: string, title: string) => {\n await threadListAdapter.onRename(threadId, title);\n },\n [threadListAdapter],\n );\n\n const archiveThread = useCallback(\n async (threadId: string) => {\n await threadListAdapter.onArchive(threadId);\n },\n [threadListAdapter],\n );\n\n const selectThread = useCallback(\n (threadId: string) => {\n if (threadContext.allThreadsMetadata.has(threadId)) {\n threadListAdapter.onSwitchToThread(threadId);\n } else {\n void threadListAdapter.onSwitchToNewThread();\n }\n },\n [threadContext.allThreadsMetadata, threadListAdapter],\n );\n\n const aomiRuntimeApi: AomiRuntimeApi = useMemo(\n () => ({\n // User API\n user: userContext.user,\n getUserState: userContext.getUserState,\n setUser: userContext.setUser,\n addExtValue: userContext.addExtValue,\n removeExtValue: userContext.removeExtValue,\n onUserStateChange: userContext.onUserStateChange,\n\n // Thread API\n currentThreadId: threadContext.currentThreadId,\n threadViewKey: threadContext.threadViewKey,\n threadMetadata: threadContext.allThreadsMetadata,\n getThreadMetadata: threadContext.getThreadMetadata,\n createThread,\n deleteThread,\n renameThread,\n archiveThread,\n selectThread,\n\n // Chat API\n isRunning,\n getMessages,\n sendMessage,\n cancelGeneration,\n\n // Notification API\n notifications: notificationContext.notifications,\n showNotification: notificationContext.showNotification,\n dismissNotification: notificationContext.dismissNotification,\n clearAllNotifications: notificationContext.clearAll,\n\n // Wallet API\n pendingWalletRequests: walletHandler.pendingRequests,\n startWalletRequest: () => {}, // No-op: ClientSession manages processing state\n resolveWalletRequest: walletHandler.resolveRequest,\n rejectWalletRequest: walletHandler.rejectRequest,\n\n // Event API\n subscribe: eventContext.subscribe,\n sendSystemCommand: eventContext.sendOutboundSystem,\n sseStatus: eventContext.sseStatus,\n }),\n [\n userContext,\n threadContext.currentThreadId,\n threadContext.threadViewKey,\n threadContext.allThreadsMetadata,\n threadContext.getThreadMetadata,\n createThread,\n deleteThread,\n renameThread,\n archiveThread,\n selectThread,\n isRunning,\n getMessages,\n sendMessage,\n cancelGeneration,\n notificationContext,\n walletHandler,\n eventContext,\n ],\n );\n\n return (\n <AomiRuntimeApiProvider value={aomiRuntimeApi}>\n <AssistantRuntimeProvider runtime={runtime}>\n {children}\n </AssistantRuntimeProvider>\n </AomiRuntimeApiProvider>\n );\n}\n","\"use client\";\n\nimport type { MutableRefObject } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type {\n AomiClient,\n AomiSSEEvent,\n WalletRequest,\n} from \"@aomi-labs/client\";\nimport { Session as ClientSession } from \"@aomi-labs/client\";\nimport type { UserState } from \"../contexts/user-context\";\nimport {\n useThreadContext,\n type ThreadContext,\n} from \"../contexts/thread-context\";\nimport { SessionManager } from \"./session-manager\";\nimport { toInboundMessage } from \"./utils\";\n\ntype OrchestratorOptions = {\n getPublicKey?: () => string | undefined;\n getUserState?: () => UserState;\n getApp: () => string;\n getApiKey?: () => string | null;\n getClientId?: () => string | undefined;\n onWalletRequest?: (request: WalletRequest) => void;\n onEvent?: (event: { type: string; payload: unknown; sessionId: string }) => void;\n};\n\nexport function useRuntimeOrchestrator(\n aomiClient: AomiClient,\n options: OrchestratorOptions,\n) {\n const threadContext = useThreadContext();\n const threadContextRef = useRef<ThreadContext>(threadContext);\n threadContextRef.current = threadContext;\n const aomiClientRef = useRef(aomiClient);\n aomiClientRef.current = aomiClient;\n\n const [isRunning, setIsRunning] = useState(false);\n\n const sessionManagerRef = useRef<SessionManager | null>(null);\n if (!sessionManagerRef.current) {\n sessionManagerRef.current = new SessionManager(() => aomiClientRef.current);\n }\n\n const pendingFetches = useRef<Set<string>>(new Set());\n // Track event listener cleanup per thread\n const listenerCleanups = useRef<Map<string, () => void>>(new Map());\n\n /** Get or create a ClientSession for a thread, wiring up event listeners. */\n const getSession = useCallback(\n (threadId: string): ClientSession => {\n const manager = sessionManagerRef.current!;\n const existing = manager.get(threadId);\n if (existing) return existing;\n\n const session = manager.getOrCreate(threadId, {\n app: options.getApp(),\n publicKey: options.getPublicKey?.(),\n apiKey: options.getApiKey?.() ?? undefined,\n clientId: options.getClientId?.(),\n userState: options.getUserState?.(),\n });\n\n // Wire ClientSession events → React state\n const cleanups: Array<() => void> = [];\n\n // Messages → thread context\n cleanups.push(\n session.on(\"messages\", (msgs) => {\n const threadMessages: ThreadMessageLike[] = [];\n for (const msg of msgs) {\n const converted = toInboundMessage(msg);\n if (converted) threadMessages.push(converted);\n }\n threadContextRef.current.setThreadMessages(threadId, threadMessages);\n }),\n );\n\n // Processing state\n cleanups.push(\n session.on(\"processing_start\", () => {\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(true);\n }\n }),\n );\n cleanups.push(\n session.on(\"processing_end\", () => {\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(false);\n }\n }),\n );\n\n // Wallet requests → forwarded to handler\n cleanups.push(\n session.on(\"wallet_tx_request\", (req) => options.onWalletRequest?.(req)),\n );\n cleanups.push(\n session.on(\"wallet_eip712_request\", (req) => options.onWalletRequest?.(req)),\n );\n\n // Title changes → thread metadata\n cleanups.push(\n session.on(\"title_changed\", ({ title }) => {\n threadContextRef.current.updateThreadMetadata(threadId, { title });\n }),\n );\n\n // Forward SSE/system events to the event relay\n const forwardEvent = (type: string) =>\n session.on(type as keyof import(\"@aomi-labs/client\").SessionEventMap, (payload: unknown) => {\n options.onEvent?.({ type, payload, sessionId: threadId });\n });\n\n cleanups.push(forwardEvent(\"tool_update\"));\n cleanups.push(forwardEvent(\"tool_complete\"));\n cleanups.push(forwardEvent(\"system_notice\"));\n cleanups.push(forwardEvent(\"system_error\"));\n cleanups.push(forwardEvent(\"async_callback\"));\n\n listenerCleanups.current.set(threadId, () => {\n for (const cleanup of cleanups) cleanup();\n });\n\n return session;\n },\n // Stable deps — option getters are refs\n [],\n );\n\n const ensureInitialState = useCallback(\n async (threadId: string) => {\n if (pendingFetches.current.has(threadId)) return;\n pendingFetches.current.add(threadId);\n\n try {\n const session = getSession(threadId);\n // Update user state before fetching\n const userState = options.getUserState?.();\n if (userState) session.resolveUserState(userState);\n await session.fetchCurrentState();\n\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(session.getIsProcessing());\n }\n } catch (error) {\n console.error(\"Failed to fetch initial state:\", error);\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(false);\n }\n } finally {\n pendingFetches.current.delete(threadId);\n }\n },\n [getSession],\n );\n\n /** Send a message on the given thread. */\n const sendMessage = useCallback(\n async (text: string, threadId: string) => {\n const session = getSession(threadId);\n const userState = options.getUserState?.();\n if (userState) session.resolveUserState(userState);\n\n // Add user message to thread immediately\n const existingMessages = threadContextRef.current.getThreadMessages(threadId);\n const userMessage: ThreadMessageLike = {\n role: \"user\",\n content: [{ type: \"text\", text }],\n createdAt: new Date(),\n };\n threadContextRef.current.setThreadMessages(threadId, [\n ...existingMessages,\n userMessage,\n ]);\n threadContextRef.current.updateThreadMetadata(threadId, {\n lastActiveAt: new Date().toISOString(),\n });\n\n await session.sendAsync(text);\n },\n [getSession],\n );\n\n /** Cancel the current generation on the given thread. */\n const cancelGeneration = useCallback(\n async (threadId: string) => {\n const session = sessionManagerRef.current?.get(threadId);\n if (session) {\n await session.interrupt();\n }\n },\n [],\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n sessionManagerRef.current?.closeAll();\n for (const cleanup of listenerCleanups.current.values()) {\n cleanup();\n }\n listenerCleanups.current.clear();\n };\n }, []);\n\n return {\n sessionManager: sessionManagerRef.current!,\n getSession,\n isRunning,\n setIsRunning,\n ensureInitialState,\n sendMessage,\n cancelGeneration,\n aomiClientRef,\n };\n}\n","// =============================================================================\n// SessionManager — manages one ClientSession per thread\n// =============================================================================\n\nimport type { AomiClient, AomiClientOptions } from \"@aomi-labs/client\";\nimport { Session as ClientSession, type SessionOptions } from \"@aomi-labs/client\";\n\nexport class SessionManager {\n private sessions = new Map<string, ClientSession>();\n\n constructor(\n private readonly clientFactory: () => AomiClient,\n ) {}\n\n getOrCreate(threadId: string, opts: Omit<SessionOptions, \"sessionId\">): ClientSession {\n let session = this.sessions.get(threadId);\n if (session) return session;\n\n session = new ClientSession(this.clientFactory(), {\n ...opts,\n sessionId: threadId,\n });\n this.sessions.set(threadId, session);\n return session;\n }\n\n get(threadId: string): ClientSession | undefined {\n return this.sessions.get(threadId);\n }\n\n close(threadId: string): void {\n const session = this.sessions.get(threadId);\n if (session) {\n session.close();\n this.sessions.delete(threadId);\n }\n }\n\n closeAll(): void {\n for (const [threadId, session] of this.sessions) {\n session.close();\n }\n this.sessions.clear();\n }\n}\n","import type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { AomiMessage } from \"@aomi-labs/client\";\nimport type { UserState } from \"../contexts/user-context\";\n\nimport { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Utility function to merge Tailwind CSS classes with conflict resolution.\n * Combines clsx for conditional classes and tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n\n// ==================== Thread Utilities ====================\n\nexport const parseTimestamp = (value?: string | number) => {\n if (value === undefined || value === null) return 0;\n if (typeof value === \"number\") {\n return Number.isFinite(value) ? (value < 1e12 ? value * 1000 : value) : 0;\n }\n\n const numeric = Number(value);\n if (!Number.isNaN(numeric)) {\n return numeric < 1e12 ? numeric * 1000 : numeric;\n }\n\n const ts = Date.parse(value);\n return Number.isNaN(ts) ? 0 : ts;\n};\n\nexport const isPlaceholderTitle = (title?: string) => {\n const normalized = title?.trim() ?? \"\";\n return !normalized || normalized.startsWith(\"#[\");\n};\n\n// ==================== Message Conversion ====================\n\ntype MessageContentPart =\n Exclude<ThreadMessageLike[\"content\"], string> extends readonly (infer U)[]\n ? U\n : never;\n\nexport function toInboundMessage(msg: AomiMessage): ThreadMessageLike | null {\n if (msg.sender === \"system\") return null;\n\n const content: MessageContentPart[] = [];\n const role: ThreadMessageLike[\"role\"] =\n msg.sender === \"user\" ? \"user\" : \"assistant\";\n\n if (msg.content) {\n content.push({ type: \"text\" as const, text: msg.content });\n }\n\n const [topic, toolContent] = parseToolPayload(msg) ?? [];\n if (topic && toolContent) {\n content.push({\n type: \"tool-call\" as const,\n toolCallId: `tool_${Date.now()}`,\n toolName: topic,\n args: undefined,\n result: (() => {\n try {\n return JSON.parse(toolContent);\n } catch {\n return { args: toolContent };\n }\n })(),\n });\n }\n\n const threadMessage = {\n role,\n content: (content.length > 0\n ? content\n : [{ type: \"text\" as const, text: \"\" }]) as ThreadMessageLike[\"content\"],\n ...(msg.timestamp && { createdAt: new Date(msg.timestamp) }),\n } satisfies ThreadMessageLike;\n\n return threadMessage;\n}\n\nfunction parseToolPayload(msg: AomiMessage): [string, string] | null {\n return parseToolResult(msg.tool_result);\n}\n\nexport function constructUITool(): string {\n return \"\";\n}\n\nfunction parseMessageTimestamp(timestamp?: string) {\n if (!timestamp) return undefined;\n const parsed = new Date(timestamp);\n return Number.isNaN(parsed.valueOf()) ? undefined : parsed;\n}\n\nfunction parseToolResult(\n toolResult: AomiMessage[\"tool_result\"],\n): [string, string] | null {\n if (!toolResult) return null;\n\n if (Array.isArray(toolResult) && toolResult.length === 2) {\n const [topic, content] = toolResult;\n return [String(topic), String(content ?? \"\")];\n }\n\n return null;\n}\n\n// ==================== Wallet Utilities ====================\n\n/**\n * User configuration props for footer components.\n * Provides user state and setter from UserContext.\n */\nexport type UserConfig = {\n user: UserState;\n setUser: (data: Partial<UserState>) => void;\n};\n\nexport type Eip1193Provider = {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n};\n\nexport const getNetworkName = (\n chainId: number | string | undefined,\n): string => {\n if (chainId === undefined) return \"\";\n const id = typeof chainId === \"string\" ? Number(chainId) : chainId;\n switch (id) {\n case 1:\n return \"ethereum\";\n case 137:\n return \"polygon\";\n case 42161:\n return \"arbitrum\";\n case 8453:\n return \"base\";\n case 10:\n return \"optimism\";\n case 11155111:\n return \"sepolia\";\n case 1337:\n case 31337:\n return \"testnet\";\n case 59140:\n return \"linea-sepolia\";\n case 59144:\n return \"linea\";\n default:\n return \"testnet\";\n }\n};\n\nexport const formatAddress = (addr?: string): string =>\n addr ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : \"Connect Wallet\";\n\n// ==================== Chain Metadata ====================\n\n/** Static metadata for a supported chain */\nexport type ChainInfo = { id: number; name: string; ticker: string };\n\n/** All chains supported by the application. Single source of truth. */\nexport const SUPPORTED_CHAINS: ChainInfo[] = [\n { id: 1, name: \"Ethereum\", ticker: \"ETH\" },\n { id: 137, name: \"Polygon\", ticker: \"MATIC\" },\n { id: 42161, name: \"Arbitrum\", ticker: \"ARB\" },\n { id: 8453, name: \"Base\", ticker: \"BASE\" },\n { id: 10, name: \"Optimism\", ticker: \"OP\" },\n { id: 11155111, name: \"Sepolia\", ticker: \"SEP\" },\n];\n\n/** Look up ChainInfo by chain ID. Returns undefined for unknown chains. */\nexport const getChainInfo = (\n chainId: number | undefined,\n): ChainInfo | undefined =>\n chainId === undefined\n ? undefined\n : SUPPORTED_CHAINS.find((c) => c.id === chainId);\n\nexport function normalizeWalletError(error: unknown): {\n rejected: boolean;\n message: string;\n} {\n const e = error as {\n code?: unknown;\n name?: unknown;\n message?: unknown;\n shortMessage?: unknown;\n cause?: unknown;\n };\n const cause = (e?.cause ?? null) as {\n code?: unknown;\n name?: unknown;\n message?: unknown;\n shortMessage?: unknown;\n } | null;\n\n const code =\n (typeof e?.code === \"number\" ? e.code : undefined) ??\n (typeof cause?.code === \"number\" ? cause.code : undefined);\n const name =\n (typeof e?.name === \"string\" ? e.name : undefined) ??\n (typeof cause?.name === \"string\" ? cause.name : undefined);\n const msg =\n (typeof e?.shortMessage === \"string\" ? e.shortMessage : undefined) ??\n (typeof cause?.shortMessage === \"string\"\n ? cause.shortMessage\n : undefined) ??\n (typeof e?.message === \"string\" ? e.message : undefined) ??\n (typeof cause?.message === \"string\" ? cause.message : undefined) ??\n \"Unknown wallet error\";\n\n const rejected =\n code === 4001 ||\n name === \"UserRejectedRequestError\" ||\n name === \"RejectedRequestError\" ||\n /user rejected|rejected the request|denied|request rejected|canceled|cancelled/i.test(\n msg,\n );\n\n return { rejected, message: msg };\n}\n\nexport function toHexQuantity(value: string): string {\n const trimmed = value.trim();\n const asBigInt = BigInt(trimmed);\n return `0x${asBigInt.toString(16)}`;\n}\n\nexport async function pickInjectedProvider(\n publicKey?: string,\n): Promise<Eip1193Provider | undefined> {\n const ethereum = (globalThis as unknown as { ethereum?: unknown })\n .ethereum as (Eip1193Provider & { providers?: unknown[] }) | undefined;\n if (!ethereum?.request) return undefined;\n\n const candidates: Eip1193Provider[] = Array.isArray(ethereum.providers)\n ? (ethereum.providers.filter(\n (p): p is Eip1193Provider => !!(p as Eip1193Provider)?.request,\n ) as Eip1193Provider[])\n : [ethereum];\n\n const target = publicKey?.toLowerCase();\n if (target) {\n for (const candidate of candidates) {\n try {\n const accounts = (await candidate.request({\n method: \"eth_accounts\",\n })) as unknown;\n const list = Array.isArray(accounts)\n ? (accounts as unknown[]).map((a) => String(a).toLowerCase())\n : [];\n if (list.includes(target)) return candidate;\n } catch {\n // Ignore providers that error on eth_accounts.\n }\n }\n }\n\n return candidates[0];\n}\n","import { generateUUID } from \"../utils/uuid\";\nimport type { MutableRefObject } from \"react\";\nimport type { ExternalStoreThreadData } from \"@assistant-ui/react\";\n\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport type { ThreadContext } from \"../contexts/thread-context\";\nimport type { UserState } from \"../contexts/user-context\";\nimport { initThreadControl, type ThreadMetadata } from \"../state/thread-store\";\nimport { isPlaceholderTitle, parseTimestamp } from \"./utils\";\n\n// =============================================================================\n// Thread List Helpers\n// =============================================================================\n\nconst sortByLastActiveDesc = (\n [, metaA]: [string, ThreadMetadata],\n [, metaB]: [string, ThreadMetadata],\n) => {\n const tsA = parseTimestamp(metaA.lastActiveAt);\n const tsB = parseTimestamp(metaB.lastActiveAt);\n return tsB - tsA;\n};\n\nfunction buildThreadLists(threadMetadata: Map<string, ThreadMetadata>) {\n const entries = Array.from(threadMetadata.entries()).filter(\n ([, meta]) => !isPlaceholderTitle(meta.title),\n );\n\n const regularThreads = entries\n .filter(([, meta]) => meta.status !== \"archived\")\n .sort(sortByLastActiveDesc)\n .map(\n ([id, meta]): ExternalStoreThreadData<\"regular\"> => ({\n id,\n title: meta.title || \"New Chat\",\n status: \"regular\",\n }),\n );\n\n const archivedThreads = entries\n .filter(([, meta]) => meta.status === \"archived\")\n .sort(sortByLastActiveDesc)\n .map(\n ([id, meta]): ExternalStoreThreadData<\"archived\"> => ({\n id,\n title: meta.title || \"New Chat\",\n status: \"archived\",\n }),\n );\n\n return { regularThreads, archivedThreads };\n}\n\n// =============================================================================\n// Adapter Builder\n// =============================================================================\n\nexport type ThreadListAdapterConfig = {\n aomiClientRef: MutableRefObject<AomiClient>;\n threadContext: ThreadContext;\n setIsRunning: (running: boolean) => void;\n};\n\nexport function buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n}: ThreadListAdapterConfig) {\n const { regularThreads, archivedThreads } = buildThreadLists(\n threadContext.allThreadsMetadata,\n );\n\n return {\n threadId: threadContext.currentThreadId,\n threads: regularThreads,\n archivedThreads,\n\n onSwitchToNewThread: () => {\n const threadId = generateUUID();\n threadContext.setThreadMetadata((prev) =>\n new Map(prev).set(threadId, {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n }),\n );\n threadContext.setThreadMessages(threadId, []);\n threadContext.setCurrentThreadId(threadId);\n setIsRunning(false);\n threadContext.bumpThreadViewKey();\n },\n\n onSwitchToThread: (threadId: string) => {\n threadContext.setCurrentThreadId(threadId);\n threadContext.bumpThreadViewKey();\n },\n\n onRename: async (threadId: string, newTitle: string) => {\n const previousTitle =\n threadContext.getThreadMetadata(threadId)?.title ?? \"\";\n const normalizedTitle = isPlaceholderTitle(newTitle) ? \"\" : newTitle;\n threadContext.updateThreadMetadata(threadId, {\n title: normalizedTitle,\n });\n\n try {\n await aomiClientRef.current.renameThread(threadId, newTitle);\n } catch (error) {\n console.error(\"Failed to rename thread:\", error);\n threadContext.updateThreadMetadata(threadId, {\n title: previousTitle,\n });\n }\n },\n\n onArchive: async (threadId: string) => {\n threadContext.updateThreadMetadata(threadId, { status: \"archived\" });\n\n try {\n await aomiClientRef.current.archiveThread(threadId);\n } catch (error) {\n console.error(\"Failed to archive thread:\", error);\n threadContext.updateThreadMetadata(threadId, { status: \"regular\" });\n }\n },\n\n onUnarchive: async (threadId: string) => {\n threadContext.updateThreadMetadata(threadId, { status: \"regular\" });\n\n try {\n await aomiClientRef.current.unarchiveThread(threadId);\n } catch (error) {\n console.error(\"Failed to unarchive thread:\", error);\n threadContext.updateThreadMetadata(threadId, { status: \"archived\" });\n }\n },\n\n onDelete: async (threadId: string) => {\n try {\n await aomiClientRef.current.deleteThread(threadId);\n\n threadContext.setThreadMetadata((prev) => {\n const next = new Map(prev);\n next.delete(threadId);\n return next;\n });\n threadContext.setThreads((prev) => {\n const next = new Map(prev);\n next.delete(threadId);\n return next;\n });\n\n if (threadContext.currentThreadId === threadId) {\n const firstRegularThread = Array.from(\n threadContext.allThreadsMetadata.entries(),\n ).find(([id, meta]) => meta.status === \"regular\" && id !== threadId);\n\n if (firstRegularThread) {\n threadContext.setCurrentThreadId(firstRegularThread[0]);\n } else {\n const defaultId = \"default-session\";\n threadContext.setThreadMetadata((prev) =>\n new Map(prev).set(defaultId, {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n }),\n );\n threadContext.setThreadMessages(defaultId, []);\n threadContext.setCurrentThreadId(defaultId);\n }\n }\n } catch (error) {\n console.error(\"Failed to delete thread:\", error);\n throw error;\n }\n },\n };\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { UserState } from \"./contexts/user-context\";\nimport type { ThreadMetadata } from \"./state/thread-store\";\nimport type {\n EventSubscriber,\n SSEStatus,\n} from \"./contexts/event-context\";\nimport type {\n Notification,\n NotificationData,\n} from \"./contexts/notification-context\";\nimport type {\n WalletRequest,\n WalletRequestResult,\n} from \"./handlers/wallet-handler\";\n\n// =============================================================================\n// AomiRuntimeApi Type\n// =============================================================================\n\nexport type AomiRuntimeApi = {\n // -------------------------------------------------------------------------\n // USER API\n // -------------------------------------------------------------------------\n /** Current user state (wallet connection, address, chain, etc.) */\n user: UserState;\n /** Get current user state synchronously (useful in callbacks) */\n getUserState: () => UserState;\n /** Update user state (partial updates merged with existing state) */\n setUser: (data: Partial<UserState>) => void;\n /** Add or overwrite a value in user_state.ext */\n addExtValue: (key: string, value: unknown) => void;\n /** Remove a value from user_state.ext */\n removeExtValue: (key: string) => void;\n /** Subscribe to user state changes. Returns unsubscribe function. */\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n\n // -------------------------------------------------------------------------\n // THREAD API\n // -------------------------------------------------------------------------\n /** ID of the currently active thread */\n currentThreadId: string;\n /** Key that changes when thread view should remount (use for React key prop) */\n threadViewKey: number;\n /** Metadata for all threads (title, status, lastActiveAt) */\n threadMetadata: Map<string, ThreadMetadata>;\n /** Get metadata for a specific thread */\n getThreadMetadata: (threadId: string) => ThreadMetadata | undefined;\n /** Create a new thread and return its ID */\n createThread: () => Promise<string>;\n /** Delete a thread by ID */\n deleteThread: (threadId: string) => Promise<void>;\n /** Rename a thread */\n renameThread: (threadId: string, title: string) => Promise<void>;\n /** Archive a thread */\n archiveThread: (threadId: string) => Promise<void>;\n /** Switch to a thread. If thread doesn't exist, creates a new one. */\n selectThread: (threadId: string) => void;\n\n // -------------------------------------------------------------------------\n // CHAT API\n // -------------------------------------------------------------------------\n /** Whether the assistant is currently generating a response */\n isRunning: boolean;\n /** Get messages for a thread (defaults to currentThreadId) */\n getMessages: (threadId?: string) => ThreadMessageLike[];\n /** Send a message to the current thread */\n sendMessage: (text: string) => Promise<void>;\n /** Cancel the current generation */\n cancelGeneration: () => void;\n\n // -------------------------------------------------------------------------\n // NOTIFICATION API\n // -------------------------------------------------------------------------\n /** All active notifications */\n notifications: Notification[];\n /** Show a notification. Returns the notification ID. */\n showNotification: (params: NotificationData) => string;\n /** Dismiss a notification by ID */\n dismissNotification: (id: string) => void;\n /** Clear all notifications */\n clearAllNotifications: () => void;\n\n // -------------------------------------------------------------------------\n // WALLET API\n // -------------------------------------------------------------------------\n /** All queued wallet requests (tx + eip712 signing) */\n pendingWalletRequests: WalletRequest[];\n /** Mark a wallet request as being processed */\n startWalletRequest: (id: string) => void;\n /** Complete a wallet request — dequeues + sends response to backend */\n resolveWalletRequest: (id: string, result: WalletRequestResult) => void;\n /** Fail a wallet request — dequeues + sends error to backend */\n rejectWalletRequest: (id: string, error?: string) => void;\n\n // -------------------------------------------------------------------------\n // EVENT API\n // -------------------------------------------------------------------------\n /** Subscribe to inbound events by type. Returns unsubscribe function. */\n subscribe: (type: string, callback: EventSubscriber) => () => void;\n /** Send a system command to the backend */\n sendSystemCommand: (event: { type: string; sessionId: string; payload: unknown }) => Promise<void>;\n /** Current SSE connection status */\n sseStatus: SSEStatus;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst AomiRuntimeContext = createContext<AomiRuntimeApi | null>(null);\n\nexport const AomiRuntimeApiProvider = AomiRuntimeContext.Provider;\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Unified hook that provides access to all Aomi runtime APIs.\n *\n * This is the primary way to interact with the Aomi runtime from consumer code.\n * It combines user, thread, chat, notification, and event APIs into a single interface.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const aomi = useAomiRuntime();\n *\n * // User API\n * const { user, setUser } = aomi;\n *\n * // Thread API\n * const { currentThreadId, createThread, selectThread } = aomi;\n *\n * // Chat API\n * const { isRunning, sendMessage, cancelGeneration } = aomi;\n *\n * // Notification API\n * const { showNotification } = aomi;\n *\n * // Event API\n * const { subscribe, sendSystemCommand } = aomi;\n * }\n * ```\n */\nexport function useAomiRuntime(): AomiRuntimeApi {\n const context = useContext(AomiRuntimeContext);\n if (!context) {\n throw new Error(\n \"useAomiRuntime must be used within AomiRuntimeProvider. \" +\n \"Wrap your app with <AomiRuntimeProvider>...</AomiRuntimeProvider>\",\n );\n }\n return context;\n}\n","\"use client\";\n\nimport { useCallback, useRef, useState } from \"react\";\nimport type {\n WalletEip712Payload,\n WalletTxPayload,\n WalletRequest,\n} from \"@aomi-labs/client\";\nimport type { Session as ClientSession } from \"@aomi-labs/client\";\n\n// Re-export types consumers need\nexport type { WalletRequest, WalletTxPayload, WalletEip712Payload };\n\nexport type WalletRequestKind = \"transaction\" | \"eip712_sign\";\nexport type WalletRequestStatus = \"pending\" | \"processing\";\n\nexport type WalletRequestResult = {\n txHash?: string;\n signature?: string;\n amount?: string;\n};\n\nexport type WalletHandlerConfig = {\n /** Get the ClientSession for the current thread. */\n getSession: () => ClientSession | undefined;\n};\n\nexport type WalletHandlerApi = {\n /** All queued wallet requests (tx + eip712) */\n pendingRequests: WalletRequest[];\n /** Enqueue a wallet request (called by orchestrator on ClientSession events) */\n enqueueRequest: (request: WalletRequest) => void;\n /** Complete a request successfully — sends response to backend via ClientSession */\n resolveRequest: (id: string, result: WalletRequestResult) => void;\n /** Fail a request — sends error to backend via ClientSession */\n rejectRequest: (id: string, error?: string) => void;\n};\n\nexport function useWalletHandler({\n getSession,\n}: WalletHandlerConfig): WalletHandlerApi {\n const [pendingRequests, setPendingRequests] = useState<WalletRequest[]>([]);\n const requestsRef = useRef<WalletRequest[]>([]);\n\n const enqueueRequest = useCallback((request: WalletRequest) => {\n requestsRef.current = [...requestsRef.current, request];\n setPendingRequests(requestsRef.current);\n }, []);\n\n const resolveRequest = useCallback(\n (id: string, result: WalletRequestResult) => {\n const session = getSession();\n if (!session) {\n console.error(\"[wallet-handler] No session available to resolve request\");\n return;\n }\n\n requestsRef.current = requestsRef.current.filter((r) => r.id !== id);\n setPendingRequests(requestsRef.current);\n\n void session.resolve(id, result).catch((err) => {\n console.error(\"[wallet-handler] Failed to resolve request:\", err);\n });\n },\n [getSession],\n );\n\n const rejectRequest = useCallback(\n (id: string, error?: string) => {\n const session = getSession();\n if (!session) {\n console.error(\"[wallet-handler] No session available to reject request\");\n return;\n }\n\n requestsRef.current = requestsRef.current.filter((r) => r.id !== id);\n setPendingRequests(requestsRef.current);\n\n void session.reject(id, error).catch((err) => {\n console.error(\"[wallet-handler] Failed to reject request:\", err);\n });\n },\n [getSession],\n );\n\n return {\n pendingRequests,\n enqueueRequest,\n resolveRequest,\n rejectRequest,\n };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useEventContext } from \"../contexts/event-context\";\nimport type { InboundEvent } from \"../contexts/event-context\";\n\nexport type Notification = {\n id: string;\n type: string;\n title: string;\n body?: unknown; // Could be JSON object or string\n handled: boolean;\n timestamp: number;\n sessionId: string;\n};\n\nexport type NotificationHandlerConfig = {\n /** Callback when new notification arrives */\n onNotification?: (notification: Notification) => void;\n};\n\nexport type NotificationApi = {\n /** All notifications */\n notifications: Notification[];\n /** Unhandled count */\n unhandledCount: number;\n /** Mark notification as handled */\n markDone: (id: string) => void;\n};\n\nlet notificationIdCounter = 0;\nfunction generateNotificationId(): string {\n return `notif-${Date.now()}-${++notificationIdCounter}`;\n}\n\nexport function useNotificationHandler({\n onNotification,\n}: NotificationHandlerConfig = {}): NotificationApi {\n const { subscribe } = useEventContext();\n const [notifications, setNotifications] = useState<Notification[]>([]);\n\n // ---------------------------------------------------------------------------\n // Subscribe to notification events\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = subscribe(\"notification\", (event: InboundEvent) => {\n const payload = event.payload as Record<string, unknown>;\n\n const notification: Notification = {\n id: generateNotificationId(),\n type: (payload.type as string) ?? \"notification\",\n title: (payload.title as string) ?? \"Notification\",\n body: payload.body,\n handled: false,\n timestamp: Date.now(),\n sessionId: event.sessionId,\n };\n\n setNotifications((prev) => [notification, ...prev]);\n onNotification?.(notification);\n });\n\n return unsubscribe;\n }, [subscribe, onNotification]);\n\n // ---------------------------------------------------------------------------\n // Computed: unhandled count\n // ---------------------------------------------------------------------------\n const unhandledCount = notifications.filter((n) => !n.handled).length;\n\n // ---------------------------------------------------------------------------\n // Actions\n // ---------------------------------------------------------------------------\n const markHandled = useCallback((id: string) => {\n setNotifications((prev) =>\n prev.map((n) => (n.id === id ? { ...n, handled: true } : n)),\n );\n }, []);\n\n return {\n notifications,\n unhandledCount,\n markDone: markHandled,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,IAAAA,iBAA2B;AAa3B,IAAAA,iBAAwC;;;ACdxC,IAAAC,iBAAwB;AAGxB,IAAAC,iBAA2B;;;ACH3B,mBAQO;;;ACTA,SAAS,eAAuB;AACrC,MACE,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,YAC7B;AACA,WAAO,OAAO,WAAW;AAAA,EAC3B;AAGA,SAAO,uCAAuC,QAAQ,SAAS,CAAC,MAAM;AACpE,UAAM,IAAK,KAAK,OAAO,IAAI,KAAM;AACjC,UAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAO;AACtC,WAAO,EAAE,SAAS,EAAE;AAAA,EACtB,CAAC;AACH;;;ACVA,IAAM,yBAAyB,QAAQ,IAAI,aAAa;AAExD,IAAM,0BAA0B,CAC9B,QACA,UACA,MACA,SACG;AACH,MAAI,CAAC,uBAAwB;AAC7B,MAAI,CAAC,QAAQ,CAAC,KAAM;AACpB,MAAI,CAAC,QAAQ,CAAC,MAAM;AAClB,YAAQ,MAAM,iBAAiB,MAAM,KAAK,EAAE,UAAU,MAAM,KAAK,CAAC;AAClE;AAAA,EACF;AACA,MACE,KAAK,UAAU,KAAK,SACpB,KAAK,WAAW,KAAK,UACrB,KAAK,iBAAiB,KAAK,cAC3B;AACA,YAAQ,MAAM,iBAAiB,MAAM,KAAK,EAAE,UAAU,MAAM,KAAK,CAAC;AAAA,EACpE;AACF;AAwBO,SAAS,oBAAwC;AACtD,SAAO;AAAA,IACL,OAAO;AAAA,IACP,KAAK;AAAA,IACL,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AACF;AAcO,IAAM,cAAN,MAAkB;AAAA,EAKvB,YAAY,SAA8B;AAH1C,SAAQ,YAAY,oBAAI,IAAgB;AA0BxC,qBAAY,CAAC,aAAuC;AAClD,WAAK,UAAU,IAAI,QAAQ;AAC3B,aAAO,MAAM;AACX,aAAK,UAAU,OAAO,QAAQ;AAAA,MAChC;AAAA,IACF;AAEA,uBAAc,MAAqB,KAAK;AA0DxC,8BAAqB,CAAC,aAAqB;AACzC,WAAK,mBAAmB,QAAQ;AAChC,WAAK,YAAY,EAAE,iBAAiB,SAAS,CAAC;AAAA,IAChD;AAEA,6BAAoB,MAAM;AACxB,WAAK,YAAY,EAAE,eAAe,KAAK,MAAM,gBAAgB,EAAE,CAAC;AAAA,IAClE;AAEA,wBAAe,CAAC,YAAoC;AAClD,YAAM,UAAU,KAAK,mBAAmB,SAAS,KAAK,MAAM,SAAS;AACrE,WAAK,YAAY,EAAE,WAAW,QAAQ,CAAC;AAAA,IACzC;AAEA,sBAAa,CAAC,YAA8D;AAC1E,YAAM,cAAc,KAAK,mBAAmB,SAAS,KAAK,MAAM,OAAO;AACvE,WAAK,YAAY,EAAE,SAAS,IAAI,IAAI,WAAW,EAAE,CAAC;AAAA,IACpD;AAEA,6BAAoB,CAClB,YACG;AACH,YAAM,eAAe,KAAK,MAAM;AAChC,YAAM,eAAe,KAAK,mBAAmB,SAAS,YAAY;AAClE,iBAAW,CAAC,UAAU,IAAI,KAAK,aAAa,QAAQ,GAAG;AACrD;AAAA,UACE;AAAA,UACA;AAAA,UACA,aAAa,IAAI,QAAQ;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AACA,iBAAW,CAAC,UAAU,IAAI,KAAK,aAAa,QAAQ,GAAG;AACrD,YAAI,CAAC,aAAa,IAAI,QAAQ,GAAG;AAC/B,kCAAwB,qBAAqB,UAAU,MAAM,MAAS;AAAA,QACxE;AAAA,MACF;AACA,WAAK,YAAY,EAAE,gBAAgB,IAAI,IAAI,YAAY,EAAE,CAAC;AAAA,IAC5D;AAEA,6BAAoB,CAAC,UAAkB,aAAkC;AACvE,WAAK,mBAAmB,QAAQ;AAChC,YAAM,cAAc,IAAI,IAAI,KAAK,MAAM,OAAO;AAC9C,kBAAY,IAAI,UAAU,QAAQ;AAClC,WAAK,YAAY,EAAE,SAAS,YAAY,CAAC;AAAA,IAC3C;AAEA,6BAAoB,CAAC,aAA0C;AAnNjE;AAoNI,cAAO,UAAK,MAAM,QAAQ,IAAI,QAAQ,MAA/B,YAAoC,CAAC;AAAA,IAC9C;AAEA,6BAAoB,CAAC,aAAiD;AACpE,aAAO,KAAK,MAAM,eAAe,IAAI,QAAQ;AAAA,IAC/C;AAEA,gCAAuB,CACrB,UACA,YACG;AACH,YAAM,WAAW,KAAK,MAAM,eAAe,IAAI,QAAQ;AACvD,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AACA,YAAM,OAAO,kCAAK,WAAa;AAC/B,YAAM,eAAe,IAAI,IAAI,KAAK,MAAM,cAAc;AACtD,mBAAa,IAAI,UAAU,IAAI;AAC/B,8BAAwB,wBAAwB,UAAU,UAAU,IAAI;AACxE,WAAK,YAAY,EAAE,gBAAgB,aAAa,CAAC;AAAA,IACnD;AAxOF;AA6EI,UAAM,mBAAkB,wCAAS,oBAAT,YAA4B,aAAa;AACjE,SAAK,QAAQ;AAAA,MACX,iBAAiB;AAAA,MACjB,eAAe;AAAA,MACf,WAAW;AAAA,MACX,SAAS,oBAAI,IAAI,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAAA,MACxC,gBAAgB,oBAAI,IAAI;AAAA,QACtB;AAAA,UACE;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,YACrC,SAAS,kBAAkB;AAAA,UAC7B;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,SAAK,WAAW,KAAK,cAAc;AAAA,EACrC;AAAA,EAWQ,OAAO;AACb,eAAW,YAAY,KAAK,WAAW;AACrC,eAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,mBAAsB,SAA4B,SAAe;AACvE,WAAO,OAAO,YAAY,aACrB,QAA2B,OAAO,IACnC;AAAA,EACN;AAAA,EAEQ,mBAAmB,UAAkB;AAC3C,QAAI,CAAC,KAAK,MAAM,eAAe,IAAI,QAAQ,GAAG;AAC5C,YAAM,eAAe,IAAI,IAAI,KAAK,MAAM,cAAc;AACtD,mBAAa,IAAI,UAAU;AAAA,QACzB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QACrC,SAAS,kBAAkB;AAAA,MAC7B,CAAC;AACD,WAAK,QAAQ,iCAAK,KAAK,QAAV,EAAiB,gBAAgB,aAAa;AAAA,IAC7D;AAEA,QAAI,CAAC,KAAK,MAAM,QAAQ,IAAI,QAAQ,GAAG;AACrC,YAAM,cAAc,IAAI,IAAI,KAAK,MAAM,OAAO;AAC9C,kBAAY,IAAI,UAAU,CAAC,CAAC;AAC5B,WAAK,QAAQ,iCAAK,KAAK,QAAV,EAAiB,SAAS,YAAY;AAAA,IACrD;AAAA,EACF;AAAA,EAEQ,YAAY,SAAoC;AACtD,SAAK,QAAQ,kCAAK,KAAK,QAAU;AACjC,SAAK,WAAW,KAAK,cAAc;AACnC,SAAK,KAAK;AAAA,EACZ;AAAA,EAEQ,gBAA+B;AACrC,WAAO;AAAA,MACL,iBAAiB,KAAK,MAAM;AAAA,MAC5B,oBAAoB,KAAK;AAAA,MACzB,eAAe,KAAK,MAAM;AAAA,MAC1B,mBAAmB,KAAK;AAAA,MACxB,YAAY,KAAK,MAAM;AAAA,MACvB,YAAY,KAAK;AAAA,MACjB,oBAAoB,KAAK,MAAM;AAAA,MAC/B,mBAAmB,KAAK;AAAA,MACxB,WAAW,KAAK,MAAM;AAAA,MACtB,cAAc,KAAK;AAAA,MACnB,mBAAmB,KAAK;AAAA,MACxB,mBAAmB,KAAK;AAAA,MACxB,mBAAmB,KAAK;AAAA,MACxB,sBAAsB,KAAK;AAAA,IAC7B;AAAA,EACF;AAuEF;;;AF0bI;AAtkBJ,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,4BAA4B;AAClC,IAAM,6BAA6B;AAEnC,SAAS,sBAA8B;AAlGvC;AAmGE,MAAI;AACF,UAAM,kBAAiB,gBAAW,iBAAX,mBAAyB,QAAQ;AACxD,QAAI,kBAAkB,eAAe,KAAK,EAAE,SAAS,GAAG;AACtD,aAAO;AAAA,IACT;AAAA,EACF,SAAQ;AAAA,EAER;AAEA,QAAM,YAAW,4BAAW,WAAX,mBAAmB,eAAnB,4CAAqC,UAAU,KAAK,IAAI,CAAC;AAC1E,MAAI;AACF,qBAAW,iBAAX,mBAAyB,QAAQ,uBAAuB;AAAA,EAC1D,SAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAA+B;AArHtD;AAsHE,SAAO,KAAK,SAAS,SAAS,IAAI,aAAa,UAAK,CAAC,MAAN,YAAW;AAC5D;AAEA,SAAS,qBACP,KACA,gBACA,YACe;AACf,MAAI,OAAO,eAAe,SAAS,GAAG,GAAG;AACvC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMA,IAAM,qBAAiB,4BAAwC,IAAI;AAM5D,SAAS,aAAgC;AAC9C,QAAM,UAAM,yBAAW,cAAc;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAO;AACT;AAoBO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAgC;AA/KhC;AAgLE,QAAM,CAAC,OAAO,gBAAgB,QAAI,uBAAuB,OAAO;AAAA,IAC9D,QAAQ;AAAA,IACR,UAAU,oBAAoB;AAAA,IAC9B,iBAAiB,CAAC;AAAA,IAClB,gBAAgB,CAAC;AAAA,IACjB,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,cAAc,CAAC;AAAA,EACjB,EAAE;AAEF,QAAM,eAAW,qBAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,QAAM,oBAAgB,qBAAO,UAAU;AACvC,gBAAc,UAAU;AAExB,QAAM,mBAAe,qBAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,mBAAe,qBAAO,SAAS;AACrC,eAAa,UAAU;AAEvB,QAAM,2BAAuB,qBAAO,iBAAiB;AACrD,uBAAqB,UAAU;AAE/B,QAAM,8BAA0B,qBAAO,oBAAoB;AAC3D,0BAAwB,UAAU;AAElC,QAAM,gBAAY,qBAA2C,oBAAI,IAAI,CAAC;AAGtE,QAAM,wBAAwB,kBAAkB,SAAS;AACzD,QAAM,gBAAe,0EAAuB,YAAvB,mBAAgC,iBAAhC,YAAgD;AAIrE,8BAAU,MAAM;AApNlB,QAAAC;AAqNI,QAAI;AACF,UAAI,MAAM,UAAU;AAClB,SAAAA,MAAA,WAAW,iBAAX,gBAAAA,IAAyB,QAAQ,uBAAuB,MAAM;AAAA,MAChE;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,MAAM,QAAQ,CAAC;AAGnB,8BAAU,MAAM;AA/NlB,QAAAA,KAAAC;AAgOI,QAAI;AACF,YAAM,gBACJA,OAAAD,MAAA,WAAW,iBAAX,gBAAAA,IAAyB,QAAQ,yBAAjC,OAAAC,MAAyD;AAC3D,UAAI,cAAc;AAChB,yBAAiB,CAAC,SAAU,iCAAK,OAAL,EAAW,QAAQ,aAAa,EAAE;AAAA,MAChE;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AA5OlB,QAAAD;AA6OI,QAAI;AACF,YAAM,OAAMA,MAAA,WAAW,iBAAX,gBAAAA,IAAyB,QAAQ;AAC7C,UAAI,KAAK;AACP,cAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,yBAAiB,CAAC,SAAU,iCAAK,OAAL,EAAW,cAAc,OAAO,EAAE;AAAA,MAChE;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AAzPlB,QAAAA,KAAAC;AA0PI,QAAI;AACF,UAAI,MAAM,QAAQ;AAChB,SAAAD,MAAA,WAAW,iBAAX,gBAAAA,IAAyB,QAAQ,qBAAqB,MAAM;AAAA,MAC9D,OAAO;AACL,SAAAC,MAAA,WAAW,iBAAX,gBAAAA,IAAyB,WAAW;AAAA,MACtC;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,CAAC;AAGjB,8BAAU,MAAM;AAtQlB,QAAAD,KAAAC;AAuQI,QAAI;AACF,YAAM,OAAO,MAAM;AACnB,UAAI,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AAChC,SAAAD,MAAA,WAAW,iBAAX,gBAAAA,IAAyB;AAAA,UACvB;AAAA,UACA,KAAK,UAAU,IAAI;AAAA;AAAA,MAEvB,OAAO;AACL,SAAAC,MAAA,WAAW,iBAAX,gBAAAA,IAAyB,WAAW;AAAA,MACtC;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,MAAM,YAAY,CAAC;AAGvB,8BAAU,MAAM;AACd,QAAI,CAAC,MAAM,SAAU;AACrB,UAAM,OAAO,SAAS,QAAQ;AAC9B,QAAI,OAAO,KAAK,IAAI,EAAE,WAAW,EAAG;AAEpC,UAAM,UAAkC,CAAC;AACzC,eAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AACpD,cAAQ,GAAG,0BAA0B,GAAG,QAAQ,EAAE,IAAI,MAAM;AAAA,IAC9D;AAEA,SAAK,cAAc,QAAQ,cAAc,MAAM,UAAU,OAAO,EAAE,MAAM,CAAC,QAAiB;AACxF,cAAQ,MAAM,wCAAwC,GAAG;AAAA,IAC3D,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,UAAU,MAAM,YAAY,CAAC;AAGvC,8BAAU,MAAM;AACd,UAAM,YAAY,YAAY;AAxSlC,UAAAD;AAySM,UAAI;AACF,cAAM,OAAO,MAAM,cAAc,QAAQ;AAAA,UACvC,aAAa;AAAA,UACb;AAAA,YACE,WAAW,aAAa;AAAA,YACxB,SAAQA,MAAA,SAAS,QAAQ,WAAjB,OAAAA,MAA2B;AAAA,UACrC;AAAA,QACF;AACA,cAAM,aAAa,cAAc,IAAI;AACrC,yBAAiB,CAAC,SAAU,iCACvB,OADuB;AAAA,UAE1B,gBAAgB;AAAA,UAChB;AAAA,QACF,EAAE;AAAA,MACJ,SAAS,OAAO;AACd,gBAAQ,MAAM,yBAAyB,KAAK;AAC5C,yBAAiB,CAAC,SAAU,iCACvB,OADuB;AAAA,UAE1B,gBAAgB,CAAC,SAAS;AAAA,UAC1B,YAAY;AAAA,QACd,EAAE;AAAA,MACJ;AAAA,IACF;AACA,SAAK,UAAU;AAAA,EACjB,GAAG,CAAC,MAAM,QAAQ,WAAW,SAAS,CAAC;AAGvC,8BAAU,MAAM;AACd,UAAM,cAAc,YAAY;AAC9B,UAAI;AACF,cAAM,SAAS,MAAM,cAAc,QAAQ;AAAA,UACzC,aAAa;AAAA,QACf;AACA,yBAAiB,CAAC,SAAM;AA1UhC,cAAAA;AA0UoC,kDACvB,OADuB;AAAA,YAE1B,iBAAiB;AAAA,YACjB,eAAcA,MAAA,OAAO,CAAC,MAAR,OAAAA,MAAa;AAAA,UAC7B;AAAA,SAAE;AAAA,MACJ,SAAS,OAAO;AACd,gBAAQ,MAAM,2BAA2B,KAAK;AAAA,MAChD;AAAA,IACF;AACA,SAAK,YAAY;AAAA,EACnB,GAAG,CAAC,CAAC;AAKL,QAAM,gBAAY,0BAAY,CAAC,WAA0B;AACvD,qBAAiB,CAAC,SAAS;AACzB,YAAM,OAAO,iCAAK,OAAL,EAAW,QAAQ,WAAW,KAAK,OAAO,OAAO;AAC9D,gBAAU,QAAQ,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;AAC1C,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAKL,QAAM,oBAAgB;AAAA,IACpB,OAAO,YAAqE;AAC1E,YAAM,WAAW,SAAS,QAAQ;AAClC,UAAI,CAAC,SAAU,OAAM,IAAI,MAAM,0BAA0B;AACzD,YAAM,EAAE,QAAQ,IAAI,MAAM,cAAc,QAAQ;AAAA,QAC9C;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,mBAAe,0BAAY,YAA2B;AAjX9D,QAAAA,KAAAC;AAkXI,UAAM,WAAW,SAAS,QAAQ;AAClC,QAAI,CAAC,SAAU;AACf,YAAMA,OAAAD,MAAA,cAAc,SAAQ,iBAAtB,gBAAAC,IAAA,KAAAD,KAAqC;AAAA,EAC7C,GAAG,CAAC,CAAC;AAKL,QAAM,qBAAiB;AAAA,IACrB,OAAO,UAAkB,QAAgB,UAAkC;AACzE,YAAM,UAAU,OAAO,KAAK;AAC5B,UAAI,CAAC,QAAS;AAEd,YAAM,QAA2B;AAAA,QAC/B,QAAQ;AAAA,QACR,WAAW,QAAQ,MAAM,GAAG,CAAC;AAAA,QAC7B;AAAA,MACF;AAEA,uBAAiB,CAAC,SAAS;AACzB,cAAM,OAAO,iCACR,OADQ;AAAA,UAEX,cAAc,iCAAK,KAAK,eAAV,EAAwB,CAAC,QAAQ,GAAG,MAAM;AAAA,QAC1D;AACA,kBAAU,QAAQ,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;AAC1C,eAAO;AAAA,MACT,CAAC;AAGD,YAAM,WAAW,SAAS,QAAQ;AAClC,UAAI,UAAU;AACZ,YAAI;AACF,gBAAM,cAAc,QAAQ,cAAc,UAAU;AAAA,YAClD,CAAC,GAAG,0BAA0B,GAAG,QAAQ,EAAE,GAAG;AAAA,UAChD,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,kBAAQ,MAAM,kCAAkC,GAAG;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,wBAAoB;AAAA,IACxB,OAAO,aAAoC;AACzC,YAAM,WAAW,SAAS,QAAQ;AAClC,UAAI,UAAU;AACZ,cAAM,cAAc,QAAQ;AAAA,UAC1B;AAAA,UACA,GAAG,0BAA0B,GAAG,QAAQ;AAAA,QAC1C;AAAA,MACF;AAEA,uBAAiB,CAAC,SAAS;AACzB,cAAmCA,MAAA,KAAK,cAA/B,EAxajB,CAwaiB,WAAW,EAxa5B,IAwa2CA,KAAT,iBAASA,KAAT,CAAjB;AACT,cAAM,OAAO,iCAAK,OAAL,EAAW,cAAc,KAAK;AAC3C,kBAAU,QAAQ,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;AAC1C,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,sBAAkB;AAAA,IACtB,MAAyC,SAAS,QAAQ;AAAA,IAC1D,CAAC;AAAA,EACH;AAEA,QAAM,qBAAiB;AAAA,IACrB,CAAC,aAA+B;AAC9B,YAAM,OAAO,SAAS,QAAQ;AAC9B,UAAI,SAAU,QAAO,YAAY;AACjC,aAAO,OAAO,KAAK,IAAI,EAAE,SAAS;AAAA,IACpC;AAAA,IACA,CAAC;AAAA,EACH;AAKA,QAAM,yBAAqB,0BAAY,YAA+B;AACpE,QAAI;AACF,YAAM,SAAS,MAAM,cAAc,QAAQ;AAAA,QACzC,aAAa;AAAA,MACf;AACA,uBAAiB,CAAC,SAAM;AAvc9B,YAAAA,KAAAC;AAuckC,gDACvB,OADuB;AAAA,UAE1B,iBAAiB;AAAA,UACjB,eAAcA,OAAAD,MAAA,KAAK,iBAAL,OAAAA,MAAqB,OAAO,CAAC,MAA7B,OAAAC,MAAkC;AAAA,QAClD;AAAA,OAAE;AACF,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,2BAA2B,KAAK;AAC9C,aAAO,CAAC;AAAA,IACV;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAoB,0BAAY,YAA+B;AAndvE,QAAAD;AAodI,QAAI;AACF,YAAM,OAAO,MAAM,cAAc,QAAQ;AAAA,QACvC,aAAa;AAAA,QACb;AAAA,UACE,WAAW,aAAa;AAAA,UACxB,SAAQA,MAAA,SAAS,QAAQ,WAAjB,OAAAA,MAA2B;AAAA,QACrC;AAAA,MACF;AACA,YAAM,aAAa,cAAc,IAAI;AACrC,uBAAiB,CAAC,SAAU,iCACvB,OADuB;AAAA,QAE1B,gBAAgB;AAAA,QAChB;AAAA,MACF,EAAE;AACF,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,uBAAiB,CAAC,SAAU,iCACvB,OADuB;AAAA,QAE1B,gBAAgB,CAAC,SAAS;AAAA,QAC1B,YAAY;AAAA,MACd,EAAE;AACF,aAAO,CAAC,SAAS;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,CAAC;AAKL,QAAM,8BAA0B,0BAAY,MAA0B;AAjfxE,QAAAA;AAkfI,UAAM,WAAW,qBAAqB,QAAQ,aAAa,OAAO;AAClE,YAAOA,MAAA,qCAAU,YAAV,OAAAA,MAAqB,kBAAkB;AAAA,EAChD,GAAG,CAAC,CAAC;AAEL,QAAM,0BAAsB,0BAAY,MAAc;AAtfxD,QAAAA,KAAAC,KAAA;AAufI,UAAM,kBACJA,OAAAD,MAAA,qBAAqB,QAAQ,aAAa,OAAO,MAAjD,gBAAAA,IAAoD,YAApD,OAAAC,MACA,kBAAkB;AACpB,YACE;AAAA,MACE,eAAe;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,SAAS,QAAQ;AAAA,IACnB,MAJA,YAIK;AAAA,EAET,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB,0BAAY,OAAO,UAAkB;AAngB7D,QAAAD,KAAAC,KAAA;AAogBI,UAAM,WAAW,aAAa;AAC9B,UAAM,kBACJA,OAAAD,MAAA,qBAAqB,QAAQ,QAAQ,MAArC,gBAAAA,IAAwC,YAAxC,OAAAC,MAAmD,kBAAkB;AACvE,UAAMC,gBAAe,eAAe;AAEpC,YAAQ,IAAI,0CAA0C;AAAA,MACpD;AAAA,MACA,cAAAA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAIA,eAAc;AAChB,cAAQ,KAAK,wDAAwD;AACrE;AAAA,IACF;AAEA,UAAM,OACJ;AAAA,MACE,eAAe;AAAA,MACf,SAAS,QAAQ;AAAA,MACjB,SAAS,QAAQ;AAAA,IACnB,MAJA,YAIK;AAEP,YAAQ,IAAI,qDAAqD;AAAA,MAC/D;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,4BAAwB,QAAQ,UAAU;AAAA,MACxC,SAAS,iCACJ,iBADI;AAAA,QAEP;AAAA,QACA;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,IACF,CAAC;AAED,YAAQ,IAAI,4DAA4D;AAAA,MACtE;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,cAAc;AAAA,IAC5B,CAAC;AAED,QAAI;AACF,YAAM,SAAS,MAAM,cAAc,QAAQ;AAAA,QACzC;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA,SAAQ,cAAS,QAAQ,WAAjB,YAA2B;AAAA,UACnC,WAAU,cAAS,QAAQ,aAAjB,YAA6B;AAAA,QACzC;AAAA,MACF;AACA,cAAQ,IAAI,kDAAkD,MAAM;AAAA,IACtE,SAAS,KAAK;AACZ,cAAQ,MAAM,sCAAsC,GAAG;AACvD,YAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAc,0BAAY,CAAC,QAAgB;AApkBnD,QAAAF,KAAAC;AAqkBI,UAAM,WAAW,aAAa;AAC9B,UAAM,kBACJA,OAAAD,MAAA,qBAAqB,QAAQ,QAAQ,MAArC,gBAAAA,IAAwC,YAAxC,OAAAC,MAAmD,kBAAkB;AACvE,UAAMC,gBAAe,eAAe;AAEpC,YAAQ,IAAI,wCAAwC;AAAA,MAClD;AAAA,MACA,cAAAA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAIA,eAAc;AAChB,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,QACE,SAAS,QAAQ,eAAe,SAAS,KACzC,CAAC,SAAS,QAAQ,eAAe,SAAS,GAAG,GAC7C;AACA,cAAQ,KAAK,oDAAoD,EAAE,IAAI,CAAC;AACxE;AAAA,IACF;AAEA,YAAQ,IAAI,mDAAmD;AAAA,MAC7D;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,4BAAwB,QAAQ,UAAU;AAAA,MACxC,SAAS,iCACJ,iBADI;AAAA,QAEP;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,IACF,CAAC;AAED,YAAQ,IAAI,gDAAgD;AAAA,EAC9D,GAAG,CAAC,CAAC;AAEL,QAAM,wBAAoB,0BAAY,MAAM;AAjnB9C,QAAAF,KAAAC;AAknBI,UAAM,WAAW,aAAa;AAC9B,UAAM,kBACJA,OAAAD,MAAA,qBAAqB,QAAQ,QAAQ,MAArC,gBAAAA,IAAwC,YAAxC,OAAAC,MAAmD,kBAAkB;AAEvE,QAAI,eAAe,cAAc;AAC/B,8BAAwB,QAAQ,UAAU;AAAA,QACxC,SAAS,iCACJ,iBADI;AAAA,UAEP,cAAc;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,CAAC;AAKL,QAAM,sBAAkB,0BAAY,MAAM,SAAS,SAAS,CAAC,CAAC;AAE9D,QAAM,2BAAuB;AAAA,IAC3B,CAAC,aAA4C;AAC3C,gBAAU,QAAQ,IAAI,QAAQ;AAC9B,aAAO,MAAM;AACX,kBAAU,QAAQ,OAAO,QAAQ;AAAA,MACnC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAKA,QAAM,eAAW;AAAA,IACf,CAAC,YAAoE;AAnpBzE,UAAAD;AAopBM,UAAI,YAAY,SAAS;AACvB,mBAAUA,MAAA,QAAQ,WAAR,OAAAA,MAAkB,IAAI;AAAA,MAClC;AACA,UACE,SAAS,WACT,QAAQ,QAAQ,UAChB,QAAQ,QAAQ,MAChB;AACA,oBAAY,QAAQ,GAAG;AAAA,MACzB;AAAA,IACF;AAAA,IACA,CAAC,WAAW,WAAW;AAAA,EACzB;AAEA,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;AG3rBA,IAAAG,gBAKO;AAuIH,IAAAC,sBAAA;AArGJ,IAAM,wBAAoB,6BAAmC,IAAI;AAM1D,SAAS,kBAAgC;AAC9C,QAAM,cAAU,0BAAW,iBAAiB;AAC5C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;AAuBO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,qBAAiB,sBAA0C,oBAAI,IAAI,CAAC;AAE1E,QAAM,gBAAY;AAAA,IAChB,CAAC,MAAc,aAA8B;AAC3C,YAAM,OAAO,eAAe;AAC5B,UAAI,CAAC,KAAK,IAAI,IAAI,GAAG;AACnB,aAAK,IAAI,MAAM,oBAAI,IAAI,CAAC;AAAA,MAC1B;AACA,WAAK,IAAI,IAAI,EAAG,IAAI,QAAQ;AAC5B,aAAO,MAAM;AA7FnB;AA8FQ,mBAAK,IAAI,IAAI,MAAb,mBAAgB,OAAO;AAAA,MACzB;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,oBAAgB,2BAAY,CAAC,UAAwB;AACzD,UAAM,OAAO,eAAe;AAG5B,UAAM,WAAW,KAAK,IAAI,MAAM,IAAI;AACpC,QAAI,UAAU;AACZ,iBAAW,MAAM,SAAU,IAAG,KAAK;AAAA,IACrC;AAGA,UAAM,eAAe,KAAK,IAAI,GAAG;AACjC,QAAI,cAAc;AAChB,iBAAW,MAAM,aAAc,IAAG,KAAK;AAAA,IACzC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAe;AAAA,IACnB,OAAO,UAAiE;AACtE,UAAI;AACF,cAAM,UAAU,KAAK,UAAU;AAAA,UAC7B,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,QACjB,CAAC;AACD,cAAM,WAAW,kBAAkB,MAAM,WAAW,OAAO;AAAA,MAC7D,SAAS,OAAO;AACd,gBAAQ,MAAM,kCAAkC,KAAK;AAAA,MACvD;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,eAA6B;AAAA,IACjC;AAAA,IACA,UAAU;AAAA,IACV,oBAAoB;AAAA;AAAA;AAAA;AAAA,IAIpB,WAAW;AAAA,EACb;AAEA,SACE,6CAAC,kBAAkB,UAAlB,EAA2B,OAAO,cAChC,UACH;AAEJ;;;AChJA,IAAAC,gBAMO;AA+FH,IAAAC,sBAAA;AA7DJ,IAAM,0BAAsB,6BAA6C,IAAI;AAMtE,SAAS,kBAA0C;AACxD,QAAM,cAAU,0BAAW,mBAAmB;AAC9C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMA,IAAI,wBAAwB;AAC5B,SAAS,aAAqB;AAC5B,SAAO,SAAS,KAAK,IAAI,CAAC,IAAI,EAAE,qBAAqB;AACvD;AAMO,SAAS,4BAA4B;AAAA,EAC1C;AACF,GAAqC;AACnC,QAAM,CAAC,eAAe,gBAAgB,QAAI,wBAAyB,CAAC,CAAC;AAErE,QAAM,uBAAmB,2BAAY,CAAC,WAA6B;AACjE,UAAM,KAAK,WAAW;AACtB,UAAM,eAA6B,iCAC9B,SAD8B;AAAA,MAEjC;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB;AACA,qBAAiB,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC;AAClD,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,0BAAsB,2BAAY,CAAC,OAAe;AACtD,qBAAiB,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,EAC5D,GAAG,CAAC,CAAC;AAEL,QAAM,eAAW,2BAAY,MAAM;AACjC,qBAAiB,CAAC,CAAC;AAAA,EACrB,GAAG,CAAC,CAAC;AAEL,QAAM,QAAgC;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SACE,6CAAC,oBAAoB,UAApB,EAA6B,OAC3B,UACH;AAEJ;;;ACzGA,IAAAC,gBAMO;AA+DH,IAAAC,sBAAA;AA7BJ,IAAM,yBAAqB,6BAAoC,IAAI;AAE5D,SAAS,mBAAkC;AAChD,QAAM,cAAU,0BAAW,kBAAkB;AAC7C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAA+B;AAC7B,QAAM,eAAW,sBAA2B,IAAI;AAChD,MAAI,CAAC,SAAS,SAAS;AACrB,aAAS,UAAU,IAAI,YAAY,EAAE,gBAAgB,CAAC;AAAA,EACxD;AACA,QAAM,QAAQ,SAAS;AACvB,QAAM,YAAQ;AAAA,IACZ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,SACE,6CAAC,mBAAmB,UAAnB,EAA4B,OAC1B,UACH;AAEJ;AAEO,SAAS,2BAAgD;AAC9D,QAAM,EAAE,iBAAiB,kBAAkB,IAAI,iBAAiB;AAChE,aAAO;AAAA,IACL,MAAM,kBAAkB,eAAe;AAAA,IACvC,CAAC,iBAAiB,iBAAiB;AAAA,EACrC;AACF;AAEO,SAAS,2BAAuD;AACrE,QAAM,EAAE,iBAAiB,kBAAkB,IAAI,iBAAiB;AAChE,aAAO;AAAA,IACL,MAAM,kBAAkB,eAAe;AAAA,IACvC,CAAC,iBAAiB,iBAAiB;AAAA,EACrC;AACF;;;ACzFA,IAAAC,gBAOO;AAyHH,IAAAC,sBAAA;AAtGJ,IAAM,kBAAc,6BAA4C,MAAS;AAElE,SAAS,UAAU;AACxB,QAAM,cAAU,0BAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,aAAa,QAAQ;AAAA,IACrB,gBAAgB,QAAQ;AAAA,IACxB,cAAc,QAAQ;AAAA,IACtB,mBAAmB,QAAQ;AAAA,EAC7B;AACF;AAIO,SAAS,oBAAoB,EAAE,SAAS,GAA4B;AACzE,QAAM,CAAC,MAAM,YAAY,QAAI,wBAAoB;AAAA,IAC/C,aAAa;AAAA,IACb,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,KAAK;AAAA,EACP,CAAC;AAGD,QAAM,cAAU,sBAAO,IAAI;AAC3B,UAAQ,UAAU;AAGlB,QAAM,2BAAuB;AAAA,IAC3B,oBAAI,IAAI;AAAA,EACV;AAEA,QAAM,cAAU,2BAAY,CAAC,SAA6B;AACxD,iBAAa,CAAC,SAAS;AACrB,YAAM,OAAO,kCAAK,OAAS;AAG3B,2BAAqB,QAAQ,QAAQ,CAAC,aAAa;AACjD,iBAAS,IAAI;AAAA,MACf,CAAC;AAED,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAc,2BAAY,CAAC,KAAa,UAAmB;AAC/D,iBAAa,CAAC,SAAS;AAhF3B;AAiFM,YAAM,OAAO,iCACR,OADQ;AAAA,QAEX,KAAK,kCACC,UAAK,QAAL,YAAY,CAAC,IADd;AAAA,UAEH,CAAC,GAAG,GAAG;AAAA,QACT;AAAA,MACF;AACA,2BAAqB,QAAQ,QAAQ,CAAC,aAAa;AACjD,iBAAS,IAAI;AAAA,MACf,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAiB,2BAAY,CAAC,QAAgB;AAClD,iBAAa,CAAC,SAAS;AACrB,UAAI,CAAC,KAAK,OAAO,EAAE,OAAO,KAAK,MAAM;AACnC,eAAO;AAAA,MACT;AACA,YAAM,UAAU,mBAAK,KAAK;AAC1B,aAAO,QAAQ,GAAG;AAClB,YAAM,OAAO,iCACR,OADQ;AAAA,QAEX,KAAK,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AAAA,MACnD;AACA,2BAAqB,QAAQ,QAAQ,CAAC,aAAa;AACjD,iBAAS,IAAI;AAAA,MACf,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAGL,QAAM,mBAAe,2BAAY,MAAM,QAAQ,SAAS,CAAC,CAAC;AAG1D,QAAM,wBAAoB;AAAA,IACxB,CAAC,aAAwC;AACvC,2BAAqB,QAAQ,IAAI,QAAQ;AAGzC,aAAO,MAAM;AACX,6BAAqB,QAAQ,OAAO,QAAQ;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SACE;AAAA,IAAC,YAAY;AAAA,IAAZ;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;;;AC7IA,IAAAC,gBAAwD;AAExD,IAAAA,iBAIO;;;ACLP,IAAAC,gBAAyD;;;ACEzD,oBAA8D;AAEvD,IAAM,iBAAN,MAAqB;AAAA,EAG1B,YACmB,eACjB;AADiB;AAHnB,SAAQ,WAAW,oBAAI,IAA2B;AAAA,EAI/C;AAAA,EAEH,YAAY,UAAkB,MAAwD;AACpF,QAAI,UAAU,KAAK,SAAS,IAAI,QAAQ;AACxC,QAAI,QAAS,QAAO;AAEpB,cAAU,IAAI,cAAAC,QAAc,KAAK,cAAc,GAAG,iCAC7C,OAD6C;AAAA,MAEhD,WAAW;AAAA,IACb,EAAC;AACD,SAAK,SAAS,IAAI,UAAU,OAAO;AACnC,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,UAA6C;AAC/C,WAAO,KAAK,SAAS,IAAI,QAAQ;AAAA,EACnC;AAAA,EAEA,MAAM,UAAwB;AAC5B,UAAM,UAAU,KAAK,SAAS,IAAI,QAAQ;AAC1C,QAAI,SAAS;AACX,cAAQ,MAAM;AACd,WAAK,SAAS,OAAO,QAAQ;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,WAAiB;AACf,eAAW,CAAC,UAAU,OAAO,KAAK,KAAK,UAAU;AAC/C,cAAQ,MAAM;AAAA,IAChB;AACA,SAAK,SAAS,MAAM;AAAA,EACtB;AACF;;;ACvCA,kBAAsC;AACtC,4BAAwB;AAMjB,SAAS,MAAM,QAAsB;AAC1C,aAAO,mCAAQ,kBAAK,MAAM,CAAC;AAC7B;AAIO,IAAM,iBAAiB,CAAC,UAA4B;AACzD,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,SAAS,KAAK,IAAK,QAAQ,OAAO,QAAQ,MAAO,QAAS;AAAA,EAC1E;AAEA,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,CAAC,OAAO,MAAM,OAAO,GAAG;AAC1B,WAAO,UAAU,OAAO,UAAU,MAAO;AAAA,EAC3C;AAEA,QAAM,KAAK,KAAK,MAAM,KAAK;AAC3B,SAAO,OAAO,MAAM,EAAE,IAAI,IAAI;AAChC;AAEO,IAAM,qBAAqB,CAAC,UAAmB;AAjCtD;AAkCE,QAAM,cAAa,oCAAO,WAAP,YAAiB;AACpC,SAAO,CAAC,cAAc,WAAW,WAAW,IAAI;AAClD;AASO,SAAS,iBAAiB,KAA4C;AA7C7E;AA8CE,MAAI,IAAI,WAAW,SAAU,QAAO;AAEpC,QAAM,UAAgC,CAAC;AACvC,QAAM,OACJ,IAAI,WAAW,SAAS,SAAS;AAEnC,MAAI,IAAI,SAAS;AACf,YAAQ,KAAK,EAAE,MAAM,QAAiB,MAAM,IAAI,QAAQ,CAAC;AAAA,EAC3D;AAEA,QAAM,CAAC,OAAO,WAAW,KAAI,sBAAiB,GAAG,MAApB,YAAyB,CAAC;AACvD,MAAI,SAAS,aAAa;AACxB,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,YAAY,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC9B,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,MAAM;AACb,YAAI;AACF,iBAAO,KAAK,MAAM,WAAW;AAAA,QAC/B,SAAQ;AACN,iBAAO,EAAE,MAAM,YAAY;AAAA,QAC7B;AAAA,MACF,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAEA,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA,SAAU,QAAQ,SAAS,IACvB,UACA,CAAC,EAAE,MAAM,QAAiB,MAAM,GAAG,CAAC;AAAA,KACpC,IAAI,aAAa,EAAE,WAAW,IAAI,KAAK,IAAI,SAAS,EAAE;AAG5D,SAAO;AACT;AAEA,SAAS,iBAAiB,KAA2C;AACnE,SAAO,gBAAgB,IAAI,WAAW;AACxC;AAYA,SAAS,gBACP,YACyB;AACzB,MAAI,CAAC,WAAY,QAAO;AAExB,MAAI,MAAM,QAAQ,UAAU,KAAK,WAAW,WAAW,GAAG;AACxD,UAAM,CAAC,OAAO,OAAO,IAAI;AACzB,WAAO,CAAC,OAAO,KAAK,GAAG,OAAO,4BAAW,EAAE,CAAC;AAAA,EAC9C;AAEA,SAAO;AACT;AAiBO,IAAM,iBAAiB,CAC5B,YACW;AACX,MAAI,YAAY,OAAW,QAAO;AAClC,QAAM,KAAK,OAAO,YAAY,WAAW,OAAO,OAAO,IAAI;AAC3D,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,IAAM,gBAAgB,CAAC,SAC5B,OAAO,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC,KAAK;AAQ9C,IAAM,mBAAgC;AAAA,EAC3C,EAAE,IAAI,GAAG,MAAM,YAAY,QAAQ,MAAM;AAAA,EACzC,EAAE,IAAI,KAAK,MAAM,WAAW,QAAQ,QAAQ;AAAA,EAC5C,EAAE,IAAI,OAAO,MAAM,YAAY,QAAQ,MAAM;AAAA,EAC7C,EAAE,IAAI,MAAM,MAAM,QAAQ,QAAQ,OAAO;AAAA,EACzC,EAAE,IAAI,IAAI,MAAM,YAAY,QAAQ,KAAK;AAAA,EACzC,EAAE,IAAI,UAAU,MAAM,WAAW,QAAQ,MAAM;AACjD;AAGO,IAAM,eAAe,CAC1B,YAEA,YAAY,SACR,SACA,iBAAiB,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;;;AFtJ5C,SAAS,uBACd,YACA,SACA;AACA,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,uBAAmB,sBAAsB,aAAa;AAC5D,mBAAiB,UAAU;AAC3B,QAAM,oBAAgB,sBAAO,UAAU;AACvC,gBAAc,UAAU;AAExB,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,KAAK;AAEhD,QAAM,wBAAoB,sBAA8B,IAAI;AAC5D,MAAI,CAAC,kBAAkB,SAAS;AAC9B,sBAAkB,UAAU,IAAI,eAAe,MAAM,cAAc,OAAO;AAAA,EAC5E;AAEA,QAAM,qBAAiB,sBAAoB,oBAAI,IAAI,CAAC;AAEpD,QAAM,uBAAmB,sBAAgC,oBAAI,IAAI,CAAC;AAGlE,QAAM,iBAAa;AAAA,IACjB,CAAC,aAAoC;AArDzC;AAsDM,YAAM,UAAU,kBAAkB;AAClC,YAAM,WAAW,QAAQ,IAAI,QAAQ;AACrC,UAAI,SAAU,QAAO;AAErB,YAAM,UAAU,QAAQ,YAAY,UAAU;AAAA,QAC5C,KAAK,QAAQ,OAAO;AAAA,QACpB,YAAW,aAAQ,iBAAR;AAAA,QACX,SAAQ,mBAAQ,cAAR,iDAAyB;AAAA,QACjC,WAAU,aAAQ,gBAAR;AAAA,QACV,YAAW,aAAQ,iBAAR;AAAA,MACb,CAAC;AAGD,YAAM,WAA8B,CAAC;AAGrC,eAAS;AAAA,QACP,QAAQ,GAAG,YAAY,CAAC,SAAS;AAC/B,gBAAM,iBAAsC,CAAC;AAC7C,qBAAW,OAAO,MAAM;AACtB,kBAAM,YAAY,iBAAiB,GAAG;AACtC,gBAAI,UAAW,gBAAe,KAAK,SAAS;AAAA,UAC9C;AACA,2BAAiB,QAAQ,kBAAkB,UAAU,cAAc;AAAA,QACrE,CAAC;AAAA,MACH;AAGA,eAAS;AAAA,QACP,QAAQ,GAAG,oBAAoB,MAAM;AACnC,cAAI,iBAAiB,QAAQ,oBAAoB,UAAU;AACzD,yBAAa,IAAI;AAAA,UACnB;AAAA,QACF,CAAC;AAAA,MACH;AACA,eAAS;AAAA,QACP,QAAQ,GAAG,kBAAkB,MAAM;AACjC,cAAI,iBAAiB,QAAQ,oBAAoB,UAAU;AACzD,yBAAa,KAAK;AAAA,UACpB;AAAA,QACF,CAAC;AAAA,MACH;AAGA,eAAS;AAAA,QACP,QAAQ,GAAG,qBAAqB,CAAC,QAAK;AAnG9C,cAAAC;AAmGiD,kBAAAA,MAAA,QAAQ,oBAAR,gBAAAA,IAAA,cAA0B;AAAA,SAAI;AAAA,MACzE;AACA,eAAS;AAAA,QACP,QAAQ,GAAG,yBAAyB,CAAC,QAAK;AAtGlD,cAAAA;AAsGqD,kBAAAA,MAAA,QAAQ,oBAAR,gBAAAA,IAAA,cAA0B;AAAA,SAAI;AAAA,MAC7E;AAGA,eAAS;AAAA,QACP,QAAQ,GAAG,iBAAiB,CAAC,EAAE,MAAM,MAAM;AACzC,2BAAiB,QAAQ,qBAAqB,UAAU,EAAE,MAAM,CAAC;AAAA,QACnE,CAAC;AAAA,MACH;AAGA,YAAM,eAAe,CAAC,SACpB,QAAQ,GAAG,MAA2D,CAAC,YAAqB;AAlHpG,YAAAA;AAmHU,SAAAA,MAAA,QAAQ,YAAR,gBAAAA,IAAA,cAAkB,EAAE,MAAM,SAAS,WAAW,SAAS;AAAA,MACzD,CAAC;AAEH,eAAS,KAAK,aAAa,aAAa,CAAC;AACzC,eAAS,KAAK,aAAa,eAAe,CAAC;AAC3C,eAAS,KAAK,aAAa,eAAe,CAAC;AAC3C,eAAS,KAAK,aAAa,cAAc,CAAC;AAC1C,eAAS,KAAK,aAAa,gBAAgB,CAAC;AAE5C,uBAAiB,QAAQ,IAAI,UAAU,MAAM;AAC3C,mBAAW,WAAW,SAAU,SAAQ;AAAA,MAC1C,CAAC;AAED,aAAO;AAAA,IACT;AAAA;AAAA,IAEA,CAAC;AAAA,EACH;AAEA,QAAM,yBAAqB;AAAA,IACzB,OAAO,aAAqB;AAvIhC;AAwIM,UAAI,eAAe,QAAQ,IAAI,QAAQ,EAAG;AAC1C,qBAAe,QAAQ,IAAI,QAAQ;AAEnC,UAAI;AACF,cAAM,UAAU,WAAW,QAAQ;AAEnC,cAAM,aAAY,aAAQ,iBAAR;AAClB,YAAI,UAAW,SAAQ,iBAAiB,SAAS;AACjD,cAAM,QAAQ,kBAAkB;AAEhC,YAAI,iBAAiB,QAAQ,oBAAoB,UAAU;AACzD,uBAAa,QAAQ,gBAAgB,CAAC;AAAA,QACxC;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,kCAAkC,KAAK;AACrD,YAAI,iBAAiB,QAAQ,oBAAoB,UAAU;AACzD,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF,UAAE;AACA,uBAAe,QAAQ,OAAO,QAAQ;AAAA,MACxC;AAAA,IACF;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAGA,QAAM,kBAAc;AAAA,IAClB,OAAO,MAAc,aAAqB;AAnK9C;AAoKM,YAAM,UAAU,WAAW,QAAQ;AACnC,YAAM,aAAY,aAAQ,iBAAR;AAClB,UAAI,UAAW,SAAQ,iBAAiB,SAAS;AAGjD,YAAM,mBAAmB,iBAAiB,QAAQ,kBAAkB,QAAQ;AAC5E,YAAM,cAAiC;AAAA,QACrC,MAAM;AAAA,QACN,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,QAChC,WAAW,oBAAI,KAAK;AAAA,MACtB;AACA,uBAAiB,QAAQ,kBAAkB,UAAU;AAAA,QACnD,GAAG;AAAA,QACH;AAAA,MACF,CAAC;AACD,uBAAiB,QAAQ,qBAAqB,UAAU;AAAA,QACtD,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,MACvC,CAAC;AAED,YAAM,QAAQ,UAAU,IAAI;AAAA,IAC9B;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAGA,QAAM,uBAAmB;AAAA,IACvB,OAAO,aAAqB;AA9LhC;AA+LM,YAAM,WAAU,uBAAkB,YAAlB,mBAA2B,IAAI;AAC/C,UAAI,SAAS;AACX,cAAM,QAAQ,UAAU;AAAA,MAC1B;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACH;AAGA,+BAAU,MAAM;AACd,WAAO,MAAM;AAzMjB;AA0MM,8BAAkB,YAAlB,mBAA2B;AAC3B,iBAAW,WAAW,iBAAiB,QAAQ,OAAO,GAAG;AACvD,gBAAQ;AAAA,MACV;AACA,uBAAiB,QAAQ,MAAM;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,gBAAgB,kBAAkB;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AG9MA,IAAM,uBAAuB,CAC3B,CAAC,EAAE,KAAK,GACR,CAAC,EAAE,KAAK,MACL;AACH,QAAM,MAAM,eAAe,MAAM,YAAY;AAC7C,QAAM,MAAM,eAAe,MAAM,YAAY;AAC7C,SAAO,MAAM;AACf;AAEA,SAAS,iBAAiB,gBAA6C;AACrE,QAAM,UAAU,MAAM,KAAK,eAAe,QAAQ,CAAC,EAAE;AAAA,IACnD,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,mBAAmB,KAAK,KAAK;AAAA,EAC9C;AAEA,QAAM,iBAAiB,QACpB,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,KAAK,WAAW,UAAU,EAC/C,KAAK,oBAAoB,EACzB;AAAA,IACC,CAAC,CAAC,IAAI,IAAI,OAA2C;AAAA,MACnD;AAAA,MACA,OAAO,KAAK,SAAS;AAAA,MACrB,QAAQ;AAAA,IACV;AAAA,EACF;AAEF,QAAM,kBAAkB,QACrB,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,KAAK,WAAW,UAAU,EAC/C,KAAK,oBAAoB,EACzB;AAAA,IACC,CAAC,CAAC,IAAI,IAAI,OAA4C;AAAA,MACpD;AAAA,MACA,OAAO,KAAK,SAAS;AAAA,MACrB,QAAQ;AAAA,IACV;AAAA,EACF;AAEF,SAAO,EAAE,gBAAgB,gBAAgB;AAC3C;AAYO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,EAAE,gBAAgB,gBAAgB,IAAI;AAAA,IAC1C,cAAc;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,UAAU,cAAc;AAAA,IACxB,SAAS;AAAA,IACT;AAAA,IAEA,qBAAqB,MAAM;AACzB,YAAM,WAAW,aAAa;AAC9B,oBAAc;AAAA,QAAkB,CAAC,SAC/B,IAAI,IAAI,IAAI,EAAE,IAAI,UAAU;AAAA,UAC1B,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,UACrC,SAAS,kBAAkB;AAAA,QAC7B,CAAC;AAAA,MACH;AACA,oBAAc,kBAAkB,UAAU,CAAC,CAAC;AAC5C,oBAAc,mBAAmB,QAAQ;AACzC,mBAAa,KAAK;AAClB,oBAAc,kBAAkB;AAAA,IAClC;AAAA,IAEA,kBAAkB,CAAC,aAAqB;AACtC,oBAAc,mBAAmB,QAAQ;AACzC,oBAAc,kBAAkB;AAAA,IAClC;AAAA,IAEA,UAAU,OAAO,UAAkB,aAAqB;AAlG5D;AAmGM,YAAM,iBACJ,yBAAc,kBAAkB,QAAQ,MAAxC,mBAA2C,UAA3C,YAAoD;AACtD,YAAM,kBAAkB,mBAAmB,QAAQ,IAAI,KAAK;AAC5D,oBAAc,qBAAqB,UAAU;AAAA,QAC3C,OAAO;AAAA,MACT,CAAC;AAED,UAAI;AACF,cAAM,cAAc,QAAQ,aAAa,UAAU,QAAQ;AAAA,MAC7D,SAAS,OAAO;AACd,gBAAQ,MAAM,4BAA4B,KAAK;AAC/C,sBAAc,qBAAqB,UAAU;AAAA,UAC3C,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,WAAW,OAAO,aAAqB;AACrC,oBAAc,qBAAqB,UAAU,EAAE,QAAQ,WAAW,CAAC;AAEnE,UAAI;AACF,cAAM,cAAc,QAAQ,cAAc,QAAQ;AAAA,MACpD,SAAS,OAAO;AACd,gBAAQ,MAAM,6BAA6B,KAAK;AAChD,sBAAc,qBAAqB,UAAU,EAAE,QAAQ,UAAU,CAAC;AAAA,MACpE;AAAA,IACF;AAAA,IAEA,aAAa,OAAO,aAAqB;AACvC,oBAAc,qBAAqB,UAAU,EAAE,QAAQ,UAAU,CAAC;AAElE,UAAI;AACF,cAAM,cAAc,QAAQ,gBAAgB,QAAQ;AAAA,MACtD,SAAS,OAAO;AACd,gBAAQ,MAAM,+BAA+B,KAAK;AAClD,sBAAc,qBAAqB,UAAU,EAAE,QAAQ,WAAW,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,UAAU,OAAO,aAAqB;AACpC,UAAI;AACF,cAAM,cAAc,QAAQ,aAAa,QAAQ;AAEjD,sBAAc,kBAAkB,CAAC,SAAS;AACxC,gBAAM,OAAO,IAAI,IAAI,IAAI;AACzB,eAAK,OAAO,QAAQ;AACpB,iBAAO;AAAA,QACT,CAAC;AACD,sBAAc,WAAW,CAAC,SAAS;AACjC,gBAAM,OAAO,IAAI,IAAI,IAAI;AACzB,eAAK,OAAO,QAAQ;AACpB,iBAAO;AAAA,QACT,CAAC;AAED,YAAI,cAAc,oBAAoB,UAAU;AAC9C,gBAAM,qBAAqB,MAAM;AAAA,YAC/B,cAAc,mBAAmB,QAAQ;AAAA,UAC3C,EAAE,KAAK,CAAC,CAAC,IAAI,IAAI,MAAM,KAAK,WAAW,aAAa,OAAO,QAAQ;AAEnE,cAAI,oBAAoB;AACtB,0BAAc,mBAAmB,mBAAmB,CAAC,CAAC;AAAA,UACxD,OAAO;AACL,kBAAM,YAAY;AAClB,0BAAc;AAAA,cAAkB,CAAC,SAC/B,IAAI,IAAI,IAAI,EAAE,IAAI,WAAW;AAAA,gBAC3B,OAAO;AAAA,gBACP,QAAQ;AAAA,gBACR,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,gBACrC,SAAS,kBAAkB;AAAA,cAC7B,CAAC;AAAA,YACH;AACA,0BAAc,kBAAkB,WAAW,CAAC,CAAC;AAC7C,0BAAc,mBAAmB,SAAS;AAAA,UAC5C;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,4BAA4B,KAAK;AAC/C,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;;;AClLA,IAAAC,gBAA0C;AAgH1C,IAAM,yBAAqB,6BAAqC,IAAI;AAE7D,IAAM,yBAAyB,mBAAmB;AAkClD,SAAS,iBAAiC;AAC/C,QAAM,cAAU,0BAAW,kBAAkB;AAC7C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;;;AC7JA,IAAAC,gBAA8C;AAoCvC,SAAS,iBAAiB;AAAA,EAC/B;AACF,GAA0C;AACxC,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,wBAA0B,CAAC,CAAC;AAC1E,QAAM,kBAAc,sBAAwB,CAAC,CAAC;AAE9C,QAAM,qBAAiB,2BAAY,CAAC,YAA2B;AAC7D,gBAAY,UAAU,CAAC,GAAG,YAAY,SAAS,OAAO;AACtD,uBAAmB,YAAY,OAAO;AAAA,EACxC,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAiB;AAAA,IACrB,CAAC,IAAY,WAAgC;AAC3C,YAAM,UAAU,WAAW;AAC3B,UAAI,CAAC,SAAS;AACZ,gBAAQ,MAAM,0DAA0D;AACxE;AAAA,MACF;AAEA,kBAAY,UAAU,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AACnE,yBAAmB,YAAY,OAAO;AAEtC,WAAK,QAAQ,QAAQ,IAAI,MAAM,EAAE,MAAM,CAAC,QAAQ;AAC9C,gBAAQ,MAAM,+CAA+C,GAAG;AAAA,MAClE,CAAC;AAAA,IACH;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,QAAM,oBAAgB;AAAA,IACpB,CAAC,IAAY,UAAmB;AAC9B,YAAM,UAAU,WAAW;AAC3B,UAAI,CAAC,SAAS;AACZ,gBAAQ,MAAM,yDAAyD;AACvE;AAAA,MACF;AAEA,kBAAY,UAAU,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AACnE,yBAAmB,YAAY,OAAO;AAEtC,WAAK,QAAQ,OAAO,IAAI,KAAK,EAAE,MAAM,CAAC,QAAQ;AAC5C,gBAAQ,MAAM,8CAA8C,GAAG;AAAA,MACjE,CAAC;AAAA,IACH;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AN6XM,IAAAC,sBAAA;AApbC,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AACF,GAAmC;AACjC,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,eAAe,gBAAgB;AACrC,QAAM,sBAAsB,gBAAgB;AAC5C,QAAM,EAAE,MAAM,mBAAmB,aAAa,IAAI,QAAQ;AAC1D,QAAM,EAAE,iBAAiB,qBAAqB,aAAa,IAAI,WAAW;AAK1E,QAAM,wBAAoB,sBAA2E,IAAI;AAEzG,QAAM,gBAAgB,iBAAiB;AAAA,IACrC,YAAY,MAAG;AApDnB;AAoDsB,qCAAkB,YAAlB,mBAA2B,IAAI,cAAc;AAAA;AAAA,EACjE,CAAC;AAKD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB;AAAA,EACF,IAAI,uBAAuB,YAAY;AAAA,IACrC,cAAc,MAAM,aAAa,EAAE;AAAA,IACnC;AAAA,IACA,QAAQ;AAAA,IACR,WAAW,MAAM,gBAAgB,EAAE;AAAA,IACnC,aAAa,MAAG;AAxEpB;AAwEuB,mCAAgB,EAAE,aAAlB,YAA8B;AAAA;AAAA,IACjD,iBAAiB,CAAC,YAAY,cAAc,eAAe,OAAO;AAAA,IAClE,SAAS,CAAC,UAAU,aAAa,SAAS,KAAK;AAAA,EACjD,CAAC;AAED,oBAAkB,UAAU;AAK5B,QAAM,qBAAiB;AAAA,IACrB,CAAC,cAA+C;AAAA,MAC9C,SAAS,SAAS;AAAA,MAClB,SAAS,SAAS;AAAA,MAClB,aAAa,SAAS;AAAA,MACtB,SAAS,SAAS;AAAA,IACpB;AAAA,IACA,CAAC,YAAY;AAAA,EACf;AAEA,QAAM,yBAAqB,sBAAO,eAAe,aAAa,CAAC,CAAC;AAEhE,+BAAU,MAAM;AACd,uBAAmB,UAAU,eAAe,aAAa,CAAC;AAE1D,UAAM,cAAc,kBAAkB,OAAO,YAAY;AACvD,YAAM,kBAAkB,eAAe,OAAO;AAC9C,YAAM,kBAAkB,mBAAmB;AAC3C,UACE,gBAAgB,YAAY,gBAAgB,WAC5C,gBAAgB,YAAY,gBAAgB,WAC5C,gBAAgB,gBAAgB,gBAAgB,eAChD,gBAAgB,YAAY,gBAAgB,SAC5C;AACA;AAAA,MACF;AAEA,yBAAmB,UAAU;AAC7B,YAAM,YAAY,cAAc;AAChC,YAAM,UAAU,KAAK,UAAU;AAAA,QAC7B,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AACD,YAAM,cAAc,QAAQ,kBAAkB,WAAW,OAAO;AAAA,IAClE,CAAC;AAED,WAAO;AAAA,EACT,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,uBAAmB,sBAAO,aAAa;AAC7C,mBAAiB,UAAU;AAE3B,QAAM,yBAAqB,sBAAO,cAAc,eAAe;AAC/D,+BAAU,MAAM;AACd,uBAAmB,UAAU,cAAc;AAAA,EAC7C,GAAG,CAAC,cAAc,eAAe,CAAC;AAKlC,+BAAU,MAAM;AACd,UAAM,cAAc,aAAa;AAAA,MAC/B;AAAA,MACA,MAAM;AACJ,qBAAa,mBAAmB;AAAA,UAC9B,MAAM;AAAA,UACN,WAAW,cAAc;AAAA,UACzB,SAAS,aAAa;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,cAAc,cAAc,iBAAiB,YAAY,CAAC;AAK9D,+BAAU,MAAM;AACd,SAAK,mBAAmB,cAAc,eAAe;AAAA,EACvD,GAAG,CAAC,oBAAoB,cAAc,eAAe,CAAC;AAGtD,+BAAU,MAAM;AACd,UAAM,WAAW,cAAc;AAC/B,UAAM,cAAc,cAAc,kBAAkB,QAAQ;AAC5D,QAAI,eAAe,YAAY,QAAQ,iBAAiB,WAAW;AACjE,oBAAc,qBAAqB,UAAU;AAAA,QAC3C,SAAS,iCACJ,YAAY,UADR;AAAA,UAEP,cAAc;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,CAAC;AAE7B,QAAM,kBAAkB,cAAc;AAAA,IACpC,cAAc;AAAA,EAChB;AAKA,+BAAU,MAAM;AACd,UAAM,cAAc,KAAK;AACzB,QAAI,CAAC,YAAa;AAElB,UAAM,kBAAkB,YAAY;AA3LxC;AA4LM,UAAI;AACF,cAAM,aACJ,MAAM,cAAc,QAAQ,YAAY,WAAW;AACrD,cAAM,iBAAiB,iBAAiB;AACxC,cAAM,cAAc,IAAI,IAAI,eAAe,kBAAkB;AAC7D,YAAI,aAAa,eAAe;AAEhC,mBAAW,UAAU,YAAY;AAC/B,gBAAM,YAAW,YAAO,UAAP,YAAgB;AACjC,gBAAM,QAAQ,mBAAmB,QAAQ,IAAI,KAAK;AAClD,gBAAM,eACJ,iBAAY,IAAI,OAAO,UAAU,MAAjC,mBAAoC,kBACpC,oBAAI,KAAK,GAAE,YAAY;AACzB,gBAAM,mBAAkB,iBAAY,IAAI,OAAO,UAAU,MAAjC,mBAAoC;AAC5D,sBAAY,IAAI,OAAO,YAAY;AAAA,YACjC;AAAA,YACA,QAAQ,OAAO,cAAc,aAAa;AAAA,YAC1C,cAAc;AAAA,YACd,SAAS,4CAAmB,kBAAkB;AAAA,UAChD,CAAC;AAED,gBAAM,QAAQ,MAAM,MAAM,cAAc;AACxC,cAAI,OAAO;AACT,kBAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AACjC,gBAAI,MAAM,YAAY;AACpB,2BAAa;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAEA,uBAAe,kBAAkB,WAAW;AAC5C,YAAI,aAAa,eAAe,WAAW;AACzC,yBAAe,aAAa,UAAU;AAAA,QACxC;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,gCAAgC,KAAK;AAAA,MACrD;AAAA,IACF;AAEA,SAAK,gBAAgB;AAAA,EACvB,GAAG,CAAC,KAAK,SAAS,aAAa,CAAC;AAKhC,QAAM,wBAAoB;AAAA,IACxB,MACE,uBAAuB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,IAChB;AAAA,EACF;AAKA,+BAAU,MAAM;AACd,UAAM,uBACJ,CAAC,cACD,CAAC,UAAiC;AAChC,YAAM,UAAU,MAAM;AACtB,YAAM,WACJ,QAAO,mCAAS,eAAc,WAC1B,QAAQ,YACR;AACN,YAAM,QAAQ,WACV,GAAG,cAAc,gBAAgB,gBAAgB,eAAe,KAAK,QAAQ,KAC7E,cAAc,gBACZ,gBACA;AACN,YAAM,UACJ,QAAO,mCAAS,aAAY,WACxB,QAAQ,UACR,QAAO,mCAAS,YAAW,WACzB,QAAQ,SACR;AAER,0BAAoB,iBAAiB;AAAA,QACnC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEF,UAAM,oBAAoB,aAAa;AAAA,MACrC;AAAA,MACA,qBAAqB,aAAa;AAAA,IACpC;AACA,UAAM,sBAAsB,aAAa;AAAA,MACvC;AAAA,MACA,qBAAqB,eAAe;AAAA,IACtC;AAEA,WAAO,MAAM;AACX,wBAAkB;AAClB,0BAAoB;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,cAAc,mBAAmB,CAAC;AAKtC,+BAAU,MAAM;AACd,UAAM,cAAc,aAAa,UAAU,iBAAiB,CAAC,WAAW;AAAA,IAExE,CAAC;AAED,WAAO;AAAA,EACT,GAAG,CAAC,cAAc,mBAAmB,CAAC;AAKtC,QAAM,cAAU,wCAAwB;AAAA,IACtC,UAAU;AAAA,IACV,aAAa,CAAC,SACZ,cAAc,kBAAkB,cAAc,iBAAiB,CAAC,GAAG,IAAI,CAAC;AAAA,IAC1E;AAAA,IACA,OAAO,OAAO,YAA2B;AACvC,YAAM,OAAO,QAAQ,QAClB;AAAA,QACC,CAAC,SACC,KAAK,SAAS;AAAA,MAClB,EACC,IAAI,CAAC,SAAS,KAAK,IAAI,EACvB,KAAK,IAAI;AACZ,UAAI,MAAM;AACR,cAAM,wBAAwB,MAAM,cAAc,eAAe;AAAA,MACnE;AAAA,IACF;AAAA,IACA,UAAU,YAAY;AACpB,YAAM,mBAAmB,cAAc,eAAe;AAAA,IACxD;AAAA,IACA,gBAAgB,CAAC,QAAQ;AAAA,IACzB,UAAU,EAAE,YAAY,kBAAkB;AAAA,EAC5C,CAAC;AAKD,+BAAU,MAAM;AACd,WAAO,MAAM;AACX,qBAAe,SAAS;AACxB,WAAK,aAAa;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,gBAAgB,YAAY,CAAC;AAKjC,QAAM,cAAc,QAAQ;AAE5B,QAAM,kBAAc;AAAA,IAClB,OAAO,SAAiB;AACtB,YAAM,wBAAwB,MAAM,cAAc,eAAe;AAAA,IACnE;AAAA,IACA,CAAC,yBAAyB,cAAc,eAAe;AAAA,EACzD;AAEA,QAAM,uBAAmB,2BAAY,MAAM;AACzC,SAAK,mBAAmB,cAAc,eAAe;AAAA,EACvD,GAAG,CAAC,oBAAoB,cAAc,eAAe,CAAC;AAEtD,QAAM,kBAAc;AAAA,IAClB,CAAC,aAAsB;AACrB,YAAM,KAAK,8BAAY,cAAc;AACrC,aAAO,cAAc,kBAAkB,EAAE;AAAA,IAC3C;AAAA,IACA,CAAC,aAAa;AAAA,EAChB;AAEA,QAAM,mBAAe,2BAAY,YAA6B;AAC5D,UAAM,kBAAkB,oBAAoB;AAC5C,WAAO,iBAAiB,QAAQ;AAAA,EAClC,GAAG,CAAC,iBAAiB,CAAC;AAEtB,QAAM,mBAAe;AAAA,IACnB,OAAO,aAAqB;AAC1B,qBAAe,MAAM,QAAQ;AAC7B,YAAM,kBAAkB,SAAS,QAAQ;AAAA,IAC3C;AAAA,IACA,CAAC,mBAAmB,cAAc;AAAA,EACpC;AAEA,QAAM,mBAAe;AAAA,IACnB,OAAO,UAAkB,UAAkB;AACzC,YAAM,kBAAkB,SAAS,UAAU,KAAK;AAAA,IAClD;AAAA,IACA,CAAC,iBAAiB;AAAA,EACpB;AAEA,QAAM,oBAAgB;AAAA,IACpB,OAAO,aAAqB;AAC1B,YAAM,kBAAkB,UAAU,QAAQ;AAAA,IAC5C;AAAA,IACA,CAAC,iBAAiB;AAAA,EACpB;AAEA,QAAM,mBAAe;AAAA,IACnB,CAAC,aAAqB;AACpB,UAAI,cAAc,mBAAmB,IAAI,QAAQ,GAAG;AAClD,0BAAkB,iBAAiB,QAAQ;AAAA,MAC7C,OAAO;AACL,aAAK,kBAAkB,oBAAoB;AAAA,MAC7C;AAAA,IACF;AAAA,IACA,CAAC,cAAc,oBAAoB,iBAAiB;AAAA,EACtD;AAEA,QAAM,qBAAiC;AAAA,IACrC,OAAO;AAAA;AAAA,MAEL,MAAM,YAAY;AAAA,MAClB,cAAc,YAAY;AAAA,MAC1B,SAAS,YAAY;AAAA,MACrB,aAAa,YAAY;AAAA,MACzB,gBAAgB,YAAY;AAAA,MAC5B,mBAAmB,YAAY;AAAA;AAAA,MAG/B,iBAAiB,cAAc;AAAA,MAC/B,eAAe,cAAc;AAAA,MAC7B,gBAAgB,cAAc;AAAA,MAC9B,mBAAmB,cAAc;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA,eAAe,oBAAoB;AAAA,MACnC,kBAAkB,oBAAoB;AAAA,MACtC,qBAAqB,oBAAoB;AAAA,MACzC,uBAAuB,oBAAoB;AAAA;AAAA,MAG3C,uBAAuB,cAAc;AAAA,MACrC,oBAAoB,MAAM;AAAA,MAAC;AAAA;AAAA,MAC3B,sBAAsB,cAAc;AAAA,MACpC,qBAAqB,cAAc;AAAA;AAAA,MAGnC,WAAW,aAAa;AAAA,MACxB,mBAAmB,aAAa;AAAA,MAChC,WAAW,aAAa;AAAA,IAC1B;AAAA,IACA;AAAA,MACE;AAAA,MACA,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SACE,6CAAC,0BAAuB,OAAO,gBAC7B,uDAAC,2CAAyB,SACvB,UACH,GACF;AAEJ;;;ARtbU,IAAAC,sBAAA;AAVH,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,aAAa;AACf,GAAuC;AACrC,QAAM,iBAAa,wBAAQ,MAAM,IAAI,0BAAW,EAAE,SAAS,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC;AAEtF,SACE,6CAAC,yBACC,uDAAC,+BACC,uDAAC,uBACC,uDAAC,oBAAiB,YACf,UACH,GACF,GACF,GACF;AAEJ;AAWA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AACF,GAAoC;AA5DpC;AA6DE,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,EAAE,KAAK,IAAI,QAAQ;AAEzB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,cAAc;AAAA,MACzB,YAAW,UAAK,YAAL,YAAgB;AAAA,MAC3B,mBAAmB,cAAc;AAAA,MACjC,sBAAsB,cAAc;AAAA,MAEpC;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW,cAAc;AAAA,UAEzB,uDAAC,mBAAgB,YAAyB,UAAS;AAAA;AAAA,MACrD;AAAA;AAAA,EACF;AAEJ;;;Ae9EA,IAAAC,iBAAiD;AA4BjD,IAAIC,yBAAwB;AAC5B,SAAS,yBAAiC;AACxC,SAAO,SAAS,KAAK,IAAI,CAAC,IAAI,EAAEA,sBAAqB;AACvD;AAEO,SAAS,uBAAuB;AAAA,EACrC;AACF,IAA+B,CAAC,GAAoB;AAClD,QAAM,EAAE,UAAU,IAAI,gBAAgB;AACtC,QAAM,CAAC,eAAe,gBAAgB,QAAI,yBAAyB,CAAC,CAAC;AAKrE,gCAAU,MAAM;AACd,UAAM,cAAc,UAAU,gBAAgB,CAAC,UAAwB;AA7C3E;AA8CM,YAAM,UAAU,MAAM;AAEtB,YAAM,eAA6B;AAAA,QACjC,IAAI,uBAAuB;AAAA,QAC3B,OAAO,aAAQ,SAAR,YAA2B;AAAA,QAClC,QAAQ,aAAQ,UAAR,YAA4B;AAAA,QACpC,MAAM,QAAQ;AAAA,QACd,SAAS;AAAA,QACT,WAAW,KAAK,IAAI;AAAA,QACpB,WAAW,MAAM;AAAA,MACnB;AAEA,uBAAiB,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC;AAClD,uDAAiB;AAAA,IACnB,CAAC;AAED,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,cAAc,CAAC;AAK9B,QAAM,iBAAiB,cAAc,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE;AAK/D,QAAM,kBAAc,4BAAY,CAAC,OAAe;AAC9C;AAAA,MAAiB,CAAC,SAChB,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,KAAK,iCAAK,IAAL,EAAQ,SAAS,KAAK,KAAI,CAAE;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ;AACF;","names":["import_client","import_react","import_client","_a","_b","isProcessing","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_react","ClientSession","_a","import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react","notificationIdCounter"]}
|