@aomi-labs/react 0.3.18 → 0.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/runtime/aomi-runtime.tsx","../src/contexts/control-context.tsx","../src/utils/uuid.ts","../src/state/thread-store.ts","../src/utils/model-selection.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/runtime/user-state-provider.tsx","../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 NativeWalletExecutionPolicy,\n NativeWalletSponsorship,\n SponsorshipPaymasterServiceContext,\n WalletCapabilities,\n} from \"@aomi-labs/client\";\nexport {\n toViemSignTypedDataArgs,\n hydrateTxPayloadFromUserState,\n toAAWalletCalls,\n toAAWalletCall,\n appendFeeCallToPayload,\n buildFeeAAWalletCall,\n normalizeSimulatedFee,\n MAX_AUTO_FEE_WEI,\n executeWalletCalls,\n DISABLED_PROVIDER_STATE,\n parseChainId,\n aaModeFromExecutionKind,\n} from \"@aomi-labs/client\";\n\n// =============================================================================\n// Runtime Provider\n// =============================================================================\nexport { AomiRuntimeProvider } from \"./runtime/aomi-runtime\";\nexport type { AomiRuntimeProviderProps } from \"./runtime/aomi-runtime\";\nexport { RuntimeUserStateProvider } from \"./runtime/user-state-provider\";\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 WalletSolanaSignPayload,\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 { useUser, UserContextProvider, UserState } 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 {\n ModelSelectionMode,\n ThreadMetadata,\n ThreadControlState,\n} 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\";\nexport { resolveAutoModel } from \"./utils/model-selection\";\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 StoredModelPreference,\n type StoredProviderKey,\n} from \"./contexts/control-context\";\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { AomiClient, UserState, type AomiClientOptions } 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 clientOptions?: Omit<AomiClientOptions, \"baseUrl\">;\n};\n\n// =============================================================================\n// Provider Shell\n// =============================================================================\n\nexport function AomiRuntimeProvider({\n children,\n backendUrl = \"http://localhost:8080\",\n clientOptions,\n}: Readonly<AomiRuntimeProviderProps>) {\n const aomiClient = useMemo(\n () => new AomiClient({ baseUrl: backendUrl, ...clientOptions }),\n [backendUrl, clientOptions],\n );\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={\n UserState.isConnected(user) ? (UserState.address(user) ?? undefined) : undefined\n }\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 {\n ModelSelectionMode,\n ThreadMetadata,\n ThreadControlState,\n} from \"../state/thread-store\";\nimport { initThreadControl } from \"../state/thread-store\";\nimport { resolveAutoModel } from \"../utils/model-selection\";\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\nexport type StoredModelPreference = {\n mode: ModelSelectionMode;\n model: string | null;\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: (\n secrets: Record<string, string>,\n ) => 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: (\n provider: string,\n apiKey: string,\n label?: string,\n ) => 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: (\n model: string,\n options?: { mode?: ModelSelectionMode },\n ) => 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 /** Sync pending control state to the backend before sending */\n syncCurrentThreadControl: () => Promise<void>;\n /** Build initial control state for new local threads */\n getPreferredThreadControl: () => ThreadControlState;\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 MODEL_SELECTION_STORAGE_KEY = \"aomi_model_selection\";\nconst PROVIDER_KEY_SECRET_PREFIX = \"PROVIDER_KEY:\";\n\nfunction getOrCreateClientId(): string {\n try {\n const storedClientId = globalThis.localStorage?.getItem(\n CLIENT_ID_STORAGE_KEY,\n );\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 readStoredModelPreference(): StoredModelPreference {\n try {\n const raw = globalThis.localStorage?.getItem(MODEL_SELECTION_STORAGE_KEY);\n if (!raw) return { mode: \"auto\", model: null };\n const parsed = JSON.parse(raw) as Partial<StoredModelPreference>;\n return {\n mode: parsed.mode === \"manual\" ? \"manual\" : \"auto\",\n model: typeof parsed.model === \"string\" ? parsed.model : null,\n };\n } catch {\n return { mode: \"auto\", model: null };\n }\n}\n\nfunction writeStoredModelPreference(preference: StoredModelPreference): void {\n try {\n globalThis.localStorage?.setItem(\n MODEL_SELECTION_STORAGE_KEY,\n JSON.stringify(preference),\n );\n } catch {\n // localStorage not available\n }\n}\n\nfunction resolvePreferredModelSelection(\n preference: StoredModelPreference,\n models: string[],\n defaultModel: string | null,\n): StoredModelPreference {\n if (\n preference.mode === \"manual\" &&\n preference.model &&\n models.includes(preference.model)\n ) {\n return preference;\n }\n\n if (preference.mode === \"auto\") {\n return {\n mode: \"auto\",\n model: resolveAutoModel(models) ?? defaultModel,\n };\n }\n\n return {\n mode: \"auto\",\n model: defaultModel ?? resolveAutoModel(models),\n };\n}\n\nfunction getFallbackModel(\n models: string[],\n defaultModel: string | null,\n): string | null {\n return defaultModel ?? resolveAutoModel(models);\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 so settings page and chat runtime share one 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\n .ingestSecrets(state.clientId, secrets)\n .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. App authorization is scoped\n // to auth/api-key state, so thread switches should not refetch it.\n useEffect(() => {\n const fetchApps = async () => {\n try {\n const apps = await aomiClientRef.current.getApps(sessionIdRef.current, {\n publicKey: publicKeyRef.current,\n apiKey: stateRef.current.apiKey ?? undefined,\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]);\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: resolveAutoModel(models),\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 (\n secrets: Record<string, string>,\n ): 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((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 // 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: resolveAutoModel(models),\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(sessionIdRef.current, {\n publicKey: publicKeyRef.current,\n apiKey: stateRef.current.apiKey ?? undefined,\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 getPreferredThreadControl = useCallback((): ThreadControlState => {\n const preference = readStoredModelPreference();\n const selection = resolvePreferredModelSelection(\n preference,\n stateRef.current.availableModels,\n stateRef.current.defaultModel,\n );\n return {\n ...initThreadControl(),\n model: selection.model,\n modelMode: selection.mode,\n controlDirty: selection.model !== null,\n };\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(\n async (model: string, options?: { mode?: ModelSelectionMode }) => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n const isProcessing = currentControl.isProcessing;\n const modelMode = options?.mode ?? \"manual\";\n\n console.log(\"[control-context] onModelSelect called\", {\n model,\n modelMode,\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 modelMode,\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(threadId, model, {\n app,\n apiKey: stateRef.current.apiKey ?? undefined,\n clientId: stateRef.current.clientId ?? undefined,\n });\n console.log(\"[control-context] onModelSelect backend result\", result);\n writeStoredModelPreference({\n mode: modelMode,\n model: modelMode === \"manual\" ? model : null,\n });\n const latestControl =\n getThreadMetadataRef.current(threadId)?.control ?? currentControl;\n if (latestControl.model === model && latestControl.app === app) {\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...latestControl,\n modelMode,\n controlDirty: false,\n },\n });\n }\n } catch (err) {\n console.error(\"[control-context] setModel failed:\", err);\n throw err;\n }\n },\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(\"[control-context] Cannot switch app while processing\");\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 const syncCurrentThreadControl = useCallback(async () => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n\n if (\n !currentControl.controlDirty ||\n currentControl.isProcessing ||\n !currentControl.model\n ) {\n return;\n }\n\n const app =\n resolveAuthorizedApp(\n currentControl.app,\n stateRef.current.authorizedApps,\n stateRef.current.defaultApp,\n ) ?? \"default\";\n\n await aomiClientRef.current.setModel(threadId, currentControl.model, {\n app,\n apiKey: stateRef.current.apiKey ?? undefined,\n clientId: stateRef.current.clientId ?? undefined,\n });\n\n const latestControl =\n getThreadMetadataRef.current(threadId)?.control ?? currentControl;\n if (\n latestControl.model === currentControl.model &&\n latestControl.app === currentControl.app\n ) {\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...latestControl,\n app,\n controlDirty: false,\n },\n });\n }\n }, []);\n\n useEffect(() => {\n const threadId = sessionIdRef.current;\n const metadata = getThreadMetadataRef.current(threadId);\n if (!metadata || metadata.control.isProcessing) return;\n\n const currentControl = metadata.control;\n let nextControl: ThreadControlState | null = null;\n\n if (currentControl.model === null) {\n const preferred = getPreferredThreadControl();\n if (!preferred.model) return;\n nextControl = {\n ...currentControl,\n model: preferred.model,\n modelMode: preferred.modelMode,\n controlDirty: true,\n };\n } else if (state.availableModels.length > 0) {\n const currentMode = currentControl.modelMode ?? \"manual\";\n\n if (currentMode === \"auto\") {\n const autoModel = getFallbackModel(\n state.availableModels,\n state.defaultModel,\n );\n if (autoModel && currentControl.model !== autoModel) {\n nextControl = {\n ...currentControl,\n model: autoModel,\n modelMode: \"auto\",\n controlDirty: true,\n };\n }\n } else if (!state.availableModels.includes(currentControl.model)) {\n const fallbackModel = getFallbackModel(\n state.availableModels,\n state.defaultModel,\n );\n if (fallbackModel) {\n nextControl = {\n ...currentControl,\n model: fallbackModel,\n modelMode: \"auto\",\n controlDirty: true,\n };\n }\n }\n }\n\n if (!nextControl) return;\n\n updateThreadMetadataRef.current(threadId, {\n control: nextControl,\n });\n }, [\n getPreferredThreadControl,\n sessionId,\n state.availableModels,\n state.defaultModel,\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 syncCurrentThreadControl,\n getPreferredThreadControl,\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\";\nexport type ModelSelectionMode = \"auto\" | \"manual\";\n\nexport type ThreadControlState = {\n /** Selected model for this thread (human-readable label) */\n model: string | null;\n /** Whether the selected model should be displayed as auto or explicit */\n modelMode?: ModelSelectionMode;\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 modelMode: \"auto\",\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 resetToDefault: this.resetToDefault,\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 /** Reset store to a single empty \"New Chat\" thread (e.g. on wallet disconnect). */\n resetToDefault = () => {\n const threadId = generateUUID();\n this.state = {\n currentThreadId: threadId,\n threadViewKey: this.state.threadViewKey + 1,\n threadCnt: 1,\n threads: new Map([[threadId, []]]),\n threadMetadata: new Map([\n [\n threadId,\n {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n },\n ],\n ]),\n };\n this.snapshot = this.buildSnapshot();\n this.emit();\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","/** Models preferred as default, in priority order (cheaper + good performance). */\nconst PREFERRED_DEFAULT_MODEL_PATTERNS: RegExp[] = [\n /^claude-4\\.5-haiku/i,\n /^claude.*haiku/i,\n /^gpt-4o-mini/i,\n /^gemini.*flash/i,\n];\n\n/**\n * Resolve the actual backend model for auto mode.\n * Prefers known cheaper/performance-oriented models before falling back to the\n * backend order.\n */\nexport function resolveAutoModel(models: string[]): string | null {\n if (models.length === 0) return null;\n\n for (const pattern of PREFERRED_DEFAULT_MODEL_PATTERNS) {\n const match = models.find((model) => pattern.test(model));\n if (match) return match;\n }\n\n return models[0] ?? null;\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 resetToDefault: () => 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\";\nimport { UserState } from \"@aomi-labs/client\";\n\nexport { UserState } from \"@aomi-labs/client\";\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 address: undefined,\n chain_id: undefined,\n is_connected: false,\n ens_name: 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 notifyStateChange = useCallback((next: UserState) => {\n queueMicrotask(() => {\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n });\n }, []);\n\n const pruneUndefined = useCallback((state: UserState): UserState => {\n return Object.fromEntries(\n Object.entries(state).filter(([, value]) => value !== undefined),\n );\n }, []);\n\n const setUser = useCallback((data: Partial<UserState>) => {\n setUserState((prev) => {\n const normalizedData = pruneUndefined(UserState.normalize(data) ?? {});\n const nextPartial: UserState = { ...normalizedData };\n\n // Guard against a transient \"connected-without-chain\" payload:\n // keep the previous chain if present; otherwise, delay flipping\n // `is_connected` until a concrete chain arrives.\n if (\n nextPartial.is_connected === true &&\n nextPartial.chain_id === undefined\n ) {\n if (prev.chain_id !== undefined) {\n nextPartial.chain_id = prev.chain_id;\n } else {\n delete nextPartial.is_connected;\n }\n }\n\n const next: UserState =\n nextPartial.is_connected === false\n ? {\n ...(UserState.normalize({ ...prev, ...nextPartial }) ?? prev),\n address: undefined,\n chain_id: undefined,\n ens_name: undefined,\n }\n : (UserState.normalize({ ...prev, ...nextPartial }) ?? prev);\n notifyStateChange(next);\n\n return next;\n });\n }, [notifyStateChange, pruneUndefined]);\n\n const addExtValue = useCallback((key: string, value: unknown) => {\n setUserState((prev) => {\n const next = UserState.withExt(prev, key, value);\n notifyStateChange(next);\n return next;\n });\n }, [notifyStateChange]);\n\n const removeExtValue = useCallback((key: string) => {\n setUserState((prev) => {\n const ext = prev.ext;\n if (\n typeof ext !== \"object\" ||\n ext === null ||\n Array.isArray(ext) ||\n !(key in ext)\n ) {\n return prev;\n }\n const nextExt = { ...(ext as Record<string, unknown>) };\n delete nextExt[key];\n const next: UserState = {\n ...prev,\n ext: Object.keys(nextExt).length > 0 ? nextExt : undefined,\n };\n notifyStateChange(next);\n return next;\n });\n }, [notifyStateChange]);\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, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {\n AssistantRuntimeProvider,\n useExternalStoreRuntime,\n type AppendMessage,\n} from \"@assistant-ui/react\";\n\nimport { UserState, 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\";\nimport { RuntimeUserStateProvider } from \"./user-state-provider\";\n\nconst THREAD_PREFETCH_LIMIT = 5;\nconst PREFETCH_IDLE_TIMEOUT_MS = 1500;\n\ntype GlobalWithIdleCallback = typeof globalThis & {\n requestIdleCallback?: (\n callback: () => void,\n options?: { timeout?: number },\n ) => number;\n cancelIdleCallback?: (handle: number) => void;\n};\n\nfunction scheduleBackgroundTask(task: () => void): () => void {\n const runtimeGlobal = globalThis as GlobalWithIdleCallback;\n\n if (typeof runtimeGlobal.requestIdleCallback === \"function\") {\n const idleId = runtimeGlobal.requestIdleCallback(task, {\n timeout: PREFETCH_IDLE_TIMEOUT_MS,\n });\n return () => runtimeGlobal.cancelIdleCallback?.(idleId);\n }\n\n const timeoutId = runtimeGlobal.setTimeout(task, 0);\n return () => runtimeGlobal.clearTimeout(timeoutId);\n}\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 {\n getControlState,\n getCurrentThreadApp,\n getPreferredThreadControl,\n syncCurrentThreadControl,\n } = useControl();\n\n // ---------------------------------------------------------------------------\n // Wallet handler (receives requests from orchestrator)\n // ---------------------------------------------------------------------------\n const sessionManagerRef = useRef<\n ReturnType<typeof useRuntimeOrchestrator>[\"sessionManager\"] | null\n >(null);\n\n const walletHandler = useWalletHandler({\n getSession: () =>\n 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 closeSession,\n closeIdleSessionsExcept,\n closeAllSessions,\n aomiClientRef,\n } = useRuntimeOrchestrator(aomiClient, {\n getPublicKey: () =>\n UserState.isConnected(getUserState())\n ? UserState.address(getUserState())\n : undefined,\n getUserState,\n getApp: getCurrentThreadApp,\n getApiKey: () => getControlState().apiKey,\n getClientId: () => getControlState().clientId ?? undefined,\n prepareThreadForSend: async (threadId) => {\n await ensureBackendThread(threadId);\n await syncCurrentThreadControl();\n },\n onPendingRequestsChange: walletHandler.setRequests,\n onEvent: (event) => eventContext.dispatch(event),\n });\n\n sessionManagerRef.current = sessionManager;\n\n // ---------------------------------------------------------------------------\n // Refs for stable access\n // ---------------------------------------------------------------------------\n const threadContextRef = useRef(threadContext);\n threadContextRef.current = threadContext;\n const remoteThreadIdsRef = useRef(new Set<string>());\n const warmedThreadIdsRef = useRef(new Set<string>());\n const warmPromisesRef = useRef(new Map<string, Promise<void>>());\n const prefetchCancelRef = useRef<(() => void) | null>(null);\n const [isThreadLoading, setIsThreadLoading] = useState(false);\n const [isThreadListLoading, setIsThreadListLoading] = useState(true);\n\n // ---------------------------------------------------------------------------\n // Send wallet state changes to backend\n // ---------------------------------------------------------------------------\n const walletSnapshot = useCallback(\n (nextUser: ReturnType<typeof getUserState>) => ({\n address: UserState.address(nextUser),\n chain_id: UserState.chainId(nextUser),\n is_connected: UserState.isConnected(nextUser) ?? false,\n ens_name:\n typeof nextUser.ens_name === \"string\" ? nextUser.ens_name : undefined,\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.chain_id === nextWalletState.chain_id &&\n prevWalletState.is_connected === nextWalletState.is_connected &&\n prevWalletState.ens_name === nextWalletState.ens_name\n ) {\n return;\n }\n\n lastWalletStateRef.current = nextWalletState;\n const sessionId = threadContext.currentThreadId;\n if (!remoteThreadIdsRef.current.has(sessionId)) {\n return;\n }\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 const warmThread = useCallback(\n async (threadId: string) => {\n if (\n !remoteThreadIdsRef.current.has(threadId) ||\n warmedThreadIdsRef.current.has(threadId)\n ) {\n return;\n }\n\n const existingPromise = warmPromisesRef.current.get(threadId);\n if (existingPromise) {\n return existingPromise;\n }\n\n const warmPromise = (async () => {\n const userState = getUserState();\n await aomiClientRef.current.createThread(\n threadId,\n UserState.isConnected(userState)\n ? UserState.address(userState)\n : undefined,\n );\n warmedThreadIdsRef.current.add(threadId);\n })();\n\n warmPromisesRef.current.set(threadId, warmPromise);\n\n try {\n await warmPromise;\n } finally {\n warmPromisesRef.current.delete(threadId);\n }\n },\n [aomiClientRef, getUserState],\n );\n\n const scheduleThreadPrefetch = useCallback(\n (threadIds: string[]) => {\n prefetchCancelRef.current?.();\n\n const prefetchThreadIds = Array.from(new Set(threadIds))\n .filter((threadId) => remoteThreadIdsRef.current.has(threadId))\n .slice(0, THREAD_PREFETCH_LIMIT);\n\n if (prefetchThreadIds.length === 0) {\n prefetchCancelRef.current = null;\n return;\n }\n\n let cancelled = false;\n const cancelScheduledTask = scheduleBackgroundTask(() => {\n void Promise.all(\n prefetchThreadIds.map(async (threadId) => {\n if (cancelled || !remoteThreadIdsRef.current.has(threadId)) return;\n if (\n threadContextRef.current.getThreadMessages(threadId).length > 0\n ) {\n return;\n }\n\n try {\n await warmThread(threadId);\n if (cancelled || !remoteThreadIdsRef.current.has(threadId))\n return;\n await ensureInitialState(threadId);\n } catch (error) {\n console.debug(\"Failed to prefetch thread:\", threadId, error);\n }\n }),\n );\n });\n\n prefetchCancelRef.current = () => {\n cancelled = true;\n cancelScheduledTask();\n };\n },\n [ensureInitialState, warmThread],\n );\n\n // ---------------------------------------------------------------------------\n // Respond to user_state_request from backend\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const unsubscribe = eventContext.subscribe(\"user_state_request\", () => {\n const session =\n sessionManagerRef.current?.get(threadContext.currentThreadId) ??\n getSession(threadContext.currentThreadId);\n eventContext.sendOutboundSystem({\n type: \"user_state_response\",\n sessionId: threadContext.currentThreadId,\n payload: session.getUserState() ?? getUserState(),\n });\n });\n return unsubscribe;\n }, [eventContext, threadContext.currentThreadId, getSession, getUserState]);\n\n // ---------------------------------------------------------------------------\n // Ensure backend thread exists (lazy creation on first message send)\n // ---------------------------------------------------------------------------\n const ensureBackendThread = useCallback(\n async (threadId: string) => {\n if (remoteThreadIdsRef.current.has(threadId)) return;\n\n const userState = getUserState();\n await aomiClientRef.current.createThread(\n threadId,\n UserState.isConnected(userState)\n ? UserState.address(userState)\n : undefined,\n );\n remoteThreadIdsRef.current.add(threadId);\n warmedThreadIdsRef.current.add(threadId);\n },\n [aomiClientRef, getUserState],\n );\n\n // ---------------------------------------------------------------------------\n // Initial state fetch on thread change (skip for local-only threads)\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const threadId = threadContext.currentThreadId;\n closeIdleSessionsExcept(threadId);\n\n if (!remoteThreadIdsRef.current.has(threadId)) {\n setIsThreadLoading(false);\n return;\n }\n\n let cancelled = false;\n setIsThreadLoading(true);\n\n void (async () => {\n try {\n await warmThread(threadId);\n if (!cancelled) {\n await ensureInitialState(threadId);\n }\n } finally {\n if (!cancelled) {\n setIsThreadLoading(false);\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n closeIdleSessionsExcept,\n ensureInitialState,\n threadContext.currentThreadId,\n warmThread,\n ]);\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 = UserState.isConnected(user)\n ? UserState.address(user)\n : undefined;\n if (!userAddress) {\n const hadRemoteThreads = remoteThreadIdsRef.current.size > 0;\n const hadSessions = sessionManager.size > 0;\n setIsThreadListLoading(false);\n prefetchCancelRef.current?.();\n prefetchCancelRef.current = null;\n remoteThreadIdsRef.current.clear();\n warmedThreadIdsRef.current.clear();\n warmPromisesRef.current.clear();\n closeAllSessions();\n if (hadRemoteThreads || hadSessions) {\n threadContextRef.current.resetToDefault();\n }\n return;\n }\n\n let cancelled = false;\n setIsThreadListLoading(true);\n\n const fetchThreadList = async () => {\n try {\n const remoteThreadIdsAtFetchStart = new Set(remoteThreadIdsRef.current);\n const threadList = await aomiClientRef.current.listThreads(userAddress);\n if (cancelled) return;\n const currentContext = threadContextRef.current;\n const remoteThreadIds = new Set<string>();\n const newMetadata = new Map(currentContext.allThreadsMetadata);\n let maxChatNum = currentContext.threadCnt;\n\n for (const thread of threadList) {\n remoteThreadIds.add(thread.session_id);\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 for (const threadId of remoteThreadIdsRef.current) {\n if (!remoteThreadIdsAtFetchStart.has(threadId)) {\n remoteThreadIds.add(threadId);\n }\n }\n\n remoteThreadIdsRef.current = remoteThreadIds;\n warmedThreadIdsRef.current = new Set(\n Array.from(warmedThreadIdsRef.current).filter((threadId) =>\n remoteThreadIds.has(threadId),\n ),\n );\n currentContext.setThreadMetadata(newMetadata);\n if (maxChatNum > currentContext.threadCnt) {\n currentContext.setThreadCnt(maxChatNum);\n }\n\n scheduleThreadPrefetch(threadList.map((thread) => thread.session_id));\n\n if (remoteThreadIds.has(currentContext.currentThreadId)) {\n setIsThreadLoading(true);\n try {\n await warmThread(currentContext.currentThreadId);\n if (!cancelled) {\n await ensureInitialState(currentContext.currentThreadId);\n }\n } finally {\n if (!cancelled) {\n setIsThreadLoading(false);\n }\n }\n }\n } catch (error) {\n console.error(\"Failed to fetch thread list:\", error);\n } finally {\n if (!cancelled) {\n setIsThreadListLoading(false);\n }\n }\n };\n\n void fetchThreadList();\n\n return () => {\n cancelled = true;\n prefetchCancelRef.current?.();\n prefetchCancelRef.current = null;\n };\n }, [\n user,\n aomiClientRef,\n ensureInitialState,\n scheduleThreadPrefetch,\n warmThread,\n ]);\n\n // ---------------------------------------------------------------------------\n // Thread list adapter\n // ---------------------------------------------------------------------------\n const isRemoteThread = useCallback(\n (threadId: string) => remoteThreadIdsRef.current.has(threadId),\n [],\n );\n\n const threadListAdapter = useMemo(\n () =>\n buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n isLoading: isThreadListLoading,\n getInitialControl: getPreferredThreadControl,\n isRemoteThread,\n }),\n [\n aomiClientRef,\n getPreferredThreadControl,\n isRemoteThread,\n isThreadListLoading,\n setIsRunning,\n threadContext,\n threadContext.currentThreadId,\n threadContext.allThreadsMetadata,\n currentMessages,\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 isLoading: isThreadLoading,\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 prefetchCancelRef.current?.();\n closeAllSessions();\n };\n }, [closeAllSessions]);\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 closeSession(threadId);\n await threadListAdapter.onDelete(threadId);\n },\n [closeSession, 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 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 simulateBatchTransactions = useCallback<\n AomiRuntimeApi[\"simulateBatchTransactions\"]\n >(\n async (transactions, options) => {\n const session =\n sessionManagerRef.current?.get(threadContext.currentThreadId) ??\n getSession(threadContext.currentThreadId);\n if (!session) {\n throw new Error(\"runtime_session_unavailable\");\n }\n\n const response = await session.client.simulateBatch(\n session.sessionId,\n transactions,\n options,\n );\n return response.result;\n },\n [getSession, threadContext.currentThreadId],\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.startRequest,\n resolveWalletRequest: walletHandler.resolveRequest,\n rejectWalletRequest: walletHandler.rejectRequest,\n simulateBatchTransactions,\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 simulateBatchTransactions,\n eventContext,\n ],\n );\n\n return (\n <AomiRuntimeApiProvider value={aomiRuntimeApi}>\n <RuntimeUserStateProvider\n sessionManager={sessionManager}\n getUserState={userContext.getUserState}\n onUserStateChange={userContext.onUserStateChange}\n >\n <AssistantRuntimeProvider runtime={runtime}>\n {children}\n </AssistantRuntimeProvider>\n </RuntimeUserStateProvider>\n </AomiRuntimeApiProvider>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { AomiClient, UserState, WalletRequest } from \"@aomi-labs/client\";\nimport { CLIENT_TYPE_WEB_UI } from \"@aomi-labs/client\";\nimport { Session as ClientSession } from \"@aomi-labs/client\";\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 prepareThreadForSend?: (threadId: string) => Promise<void> | void;\n onPendingRequestsChange?: (requests: WalletRequest[]) => void;\n onEvent?: (event: {\n type: string;\n payload: unknown;\n sessionId: string;\n }) => void;\n};\n\ntype OptimisticSendStatus = \"sending\" | \"sent\" | \"failed\";\n\nconst toErrorMessage = (error: unknown) =>\n error instanceof Error ? error.message : \"Message failed to send\";\n\nconst getOptimisticStatus = (message: ThreadMessageLike) => {\n const status = message.metadata?.custom?.aomiSendStatus;\n return status === \"sending\" || status === \"sent\" || status === \"failed\"\n ? status\n : undefined;\n};\n\nconst hasUnhydratedOptimisticMessage = (messages: ThreadMessageLike[]) =>\n messages.some((message) => {\n const status = getOptimisticStatus(message);\n return status === \"sending\" || status === \"sent\";\n });\n\nconst withOptimisticStatus = (\n message: ThreadMessageLike,\n status: OptimisticSendStatus,\n error?: unknown,\n): ThreadMessageLike => {\n const custom: Record<string, unknown> = {\n ...(message.metadata?.custom ?? {}),\n aomiSendStatus: status,\n };\n\n if (error) {\n custom.aomiSendError = toErrorMessage(error);\n } else {\n delete custom.aomiSendError;\n }\n\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom,\n },\n };\n};\n\nconst updateOptimisticMessage = (\n threadContext: ThreadContext,\n threadId: string,\n messageId: string,\n status: OptimisticSendStatus,\n error?: unknown,\n) => {\n const messages = threadContext.getThreadMessages(threadId);\n let changed = false;\n const nextMessages = messages.map((message) => {\n if (message.id !== messageId) return message;\n changed = true;\n return withOptimisticStatus(message, status, error);\n });\n\n if (changed) {\n threadContext.setThreadMessages(threadId, nextMessages);\n }\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 optionsRef = useRef(options);\n optionsRef.current = options;\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 const initialStatePromises = useRef<Map<string, Promise<void>>>(new Map());\n const hydratedThreadIds = useRef<Set<string>>(new Set());\n // Track event listener cleanup per thread\n const listenerCleanups = useRef<Map<string, () => void>>(new Map());\n\n const cleanupSessionListeners = useCallback((threadId: string) => {\n listenerCleanups.current.get(threadId)?.();\n listenerCleanups.current.delete(threadId);\n }, []);\n\n const closeSession = useCallback(\n (threadId: string) => {\n cleanupSessionListeners(threadId);\n pendingFetches.current.delete(threadId);\n initialStatePromises.current.delete(threadId);\n hydratedThreadIds.current.delete(threadId);\n sessionManagerRef.current?.close(threadId);\n },\n [cleanupSessionListeners],\n );\n\n const closeIdleSessionsExcept = useCallback(\n (activeThreadId: string) => {\n const closedThreadIds =\n sessionManagerRef.current?.closeIdleExcept(\n activeThreadId,\n cleanupSessionListeners,\n ) ?? [];\n\n for (const threadId of closedThreadIds) {\n pendingFetches.current.delete(threadId);\n initialStatePromises.current.delete(threadId);\n hydratedThreadIds.current.delete(threadId);\n }\n\n return closedThreadIds;\n },\n [cleanupSessionListeners],\n );\n\n const closeAllSessions = useCallback(() => {\n pendingFetches.current.clear();\n initialStatePromises.current.clear();\n hydratedThreadIds.current.clear();\n for (const threadId of Array.from(listenerCleanups.current.keys())) {\n cleanupSessionListeners(threadId);\n }\n sessionManagerRef.current?.closeAll();\n }, [cleanupSessionListeners]);\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 nextOptions = optionsRef.current;\n const nextApp = nextOptions.getApp();\n const nextPublicKey = nextOptions.getPublicKey?.();\n const nextApiKey = nextOptions.getApiKey?.() ?? undefined;\n const nextClientId = nextOptions.getClientId?.();\n const nextUserState = nextOptions.getUserState?.();\n const existing = manager.get(threadId);\n if (existing) {\n existing.syncRuntimeOptions({\n app: nextApp,\n publicKey: nextPublicKey,\n apiKey: nextApiKey,\n clientId: nextClientId,\n userState: nextUserState,\n });\n return existing;\n }\n\n const session = manager.getOrCreate(threadId, {\n app: nextApp,\n publicKey: nextPublicKey,\n apiKey: nextApiKey,\n clientId: nextClientId,\n clientType: CLIENT_TYPE_WEB_UI,\n syncPendingTxRequestsFromUserState: false,\n userState: nextUserState,\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 const existingMessages =\n threadContextRef.current.getThreadMessages(threadId);\n if (\n threadMessages.length === 0 &&\n hasUnhydratedOptimisticMessage(existingMessages)\n ) {\n return;\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 cleanups.push(\n session.on(\"wallet_requests_changed\", (requests) =>\n optionsRef.current.onPendingRequestsChange?.(requests),\n ),\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(\n type as keyof import(\"@aomi-labs/client\").SessionEventMap,\n (payload: unknown) => {\n optionsRef.current.onEvent?.({\n type,\n payload,\n sessionId: threadId,\n });\n },\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 const existingPromise = initialStatePromises.current.get(threadId);\n if (existingPromise) {\n return existingPromise;\n }\n\n const cachedMessages =\n threadContextRef.current.getThreadMessages(threadId);\n const existingSession = sessionManagerRef.current?.get(threadId);\n if (\n existingSession &&\n (hydratedThreadIds.current.has(threadId) || cachedMessages.length > 0)\n ) {\n optionsRef.current.onPendingRequestsChange?.(\n existingSession.getPendingRequests(),\n );\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(existingSession.getIsProcessing());\n }\n return;\n }\n\n const fetchPromise = (async () => {\n pendingFetches.current.add(threadId);\n\n try {\n const session = getSession(threadId);\n await session.fetchCurrentState();\n hydratedThreadIds.current.add(threadId);\n optionsRef.current.onPendingRequestsChange?.(\n session.getPendingRequests(),\n );\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 initialStatePromises.current.delete(threadId);\n }\n })();\n\n initialStatePromises.current.set(threadId, fetchPromise);\n return fetchPromise;\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 existingMessages =\n threadContextRef.current.getThreadMessages(threadId);\n const optimisticMessageId = String(existingMessages.length);\n const userMessage: ThreadMessageLike = {\n id: optimisticMessageId,\n role: \"user\",\n content: [{ type: \"text\", text }],\n createdAt: new Date(),\n metadata: {\n custom: {\n aomiOriginalText: text,\n aomiSendStatus: \"sending\",\n },\n },\n };\n threadContextRef.current.setThreadMessages(threadId, [\n ...existingMessages,\n userMessage,\n ]);\n threadContextRef.current.updateThreadMetadata(threadId, {\n lastActiveAt: new Date().toISOString(),\n });\n\n // Immediately show \"generating\" state so the UI switches to the stop\n // button and displays a loading indicator while the message is in flight.\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(true);\n }\n\n try {\n await optionsRef.current.prepareThreadForSend?.(threadId);\n const session = getSession(threadId);\n await session.sendAsync(text);\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(session.getIsProcessing());\n }\n updateOptimisticMessage(\n threadContextRef.current,\n threadId,\n optimisticMessageId,\n \"sent\",\n );\n optionsRef.current.onPendingRequestsChange?.(\n session.getPendingRequests(),\n );\n } catch (error) {\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(false);\n }\n updateOptimisticMessage(\n threadContextRef.current,\n threadId,\n optimisticMessageId,\n \"failed\",\n error,\n );\n throw error;\n }\n },\n [getSession],\n );\n\n /** Cancel the current generation on the given thread. */\n const cancelGeneration = useCallback(async (threadId: string) => {\n const session = sessionManagerRef.current?.get(threadId);\n if (session) {\n await session.interrupt();\n }\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n closeAllSessions();\n };\n }, [closeAllSessions]);\n\n return {\n sessionManager: sessionManagerRef.current!,\n getSession,\n isRunning,\n setIsRunning,\n ensureInitialState,\n sendMessage,\n cancelGeneration,\n closeSession,\n closeAllSessions,\n closeIdleSessionsExcept,\n aomiClientRef,\n };\n}\n","// =============================================================================\n// SessionManager — manages one ClientSession per thread\n// =============================================================================\n\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport {\n Session as ClientSession,\n type SessionOptions,\n} from \"@aomi-labs/client\";\n\nexport class SessionManager {\n private sessions = new Map<string, ClientSession>();\n\n constructor(private readonly clientFactory: () => AomiClient) {}\n\n getOrCreate(\n threadId: string,\n opts: Omit<SessionOptions, \"sessionId\">,\n ): 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 get size(): number {\n return this.sessions.size;\n }\n\n forEach(callback: (session: ClientSession, threadId: string) => void): void {\n for (const [threadId, session] of this.sessions) {\n callback(session, threadId);\n }\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 closeIdleExcept(\n activeThreadId: string,\n onBeforeClose?: (threadId: string) => void,\n ): string[] {\n const closedThreadIds: string[] = [];\n\n for (const [threadId, session] of this.sessions) {\n if (threadId === activeThreadId) continue;\n if (session.getIsProcessing()) continue;\n if (session.getIsPolling()) continue;\n if (session.getPendingRequests().length > 0) continue;\n\n closedThreadIds.push(threadId);\n }\n\n for (const threadId of closedThreadIds) {\n onBeforeClose?.(threadId);\n this.close(threadId);\n }\n\n return closedThreadIds;\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 \"@aomi-labs/client\";\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 { initThreadControl, type ThreadMetadata } from \"../state/thread-store\";\nimport type { ThreadControlState } 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(\n threadMetadata: Map<string, ThreadMetadata>,\n shouldShowThread: (threadId: string) => boolean,\n) {\n const entries = Array.from(threadMetadata.entries()).filter(\n ([threadId, meta]) =>\n !isPlaceholderTitle(meta.title) && shouldShowThread(threadId),\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 isLoading?: boolean;\n getInitialControl?: () => ThreadControlState;\n isRemoteThread?: (threadId: string) => boolean;\n};\n\nexport function buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n isLoading = false,\n getInitialControl = initThreadControl,\n isRemoteThread = () => true,\n}: ThreadListAdapterConfig) {\n const shouldShowThread = (threadId: string) => {\n if (isRemoteThread(threadId)) return true;\n\n return threadContext\n .getThreadMessages(threadId)\n .some((message) => message.role === \"user\");\n };\n const { regularThreads, archivedThreads } = buildThreadLists(\n threadContext.allThreadsMetadata,\n shouldShowThread,\n );\n\n /** Remove previous thread if it's local-only and has no messages. */\n const cleanupEmptyLocalThread = () => {\n const prevId = threadContext.currentThreadId;\n if (isRemoteThread(prevId)) return;\n const msgs = threadContext.getThreadMessages(prevId);\n if (msgs.length > 0) return;\n threadContext.setThreadMetadata((prev) => {\n const next = new Map(prev);\n next.delete(prevId);\n return next;\n });\n threadContext.setThreads((prev) => {\n const next = new Map(prev);\n next.delete(prevId);\n return next;\n });\n };\n\n return {\n threadId: threadContext.currentThreadId,\n isLoading,\n threads: regularThreads,\n archivedThreads,\n\n onSwitchToNewThread: () => {\n cleanupEmptyLocalThread();\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: getInitialControl(),\n }),\n );\n threadContext.setThreadMessages(threadId, []);\n threadContext.setCurrentThreadId(threadId);\n setIsRunning(false);\n threadContext.bumpThreadViewKey();\n },\n\n onSwitchToThread: (threadId: string) => {\n cleanupEmptyLocalThread();\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: getInitialControl(),\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 { AomiSimulateResponse, UserState } from \"@aomi-labs/client\";\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 { WalletRequest } from \"./handlers/wallet-handler\";\nimport type { WalletRequestResult } from \"@aomi-labs/client\";\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 in-flight — suppresses it from the pending list until acked */\n startWalletRequest: (id: string) => void;\n /** Complete a wallet request after the backend acknowledges the response */\n resolveWalletRequest: (\n id: string,\n result: WalletRequestResult,\n ) => Promise<void>;\n /** Fail a wallet request after the backend acknowledges the error */\n rejectWalletRequest: (id: string, error?: string) => Promise<void>;\n /** Simulate a batch against the current thread session context. */\n simulateBatchTransactions: (\n transactions: Array<{\n to: string;\n value?: string;\n data?: string;\n label?: string;\n chain_id?: number;\n chainId?: number;\n }>,\n options?: { from?: string; chainId?: number },\n ) => Promise<AomiSimulateResponse[\"result\"]>;\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 WalletSolanaSignPayload,\n WalletTxPayload,\n WalletRequest,\n WalletRequestKind,\n WalletRequestResult,\n} from \"@aomi-labs/client\";\nimport type { Session as ClientSession } from \"@aomi-labs/client\";\n\n// Re-export types consumers need. The source of truth for `WalletRequestKind`\n// is `@aomi-labs/client` — Solana adds a third arm there.\nexport type {\n WalletRequest,\n WalletRequestKind,\n WalletRequestResult,\n WalletTxPayload,\n WalletEip712Payload,\n WalletSolanaSignPayload,\n};\n\nexport type WalletRequestStatus = \"pending\" | \"processing\";\n\nexport type WalletHandlerConfig = {\n /** Get the ClientSession for the current thread. */\n getSession: () => ClientSession | undefined;\n};\n\nexport type WalletHandlerApi = {\n /**\n * All queued wallet requests across every supported kind: EVM txs\n * (`kind: \"transaction\"`), EIP-712 signs (`kind: \"eip712_sign\"`), and\n * Solana signs (`kind: \"solana_sign\"`). Consumers should narrow on\n * `request.kind` before reading `request.payload` — the discriminated\n * union auto-narrows the payload type.\n */\n pendingRequests: WalletRequest[];\n /** Replace pending requests with the session's authoritative snapshot. */\n setRequests: (requests: WalletRequest[]) => void;\n /** Mark a request as in-flight so it is not replayed while awaiting backend ack. */\n startRequest: (id: string) => void;\n /**\n * Complete a request successfully — sends the response wire event to\n * the backend via ClientSession. The `result.kind` discriminator must\n * match the originating request's kind (e.g. `{ kind: \"solana_sign\",\n * signedTx: \"...\" }` for a Solana request); ClientSession runtime-checks\n * this and throws on mismatch.\n */\n resolveRequest: (id: string, result: WalletRequestResult) => Promise<void>;\n /** Fail a request — sends error to backend via ClientSession */\n rejectRequest: (id: string, error?: string) => Promise<void>;\n};\n\nexport function useWalletHandler({\n getSession,\n}: WalletHandlerConfig): WalletHandlerApi {\n const [pendingRequests, setPendingRequests] = useState<WalletRequest[]>([]);\n const requestsRef = useRef<WalletRequest[]>(pendingRequests);\n const inFlightRequestSetRef = useRef<Set<string>>(new Set());\n const suppressedRequestSetRef = useRef<Set<string>>(new Set());\n\n const syncVisibleRequests = useCallback(() => {\n setPendingRequests(\n requestsRef.current.filter(\n (request) => !suppressedRequestSetRef.current.has(request.id),\n ),\n );\n }, []);\n\n const setRequests = useCallback((requests: WalletRequest[]) => {\n const incomingIds = new Set(requests.map((request) => request.id));\n for (const id of suppressedRequestSetRef.current) {\n if (\n !incomingIds.has(id) &&\n !inFlightRequestSetRef.current.has(id)\n ) {\n suppressedRequestSetRef.current.delete(id);\n }\n }\n\n const preservedInFlight = requestsRef.current.filter(\n (request) =>\n inFlightRequestSetRef.current.has(request.id) &&\n !incomingIds.has(request.id),\n );\n\n requestsRef.current = [...requests, ...preservedInFlight];\n syncVisibleRequests();\n }, [syncVisibleRequests]);\n\n const startRequest = useCallback((id: string) => {\n if (!requestsRef.current.some((request) => request.id === id)) {\n return;\n }\n\n inFlightRequestSetRef.current.add(id);\n suppressedRequestSetRef.current.add(id);\n syncVisibleRequests();\n }, [syncVisibleRequests]);\n\n const resolveRequest = useCallback(\n async (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 startRequest(id);\n\n try {\n await session.resolve(id, result);\n } catch (err) {\n console.error(\"[wallet-handler] Failed to resolve request:\", err);\n } finally {\n requestsRef.current = requestsRef.current.filter(\n (request) => request.id !== id,\n );\n inFlightRequestSetRef.current.delete(id);\n syncVisibleRequests();\n }\n },\n [getSession, startRequest, syncVisibleRequests],\n );\n\n const rejectRequest = useCallback(\n async (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 startRequest(id);\n\n try {\n await session.reject(id, error);\n } catch (err) {\n console.error(\"[wallet-handler] Failed to reject request:\", err);\n } finally {\n requestsRef.current = requestsRef.current.filter(\n (request) => request.id !== id,\n );\n inFlightRequestSetRef.current.delete(id);\n syncVisibleRequests();\n }\n },\n [getSession, startRequest, syncVisibleRequests],\n );\n\n return {\n pendingRequests,\n setRequests,\n startRequest,\n resolveRequest,\n rejectRequest,\n };\n}\n","\"use client\";\n\nimport { useEffect, useRef, type ReactNode } from \"react\";\nimport type { UserState } from \"@aomi-labs/client\";\n\nimport { SessionManager } from \"./session-manager\";\n\ntype RuntimeUserStateProviderProps = {\n children: ReactNode;\n sessionManager: SessionManager;\n getUserState: () => UserState;\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n};\n\nfunction stableStateString(state: UserState): string {\n return JSON.stringify(state ?? {});\n}\n\nexport function RuntimeUserStateProvider({\n children,\n sessionManager,\n getUserState,\n onUserStateChange,\n}: RuntimeUserStateProviderProps) {\n const lastSerializedStateRef = useRef<string>(\"\");\n\n useEffect(() => {\n const applyToSessions = (next: UserState) => {\n const serialized = stableStateString(next);\n if (serialized === lastSerializedStateRef.current) {\n return;\n }\n lastSerializedStateRef.current = serialized;\n sessionManager.forEach((session) => {\n session.resolveUserState(next);\n });\n };\n\n applyToSessions(getUserState());\n const unsubscribe = onUserStateChange((next) => {\n applyToSessions(next);\n });\n return unsubscribe;\n }, [getUserState, onUserStateChange, sessionManager]);\n\n return <>{children}</>;\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":"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","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_client","import_jsx_runtime","import_react","import_client","import_react","import_client","import_client","ClientSession","_a","_b","import_react","import_react","import_react","import_jsx_runtime","import_jsx_runtime","_a","import_jsx_runtime","import_react","notificationIdCounter"]}
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/utils/model-selection.ts","../src/utils/client-session.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/runtime/user-state-provider.tsx","../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 NativeWalletExecutionPolicy,\n NativeWalletSponsorship,\n SponsorshipPaymasterServiceContext,\n WalletCapabilities,\n} from \"@aomi-labs/client\";\nexport {\n toViemSignTypedDataArgs,\n hydrateTxPayloadFromUserState,\n toAAWalletCalls,\n toAAWalletCall,\n appendFeeCallToPayload,\n buildFeeAAWalletCall,\n normalizeSimulatedFee,\n MAX_AUTO_FEE_WEI,\n executeWalletCalls,\n DISABLED_PROVIDER_STATE,\n parseChainId,\n aaModeFromExecutionKind,\n} from \"@aomi-labs/client\";\n\n// =============================================================================\n// Runtime Provider\n// =============================================================================\nexport { AomiRuntimeProvider } from \"./runtime/aomi-runtime\";\nexport type { AomiRuntimeProviderProps } from \"./runtime/aomi-runtime\";\nexport { RuntimeUserStateProvider } from \"./runtime/user-state-provider\";\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 WalletSolanaSignPayload,\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 { useUser, UserContextProvider, UserState } 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 {\n ModelSelectionMode,\n ThreadMetadata,\n ThreadControlState,\n} 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\";\nexport { resolveAutoModel } from \"./utils/model-selection\";\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 StoredModelPreference,\n type StoredProviderKey,\n} from \"./contexts/control-context\";\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\n\nimport { AomiClient, UserState, type AomiClientOptions } 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 clientOptions?: Omit<AomiClientOptions, \"baseUrl\">;\n};\n\n// =============================================================================\n// Provider Shell\n// =============================================================================\n\nexport function AomiRuntimeProvider({\n children,\n backendUrl = \"http://localhost:8080\",\n clientOptions,\n}: Readonly<AomiRuntimeProviderProps>) {\n const aomiClient = useMemo(\n () => new AomiClient({ baseUrl: backendUrl, ...clientOptions }),\n [backendUrl, clientOptions],\n );\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={\n UserState.isConnected(user) ? (UserState.address(user) ?? undefined) : undefined\n }\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 {\n ModelSelectionMode,\n ThreadMetadata,\n ThreadControlState,\n} from \"../state/thread-store\";\nimport { initThreadControl } from \"../state/thread-store\";\nimport { resolveAutoModel } from \"../utils/model-selection\";\nimport {\n CLIENT_ID_STORAGE_KEY,\n getControlSessionId,\n getOrCreateClientId,\n} from \"../utils/client-session\";\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\nexport type StoredModelPreference = {\n mode: ModelSelectionMode;\n model: string | null;\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: (\n secrets: Record<string, string>,\n ) => 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: (\n provider: string,\n apiKey: string,\n label?: string,\n ) => 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: (\n model: string,\n options?: { mode?: ModelSelectionMode },\n ) => 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 /** Sync pending control state to the backend before sending */\n syncCurrentThreadControl: () => Promise<void>;\n /** Build initial control state for new local threads */\n getPreferredThreadControl: () => ThreadControlState;\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 PROVIDER_KEYS_STORAGE_KEY = \"aomi_provider_keys\";\nconst MODEL_SELECTION_STORAGE_KEY = \"aomi_model_selection\";\nconst PROVIDER_KEY_SECRET_PREFIX = \"PROVIDER_KEY:\";\n\nfunction getDefaultApp(apps: string[]): string | null {\n return apps.includes(\"default\") ? \"default\" : (apps[0] ?? null);\n}\n\nfunction readStoredModelPreference(): StoredModelPreference {\n try {\n const raw = globalThis.localStorage?.getItem(MODEL_SELECTION_STORAGE_KEY);\n if (!raw) return { mode: \"auto\", model: null };\n const parsed = JSON.parse(raw) as Partial<StoredModelPreference>;\n return {\n mode: parsed.mode === \"manual\" ? \"manual\" : \"auto\",\n model: typeof parsed.model === \"string\" ? parsed.model : null,\n };\n } catch {\n return { mode: \"auto\", model: null };\n }\n}\n\nfunction writeStoredModelPreference(preference: StoredModelPreference): void {\n try {\n globalThis.localStorage?.setItem(\n MODEL_SELECTION_STORAGE_KEY,\n JSON.stringify(preference),\n );\n } catch {\n // localStorage not available\n }\n}\n\nfunction resolvePreferredModelSelection(\n preference: StoredModelPreference,\n models: string[],\n defaultModel: string | null,\n): StoredModelPreference {\n if (\n preference.mode === \"manual\" &&\n preference.model &&\n models.includes(preference.model)\n ) {\n return preference;\n }\n\n if (preference.mode === \"auto\") {\n return {\n mode: \"auto\",\n model: resolveAutoModel(models) ?? defaultModel,\n };\n }\n\n return {\n mode: \"auto\",\n model: defaultModel ?? resolveAutoModel(models),\n };\n}\n\nfunction getFallbackModel(\n models: string[],\n defaultModel: string | null,\n): string | null {\n return defaultModel ?? resolveAutoModel(models);\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 const getCurrentControlSessionId = useCallback(\n () => getControlSessionId(stateRef.current.clientId, sessionIdRef.current),\n [],\n );\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 so settings page and chat runtime share one 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\n .ingestSecrets(getCurrentControlSessionId(), state.clientId, secrets)\n .catch((err: unknown) => {\n console.error(\"Failed to auto-ingest provider keys:\", err);\n });\n }, [getCurrentControlSessionId, state.clientId, state.providerKeys]);\n\n // Fetch apps whenever the auth context changes. App authorization is scoped\n // to auth/api-key state, so thread switches should not refetch it.\n useEffect(() => {\n const fetchApps = async () => {\n try {\n const apps = await aomiClientRef.current.getApps(\n getCurrentControlSessionId(),\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 }, [getCurrentControlSessionId, state.apiKey, publicKey]);\n\n // Fetch models on mount\n useEffect(() => {\n const fetchModels = async () => {\n try {\n const models = await aomiClientRef.current.getModels(\n getCurrentControlSessionId(),\n );\n setStateInternal((prev) => ({\n ...prev,\n availableModels: models,\n defaultModel: resolveAutoModel(models),\n }));\n } catch (error) {\n console.error(\"Failed to fetch models:\", error);\n }\n };\n void fetchModels();\n }, [getCurrentControlSessionId]);\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 (\n secrets: Record<string, string>,\n ): 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 getCurrentControlSessionId(),\n clientId,\n secrets,\n );\n return handles;\n },\n [getCurrentControlSessionId],\n );\n\n const clearSecrets = useCallback(async (): Promise<void> => {\n const clientId = stateRef.current.clientId;\n if (!clientId) return;\n await aomiClientRef.current.clearSecrets?.(\n getCurrentControlSessionId(),\n clientId,\n );\n }, [getCurrentControlSessionId]);\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(\n getCurrentControlSessionId(),\n clientId,\n {\n [`${PROVIDER_KEY_SECRET_PREFIX}${provider}`]: trimmed,\n },\n );\n } catch (err) {\n console.error(\"Failed to ingest provider key:\", err);\n }\n }\n },\n [getCurrentControlSessionId],\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 getCurrentControlSessionId(),\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 [getCurrentControlSessionId],\n );\n\n const getProviderKeys = useCallback(\n (): Record<string, StoredProviderKey> => stateRef.current.providerKeys,\n [],\n );\n\n const hasProviderKey = useCallback((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 // Fetch available options\n // ---------------------------------------------------------------------------\n const getAvailableModels = useCallback(async (): Promise<string[]> => {\n try {\n const models = await aomiClientRef.current.getModels(\n getCurrentControlSessionId(),\n );\n setStateInternal((prev) => ({\n ...prev,\n availableModels: models,\n defaultModel: resolveAutoModel(models),\n }));\n return models;\n } catch (error) {\n console.error(\"Failed to fetch models:\", error);\n return [];\n }\n }, [getCurrentControlSessionId]);\n\n const getAuthorizedApps = useCallback(async (): Promise<string[]> => {\n try {\n const apps = await aomiClientRef.current.getApps(\n getCurrentControlSessionId(),\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 }, [getCurrentControlSessionId]);\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 getPreferredThreadControl = useCallback((): ThreadControlState => {\n const preference = readStoredModelPreference();\n const selection = resolvePreferredModelSelection(\n preference,\n stateRef.current.availableModels,\n stateRef.current.defaultModel,\n );\n return {\n ...initThreadControl(),\n model: selection.model,\n modelMode: selection.mode,\n controlDirty: selection.model !== null,\n };\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(\n async (model: string, options?: { mode?: ModelSelectionMode }) => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n const isProcessing = currentControl.isProcessing;\n const modelMode = options?.mode ?? \"manual\";\n\n console.log(\"[control-context] onModelSelect called\", {\n model,\n modelMode,\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 modelMode,\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(threadId, model, {\n app,\n apiKey: stateRef.current.apiKey ?? undefined,\n clientId: stateRef.current.clientId ?? undefined,\n });\n console.log(\"[control-context] onModelSelect backend result\", result);\n writeStoredModelPreference({\n mode: modelMode,\n model: modelMode === \"manual\" ? model : null,\n });\n const latestControl =\n getThreadMetadataRef.current(threadId)?.control ?? currentControl;\n if (latestControl.model === model && latestControl.app === app) {\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...latestControl,\n modelMode,\n controlDirty: false,\n },\n });\n }\n } catch (err) {\n console.error(\"[control-context] setModel failed:\", err);\n throw err;\n }\n },\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(\"[control-context] Cannot switch app while processing\");\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 const syncCurrentThreadControl = useCallback(async () => {\n const threadId = sessionIdRef.current;\n const currentControl =\n getThreadMetadataRef.current(threadId)?.control ?? initThreadControl();\n\n if (\n !currentControl.controlDirty ||\n currentControl.isProcessing ||\n !currentControl.model\n ) {\n return;\n }\n\n const app =\n resolveAuthorizedApp(\n currentControl.app,\n stateRef.current.authorizedApps,\n stateRef.current.defaultApp,\n ) ?? \"default\";\n\n await aomiClientRef.current.setModel(threadId, currentControl.model, {\n app,\n apiKey: stateRef.current.apiKey ?? undefined,\n clientId: stateRef.current.clientId ?? undefined,\n });\n\n const latestControl =\n getThreadMetadataRef.current(threadId)?.control ?? currentControl;\n if (\n latestControl.model === currentControl.model &&\n latestControl.app === currentControl.app\n ) {\n updateThreadMetadataRef.current(threadId, {\n control: {\n ...latestControl,\n app,\n controlDirty: false,\n },\n });\n }\n }, []);\n\n useEffect(() => {\n const threadId = sessionIdRef.current;\n const metadata = getThreadMetadataRef.current(threadId);\n if (!metadata || metadata.control.isProcessing) return;\n\n const currentControl = metadata.control;\n let nextControl: ThreadControlState | null = null;\n\n if (currentControl.model === null) {\n const preferred = getPreferredThreadControl();\n if (!preferred.model) return;\n nextControl = {\n ...currentControl,\n model: preferred.model,\n modelMode: preferred.modelMode,\n controlDirty: true,\n };\n } else if (state.availableModels.length > 0) {\n const currentMode = currentControl.modelMode ?? \"manual\";\n\n if (currentMode === \"auto\") {\n const autoModel = getFallbackModel(\n state.availableModels,\n state.defaultModel,\n );\n if (autoModel && currentControl.model !== autoModel) {\n nextControl = {\n ...currentControl,\n model: autoModel,\n modelMode: \"auto\",\n controlDirty: true,\n };\n }\n } else if (!state.availableModels.includes(currentControl.model)) {\n const fallbackModel = getFallbackModel(\n state.availableModels,\n state.defaultModel,\n );\n if (fallbackModel) {\n nextControl = {\n ...currentControl,\n model: fallbackModel,\n modelMode: \"auto\",\n controlDirty: true,\n };\n }\n }\n }\n\n if (!nextControl) return;\n\n updateThreadMetadataRef.current(threadId, {\n control: nextControl,\n });\n }, [\n getPreferredThreadControl,\n sessionId,\n state.availableModels,\n state.defaultModel,\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 syncCurrentThreadControl,\n getPreferredThreadControl,\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\";\nexport type ModelSelectionMode = \"auto\" | \"manual\";\n\nexport type ThreadControlState = {\n /** Selected model for this thread (human-readable label) */\n model: string | null;\n /** Whether the selected model should be displayed as auto or explicit */\n modelMode?: ModelSelectionMode;\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 modelMode: \"auto\",\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 resetToDefault: this.resetToDefault,\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 /** Reset store to a single empty \"New Chat\" thread (e.g. on wallet disconnect). */\n resetToDefault = () => {\n const threadId = generateUUID();\n this.state = {\n currentThreadId: threadId,\n threadViewKey: this.state.threadViewKey + 1,\n threadCnt: 1,\n threads: new Map([[threadId, []]]),\n threadMetadata: new Map([\n [\n threadId,\n {\n title: \"New Chat\",\n status: \"regular\",\n lastActiveAt: new Date().toISOString(),\n control: initThreadControl(),\n },\n ],\n ]),\n };\n this.snapshot = this.buildSnapshot();\n this.emit();\n return 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","/** Models preferred as default, in priority order (cheaper + good performance). */\nconst PREFERRED_DEFAULT_MODEL_PATTERNS: RegExp[] = [\n /^claude-4\\.5-haiku/i,\n /^claude.*haiku/i,\n /^gpt-4o-mini/i,\n /^gemini.*flash/i,\n];\n\n/**\n * Resolve the actual backend model for auto mode.\n * Prefers known cheaper/performance-oriented models before falling back to the\n * backend order.\n */\nexport function resolveAutoModel(models: string[]): string | null {\n if (models.length === 0) return null;\n\n for (const pattern of PREFERRED_DEFAULT_MODEL_PATTERNS) {\n const match = models.find((model) => pattern.test(model));\n if (match) return match;\n }\n\n return models[0] ?? null;\n}\n","\"use client\";\n\nexport const CLIENT_ID_STORAGE_KEY = \"aomi_client_id\";\n\nconst CONTROL_SESSION_PREFIX = \"control:\";\n\nexport function getOrCreateClientId(): string {\n try {\n const storedClientId = globalThis.localStorage?.getItem(\n CLIENT_ID_STORAGE_KEY,\n );\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\nexport function getControlSessionId(\n clientId: string | null | undefined,\n fallbackSessionId: string,\n): string {\n const trimmedClientId = clientId?.trim();\n return trimmedClientId\n ? `${CONTROL_SESSION_PREFIX}${trimmedClientId}`\n : fallbackSessionId;\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 resetToDefault: () => string;\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\";\nimport { UserState } from \"@aomi-labs/client\";\n\nexport { UserState } from \"@aomi-labs/client\";\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 address: undefined,\n chain_id: undefined,\n is_connected: false,\n ens_name: 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 notifyStateChange = useCallback((next: UserState) => {\n queueMicrotask(() => {\n StateChangeCallbacks.current.forEach((callback) => {\n callback(next);\n });\n });\n }, []);\n\n const pruneUndefined = useCallback((state: UserState): UserState => {\n return Object.fromEntries(\n Object.entries(state).filter(([, value]) => value !== undefined),\n );\n }, []);\n\n const setUser = useCallback((data: Partial<UserState>) => {\n setUserState((prev) => {\n const normalizedData = pruneUndefined(UserState.normalize(data) ?? {});\n const nextPartial: UserState = { ...normalizedData };\n\n // Guard against a transient \"connected-without-chain\" payload:\n // keep the previous chain if present; otherwise, delay flipping\n // `is_connected` until a concrete chain arrives.\n if (\n nextPartial.is_connected === true &&\n nextPartial.chain_id === undefined\n ) {\n if (prev.chain_id !== undefined) {\n nextPartial.chain_id = prev.chain_id;\n } else {\n delete nextPartial.is_connected;\n }\n }\n\n const next: UserState =\n nextPartial.is_connected === false\n ? {\n ...(UserState.normalize({ ...prev, ...nextPartial }) ?? prev),\n address: undefined,\n chain_id: undefined,\n ens_name: undefined,\n }\n : (UserState.normalize({ ...prev, ...nextPartial }) ?? prev);\n notifyStateChange(next);\n\n return next;\n });\n }, [notifyStateChange, pruneUndefined]);\n\n const addExtValue = useCallback((key: string, value: unknown) => {\n setUserState((prev) => {\n const next = UserState.withExt(prev, key, value);\n notifyStateChange(next);\n return next;\n });\n }, [notifyStateChange]);\n\n const removeExtValue = useCallback((key: string) => {\n setUserState((prev) => {\n const ext = prev.ext;\n if (\n typeof ext !== \"object\" ||\n ext === null ||\n Array.isArray(ext) ||\n !(key in ext)\n ) {\n return prev;\n }\n const nextExt = { ...(ext as Record<string, unknown>) };\n delete nextExt[key];\n const next: UserState = {\n ...prev,\n ext: Object.keys(nextExt).length > 0 ? nextExt : undefined,\n };\n notifyStateChange(next);\n return next;\n });\n }, [notifyStateChange]);\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, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {\n AssistantRuntimeProvider,\n useExternalStoreRuntime,\n type AppendMessage,\n} from \"@assistant-ui/react\";\n\nimport { UserState, 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 { buildThreadListAdapter } from \"./threadlist-adapter\";\nimport { AomiRuntimeApiProvider, type AomiRuntimeApi } from \"../interface\";\nimport { useWalletHandler } from \"../handlers/wallet-handler\";\nimport {\n RuntimeUserStateProvider,\n useRuntimeUserStateEffects,\n} from \"./user-state-provider\";\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 { getUserState } = useUser();\n const {\n getControlState,\n getCurrentThreadApp,\n getPreferredThreadControl,\n syncCurrentThreadControl,\n } = useControl();\n\n // ---------------------------------------------------------------------------\n // Wallet handler (receives requests from orchestrator)\n // ---------------------------------------------------------------------------\n const sessionManagerRef = useRef<\n ReturnType<typeof useRuntimeOrchestrator>[\"sessionManager\"] | null\n >(null);\n\n const walletHandler = useWalletHandler({\n getSession: () =>\n 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 closeSession,\n closeIdleSessionsExcept,\n closeAllSessions,\n aomiClientRef,\n } = useRuntimeOrchestrator(aomiClient, {\n getPublicKey: () =>\n UserState.isConnected(getUserState())\n ? UserState.address(getUserState())\n : undefined,\n getUserState,\n getApp: getCurrentThreadApp,\n getApiKey: () => getControlState().apiKey,\n getClientId: () => getControlState().clientId ?? undefined,\n prepareThreadForSend: async (threadId) => {\n await ensureBackendThread(threadId);\n await syncCurrentThreadControl();\n },\n onPendingRequestsChange: walletHandler.setRequests,\n onEvent: (event) => eventContext.dispatch(event),\n });\n\n sessionManagerRef.current = sessionManager;\n\n // ---------------------------------------------------------------------------\n // Refs for stable access\n // ---------------------------------------------------------------------------\n const threadContextRef = useRef(threadContext);\n threadContextRef.current = threadContext;\n const remoteThreadIdsRef = useRef(new Set<string>());\n const warmedThreadIdsRef = useRef(new Set<string>());\n const warmPromisesRef = useRef(new Map<string, Promise<void>>());\n const [isThreadLoading, setIsThreadLoading] = useState(false);\n\n const warmThread = useCallback(\n async (threadId: string) => {\n if (\n !remoteThreadIdsRef.current.has(threadId) ||\n warmedThreadIdsRef.current.has(threadId)\n ) {\n return;\n }\n\n const existingPromise = warmPromisesRef.current.get(threadId);\n if (existingPromise) {\n return existingPromise;\n }\n\n const warmPromise = (async () => {\n const userState = getUserState();\n await aomiClientRef.current.createThread(\n threadId,\n UserState.isConnected(userState)\n ? UserState.address(userState)\n : undefined,\n );\n warmedThreadIdsRef.current.add(threadId);\n })();\n\n warmPromisesRef.current.set(threadId, warmPromise);\n\n try {\n await warmPromise;\n } finally {\n warmPromisesRef.current.delete(threadId);\n }\n },\n [aomiClientRef, getUserState],\n );\n\n // ---------------------------------------------------------------------------\n // Ensure backend thread exists (lazy creation on first message send)\n // ---------------------------------------------------------------------------\n const ensureBackendThread = useCallback(\n async (threadId: string) => {\n if (remoteThreadIdsRef.current.has(threadId)) return;\n\n const userState = getUserState();\n await aomiClientRef.current.createThread(\n threadId,\n UserState.isConnected(userState)\n ? UserState.address(userState)\n : undefined,\n );\n remoteThreadIdsRef.current.add(threadId);\n warmedThreadIdsRef.current.add(threadId);\n },\n [aomiClientRef, getUserState],\n );\n\n const getRuntimeSession = useCallback(\n (threadId: string) =>\n sessionManagerRef.current?.get(threadId) ?? getSession(threadId),\n [getSession],\n );\n\n const { isThreadListLoading } = useRuntimeUserStateEffects({\n sessions: {\n aomiClientRef,\n sessionManager,\n getSession: getRuntimeSession,\n closeAllSessions,\n ensureInitialState,\n setIsThreadLoading,\n },\n remoteThreads: {\n remoteThreadIdsRef,\n warmPromisesRef,\n warmedThreadIdsRef,\n warmThread,\n },\n });\n\n // ---------------------------------------------------------------------------\n // Initial state fetch on thread change (skip for local-only threads)\n // ---------------------------------------------------------------------------\n useEffect(() => {\n const threadId = threadContext.currentThreadId;\n closeIdleSessionsExcept(threadId);\n\n if (!remoteThreadIdsRef.current.has(threadId)) {\n setIsThreadLoading(false);\n return;\n }\n\n let cancelled = false;\n setIsThreadLoading(true);\n\n void (async () => {\n try {\n await warmThread(threadId);\n if (!cancelled) {\n await ensureInitialState(threadId);\n }\n } finally {\n if (!cancelled) {\n setIsThreadLoading(false);\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n closeIdleSessionsExcept,\n ensureInitialState,\n threadContext.currentThreadId,\n warmThread,\n ]);\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 // Thread list adapter\n // ---------------------------------------------------------------------------\n const isRemoteThread = useCallback(\n (threadId: string) => remoteThreadIdsRef.current.has(threadId),\n [],\n );\n\n const threadListAdapter = useMemo(\n () =>\n buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n isLoading: isThreadListLoading,\n getInitialControl: getPreferredThreadControl,\n isRemoteThread,\n }),\n [\n aomiClientRef,\n getPreferredThreadControl,\n isRemoteThread,\n isThreadListLoading,\n setIsRunning,\n threadContext,\n threadContext.currentThreadId,\n threadContext.allThreadsMetadata,\n currentMessages,\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 isLoading: isThreadLoading,\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 closeAllSessions();\n };\n }, [closeAllSessions]);\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 closeSession(threadId);\n await threadListAdapter.onDelete(threadId);\n },\n [closeSession, 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 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 simulateBatchTransactions = useCallback<\n AomiRuntimeApi[\"simulateBatchTransactions\"]\n >(\n async (transactions, options) => {\n const session =\n sessionManagerRef.current?.get(threadContext.currentThreadId) ??\n getSession(threadContext.currentThreadId);\n if (!session) {\n throw new Error(\"runtime_session_unavailable\");\n }\n\n const response = await session.client.simulateBatch(\n session.sessionId,\n transactions,\n options,\n );\n return response.result;\n },\n [getSession, threadContext.currentThreadId],\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.startRequest,\n resolveWalletRequest: walletHandler.resolveRequest,\n rejectWalletRequest: walletHandler.rejectRequest,\n simulateBatchTransactions,\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 simulateBatchTransactions,\n eventContext,\n ],\n );\n\n return (\n <AomiRuntimeApiProvider value={aomiRuntimeApi}>\n <RuntimeUserStateProvider\n sessionManager={sessionManager}\n getUserState={userContext.getUserState}\n onUserStateChange={userContext.onUserStateChange}\n >\n <AssistantRuntimeProvider runtime={runtime}>\n {children}\n </AssistantRuntimeProvider>\n </RuntimeUserStateProvider>\n </AomiRuntimeApiProvider>\n );\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { ThreadMessageLike } from \"@assistant-ui/react\";\n\nimport type { AomiClient, UserState, WalletRequest } from \"@aomi-labs/client\";\nimport { CLIENT_TYPE_WEB_UI } from \"@aomi-labs/client\";\nimport { Session as ClientSession } from \"@aomi-labs/client\";\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 prepareThreadForSend?: (threadId: string) => Promise<void> | void;\n onPendingRequestsChange?: (requests: WalletRequest[]) => void;\n onEvent?: (event: {\n type: string;\n payload: unknown;\n sessionId: string;\n }) => void;\n};\n\ntype OptimisticSendStatus = \"sending\" | \"sent\" | \"failed\";\n\nconst toErrorMessage = (error: unknown) =>\n error instanceof Error ? error.message : \"Message failed to send\";\n\nconst getOptimisticStatus = (message: ThreadMessageLike) => {\n const status = message.metadata?.custom?.aomiSendStatus;\n return status === \"sending\" || status === \"sent\" || status === \"failed\"\n ? status\n : undefined;\n};\n\nconst hasUnhydratedOptimisticMessage = (messages: ThreadMessageLike[]) =>\n messages.some((message) => {\n const status = getOptimisticStatus(message);\n return status === \"sending\" || status === \"sent\";\n });\n\nconst withOptimisticStatus = (\n message: ThreadMessageLike,\n status: OptimisticSendStatus,\n error?: unknown,\n): ThreadMessageLike => {\n const custom: Record<string, unknown> = {\n ...(message.metadata?.custom ?? {}),\n aomiSendStatus: status,\n };\n\n if (error) {\n custom.aomiSendError = toErrorMessage(error);\n } else {\n delete custom.aomiSendError;\n }\n\n return {\n ...message,\n metadata: {\n ...message.metadata,\n custom,\n },\n };\n};\n\nconst updateOptimisticMessage = (\n threadContext: ThreadContext,\n threadId: string,\n messageId: string,\n status: OptimisticSendStatus,\n error?: unknown,\n) => {\n const messages = threadContext.getThreadMessages(threadId);\n let changed = false;\n const nextMessages = messages.map((message) => {\n if (message.id !== messageId) return message;\n changed = true;\n return withOptimisticStatus(message, status, error);\n });\n\n if (changed) {\n threadContext.setThreadMessages(threadId, nextMessages);\n }\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 optionsRef = useRef(options);\n optionsRef.current = options;\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 const initialStatePromises = useRef<Map<string, Promise<void>>>(new Map());\n const hydratedThreadIds = useRef<Set<string>>(new Set());\n // Track event listener cleanup per thread\n const listenerCleanups = useRef<Map<string, () => void>>(new Map());\n\n const cleanupSessionListeners = useCallback((threadId: string) => {\n listenerCleanups.current.get(threadId)?.();\n listenerCleanups.current.delete(threadId);\n }, []);\n\n const closeSession = useCallback(\n (threadId: string) => {\n cleanupSessionListeners(threadId);\n pendingFetches.current.delete(threadId);\n initialStatePromises.current.delete(threadId);\n hydratedThreadIds.current.delete(threadId);\n sessionManagerRef.current?.close(threadId);\n },\n [cleanupSessionListeners],\n );\n\n const closeIdleSessionsExcept = useCallback(\n (activeThreadId: string) => {\n const closedThreadIds =\n sessionManagerRef.current?.closeIdleExcept(\n activeThreadId,\n cleanupSessionListeners,\n ) ?? [];\n\n for (const threadId of closedThreadIds) {\n pendingFetches.current.delete(threadId);\n initialStatePromises.current.delete(threadId);\n hydratedThreadIds.current.delete(threadId);\n }\n\n return closedThreadIds;\n },\n [cleanupSessionListeners],\n );\n\n const closeAllSessions = useCallback(() => {\n pendingFetches.current.clear();\n initialStatePromises.current.clear();\n hydratedThreadIds.current.clear();\n for (const threadId of Array.from(listenerCleanups.current.keys())) {\n cleanupSessionListeners(threadId);\n }\n sessionManagerRef.current?.closeAll();\n }, [cleanupSessionListeners]);\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 nextOptions = optionsRef.current;\n const nextApp = nextOptions.getApp();\n const nextPublicKey = nextOptions.getPublicKey?.();\n const nextApiKey = nextOptions.getApiKey?.() ?? undefined;\n const nextClientId = nextOptions.getClientId?.();\n const nextUserState = nextOptions.getUserState?.();\n const existing = manager.get(threadId);\n if (existing) {\n existing.syncRuntimeOptions({\n app: nextApp,\n publicKey: nextPublicKey,\n apiKey: nextApiKey,\n clientId: nextClientId,\n userState: nextUserState,\n });\n return existing;\n }\n\n const session = manager.getOrCreate(threadId, {\n app: nextApp,\n publicKey: nextPublicKey,\n apiKey: nextApiKey,\n clientId: nextClientId,\n clientType: CLIENT_TYPE_WEB_UI,\n syncPendingTxRequestsFromUserState: false,\n userState: nextUserState,\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 const existingMessages =\n threadContextRef.current.getThreadMessages(threadId);\n if (\n threadMessages.length === 0 &&\n hasUnhydratedOptimisticMessage(existingMessages)\n ) {\n return;\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 cleanups.push(\n session.on(\"wallet_requests_changed\", (requests) =>\n optionsRef.current.onPendingRequestsChange?.(requests),\n ),\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(\n type as keyof import(\"@aomi-labs/client\").SessionEventMap,\n (payload: unknown) => {\n optionsRef.current.onEvent?.({\n type,\n payload,\n sessionId: threadId,\n });\n },\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 cleanups.push(forwardEvent(\"user_state_request\"));\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 const existingPromise = initialStatePromises.current.get(threadId);\n if (existingPromise) {\n return existingPromise;\n }\n\n const cachedMessages =\n threadContextRef.current.getThreadMessages(threadId);\n const existingSession = sessionManagerRef.current?.get(threadId);\n if (\n existingSession &&\n (hydratedThreadIds.current.has(threadId) || cachedMessages.length > 0)\n ) {\n optionsRef.current.onPendingRequestsChange?.(\n existingSession.getPendingRequests(),\n );\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(existingSession.getIsProcessing());\n }\n return;\n }\n\n const fetchPromise = (async () => {\n pendingFetches.current.add(threadId);\n\n try {\n const session = getSession(threadId);\n await session.fetchCurrentState();\n hydratedThreadIds.current.add(threadId);\n optionsRef.current.onPendingRequestsChange?.(\n session.getPendingRequests(),\n );\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 initialStatePromises.current.delete(threadId);\n }\n })();\n\n initialStatePromises.current.set(threadId, fetchPromise);\n return fetchPromise;\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 existingMessages =\n threadContextRef.current.getThreadMessages(threadId);\n const optimisticMessageId = String(existingMessages.length);\n const userMessage: ThreadMessageLike = {\n id: optimisticMessageId,\n role: \"user\",\n content: [{ type: \"text\", text }],\n createdAt: new Date(),\n metadata: {\n custom: {\n aomiOriginalText: text,\n aomiSendStatus: \"sending\",\n },\n },\n };\n threadContextRef.current.setThreadMessages(threadId, [\n ...existingMessages,\n userMessage,\n ]);\n threadContextRef.current.updateThreadMetadata(threadId, {\n lastActiveAt: new Date().toISOString(),\n });\n\n // Immediately show \"generating\" state so the UI switches to the stop\n // button and displays a loading indicator while the message is in flight.\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(true);\n }\n\n try {\n await optionsRef.current.prepareThreadForSend?.(threadId);\n const session = getSession(threadId);\n await session.sendAsync(text);\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(session.getIsProcessing());\n }\n updateOptimisticMessage(\n threadContextRef.current,\n threadId,\n optimisticMessageId,\n \"sent\",\n );\n optionsRef.current.onPendingRequestsChange?.(\n session.getPendingRequests(),\n );\n } catch (error) {\n if (threadContextRef.current.currentThreadId === threadId) {\n setIsRunning(false);\n }\n updateOptimisticMessage(\n threadContextRef.current,\n threadId,\n optimisticMessageId,\n \"failed\",\n error,\n );\n throw error;\n }\n },\n [getSession],\n );\n\n /** Cancel the current generation on the given thread. */\n const cancelGeneration = useCallback(async (threadId: string) => {\n const session = sessionManagerRef.current?.get(threadId);\n if (session) {\n await session.interrupt();\n }\n }, []);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n closeAllSessions();\n };\n }, [closeAllSessions]);\n\n return {\n sessionManager: sessionManagerRef.current!,\n getSession,\n isRunning,\n setIsRunning,\n ensureInitialState,\n sendMessage,\n cancelGeneration,\n closeSession,\n closeAllSessions,\n closeIdleSessionsExcept,\n aomiClientRef,\n };\n}\n","// =============================================================================\n// SessionManager — manages one ClientSession per thread\n// =============================================================================\n\nimport type { AomiClient } from \"@aomi-labs/client\";\nimport {\n Session as ClientSession,\n type SessionOptions,\n} from \"@aomi-labs/client\";\n\nexport class SessionManager {\n private sessions = new Map<string, ClientSession>();\n\n constructor(private readonly clientFactory: () => AomiClient) {}\n\n getOrCreate(\n threadId: string,\n opts: Omit<SessionOptions, \"sessionId\">,\n ): 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 get size(): number {\n return this.sessions.size;\n }\n\n forEach(callback: (session: ClientSession, threadId: string) => void): void {\n for (const [threadId, session] of this.sessions) {\n callback(session, threadId);\n }\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 closeIdleExcept(\n activeThreadId: string,\n onBeforeClose?: (threadId: string) => void,\n ): string[] {\n const closedThreadIds: string[] = [];\n\n for (const [threadId, session] of this.sessions) {\n if (threadId === activeThreadId) continue;\n if (session.getIsProcessing()) continue;\n if (session.getIsPolling()) continue;\n if (session.getPendingRequests().length > 0) continue;\n\n closedThreadIds.push(threadId);\n }\n\n for (const threadId of closedThreadIds) {\n onBeforeClose?.(threadId);\n this.close(threadId);\n }\n\n return closedThreadIds;\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 \"@aomi-labs/client\";\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 { initThreadControl, type ThreadMetadata } from \"../state/thread-store\";\nimport type { ThreadControlState } 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(\n threadMetadata: Map<string, ThreadMetadata>,\n shouldShowThread: (threadId: string) => boolean,\n) {\n const entries = Array.from(threadMetadata.entries()).filter(\n ([threadId, meta]) =>\n !isPlaceholderTitle(meta.title) && shouldShowThread(threadId),\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 isLoading?: boolean;\n getInitialControl?: () => ThreadControlState;\n isRemoteThread?: (threadId: string) => boolean;\n};\n\nexport function buildThreadListAdapter({\n aomiClientRef,\n threadContext,\n setIsRunning,\n isLoading = false,\n getInitialControl = initThreadControl,\n isRemoteThread = () => true,\n}: ThreadListAdapterConfig) {\n const shouldShowThread = (threadId: string) => {\n if (isRemoteThread(threadId)) return true;\n\n return threadContext\n .getThreadMessages(threadId)\n .some((message) => message.role === \"user\");\n };\n const { regularThreads, archivedThreads } = buildThreadLists(\n threadContext.allThreadsMetadata,\n shouldShowThread,\n );\n\n /** Remove previous thread if it's local-only and has no messages. */\n const cleanupEmptyLocalThread = () => {\n const prevId = threadContext.currentThreadId;\n if (isRemoteThread(prevId)) return;\n const msgs = threadContext.getThreadMessages(prevId);\n if (msgs.length > 0) return;\n threadContext.setThreadMetadata((prev) => {\n const next = new Map(prev);\n next.delete(prevId);\n return next;\n });\n threadContext.setThreads((prev) => {\n const next = new Map(prev);\n next.delete(prevId);\n return next;\n });\n };\n\n return {\n threadId: threadContext.currentThreadId,\n isLoading,\n threads: regularThreads,\n archivedThreads,\n\n onSwitchToNewThread: () => {\n cleanupEmptyLocalThread();\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: getInitialControl(),\n }),\n );\n threadContext.setThreadMessages(threadId, []);\n threadContext.setCurrentThreadId(threadId);\n setIsRunning(false);\n threadContext.bumpThreadViewKey();\n },\n\n onSwitchToThread: (threadId: string) => {\n cleanupEmptyLocalThread();\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: getInitialControl(),\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 { AomiSimulateResponse, UserState } from \"@aomi-labs/client\";\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 { WalletRequest } from \"./handlers/wallet-handler\";\nimport type { WalletRequestResult } from \"@aomi-labs/client\";\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 in-flight — suppresses it from the pending list until acked */\n startWalletRequest: (id: string) => void;\n /** Complete a wallet request after the backend acknowledges the response */\n resolveWalletRequest: (\n id: string,\n result: WalletRequestResult,\n ) => Promise<void>;\n /** Fail a wallet request after the backend acknowledges the error */\n rejectWalletRequest: (id: string, error?: string) => Promise<void>;\n /** Simulate a batch against the current thread session context. */\n simulateBatchTransactions: (\n transactions: Array<{\n to: string;\n value?: string;\n data?: string;\n label?: string;\n chain_id?: number;\n chainId?: number;\n }>,\n options?: { from?: string; chainId?: number },\n ) => Promise<AomiSimulateResponse[\"result\"]>;\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 WalletSolanaSignPayload,\n WalletTxPayload,\n WalletRequest,\n WalletRequestKind,\n WalletRequestResult,\n} from \"@aomi-labs/client\";\nimport type { Session as ClientSession } from \"@aomi-labs/client\";\n\n// Re-export types consumers need. The source of truth for `WalletRequestKind`\n// is `@aomi-labs/client` — Solana adds a third arm there.\nexport type {\n WalletRequest,\n WalletRequestKind,\n WalletRequestResult,\n WalletTxPayload,\n WalletEip712Payload,\n WalletSolanaSignPayload,\n};\n\nexport type WalletRequestStatus = \"pending\" | \"processing\";\n\nexport type WalletHandlerConfig = {\n /** Get the ClientSession for the current thread. */\n getSession: () => ClientSession | undefined;\n};\n\nexport type WalletHandlerApi = {\n /**\n * All queued wallet requests across every supported kind: EVM txs\n * (`kind: \"transaction\"`), EIP-712 signs (`kind: \"eip712_sign\"`), and\n * Solana signs (`kind: \"solana_sign\"`). Consumers should narrow on\n * `request.kind` before reading `request.payload` — the discriminated\n * union auto-narrows the payload type.\n */\n pendingRequests: WalletRequest[];\n /** Replace pending requests with the session's authoritative snapshot. */\n setRequests: (requests: WalletRequest[]) => void;\n /** Mark a request as in-flight so it is not replayed while awaiting backend ack. */\n startRequest: (id: string) => void;\n /**\n * Complete a request successfully — sends the response wire event to\n * the backend via ClientSession. The `result.kind` discriminator must\n * match the originating request's kind (e.g. `{ kind: \"solana_sign\",\n * signedTx: \"...\" }` for a Solana request); ClientSession runtime-checks\n * this and throws on mismatch.\n */\n resolveRequest: (id: string, result: WalletRequestResult) => Promise<void>;\n /** Fail a request — sends error to backend via ClientSession */\n rejectRequest: (id: string, error?: string) => Promise<void>;\n};\n\nexport function useWalletHandler({\n getSession,\n}: WalletHandlerConfig): WalletHandlerApi {\n const [pendingRequests, setPendingRequests] = useState<WalletRequest[]>([]);\n const requestsRef = useRef<WalletRequest[]>(pendingRequests);\n const inFlightRequestSetRef = useRef<Set<string>>(new Set());\n const suppressedRequestSetRef = useRef<Set<string>>(new Set());\n\n const syncVisibleRequests = useCallback(() => {\n setPendingRequests(\n requestsRef.current.filter(\n (request) => !suppressedRequestSetRef.current.has(request.id),\n ),\n );\n }, []);\n\n const setRequests = useCallback((requests: WalletRequest[]) => {\n const incomingIds = new Set(requests.map((request) => request.id));\n for (const id of suppressedRequestSetRef.current) {\n if (\n !incomingIds.has(id) &&\n !inFlightRequestSetRef.current.has(id)\n ) {\n suppressedRequestSetRef.current.delete(id);\n }\n }\n\n const preservedInFlight = requestsRef.current.filter(\n (request) =>\n inFlightRequestSetRef.current.has(request.id) &&\n !incomingIds.has(request.id),\n );\n\n requestsRef.current = [...requests, ...preservedInFlight];\n syncVisibleRequests();\n }, [syncVisibleRequests]);\n\n const startRequest = useCallback((id: string) => {\n if (!requestsRef.current.some((request) => request.id === id)) {\n return;\n }\n\n inFlightRequestSetRef.current.add(id);\n suppressedRequestSetRef.current.add(id);\n syncVisibleRequests();\n }, [syncVisibleRequests]);\n\n const resolveRequest = useCallback(\n async (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 startRequest(id);\n\n try {\n await session.resolve(id, result);\n } catch (err) {\n console.error(\"[wallet-handler] Failed to resolve request:\", err);\n } finally {\n requestsRef.current = requestsRef.current.filter(\n (request) => request.id !== id,\n );\n inFlightRequestSetRef.current.delete(id);\n syncVisibleRequests();\n }\n },\n [getSession, startRequest, syncVisibleRequests],\n );\n\n const rejectRequest = useCallback(\n async (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 startRequest(id);\n\n try {\n await session.reject(id, error);\n } catch (err) {\n console.error(\"[wallet-handler] Failed to reject request:\", err);\n } finally {\n requestsRef.current = requestsRef.current.filter(\n (request) => request.id !== id,\n );\n inFlightRequestSetRef.current.delete(id);\n syncVisibleRequests();\n }\n },\n [getSession, startRequest, syncVisibleRequests],\n );\n\n return {\n pendingRequests,\n setRequests,\n startRequest,\n resolveRequest,\n rejectRequest,\n };\n}\n","\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type MutableRefObject,\n type ReactNode,\n} from \"react\";\nimport type { AomiClient, UserState } from \"@aomi-labs/client\";\nimport { UserState as UserStateHelpers } from \"@aomi-labs/client\";\n\nimport {\n useControl,\n type ControlState,\n} from \"../contexts/control-context\";\nimport { useEventContext } from \"../contexts/event-context\";\nimport type { ThreadContext } from \"../contexts/thread-context\";\nimport { useThreadContext } from \"../contexts/thread-context\";\nimport { useUser } from \"../contexts/user-context\";\nimport { initThreadControl } from \"../state/thread-store\";\nimport { getControlSessionId } from \"../utils/client-session\";\nimport { isPlaceholderTitle } from \"./utils\";\nimport { SessionManager } from \"./session-manager\";\n\nconst THREAD_PREFETCH_LIMIT = 5;\nconst PREFETCH_IDLE_TIMEOUT_MS = 1500;\n\ntype GlobalWithIdleCallback = typeof globalThis & {\n requestIdleCallback?: (\n callback: () => void,\n options?: { timeout?: number },\n ) => number;\n cancelIdleCallback?: (handle: number) => void;\n};\n\nfunction scheduleBackgroundTask(task: () => void): () => void {\n const runtimeGlobal = globalThis as GlobalWithIdleCallback;\n\n if (typeof runtimeGlobal.requestIdleCallback === \"function\") {\n const idleId = runtimeGlobal.requestIdleCallback(task, {\n timeout: PREFETCH_IDLE_TIMEOUT_MS,\n });\n return () => runtimeGlobal.cancelIdleCallback?.(idleId);\n }\n\n const timeoutId = runtimeGlobal.setTimeout(task, 0);\n return () => runtimeGlobal.clearTimeout(timeoutId);\n}\n\ntype RuntimeUserStateProviderProps = {\n children: ReactNode;\n sessionManager: SessionManager;\n getUserState: () => UserState;\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n};\n\ntype RuntimeSessionBridge = {\n aomiClientRef: MutableRefObject<AomiClient>;\n sessionManager: SessionManager;\n getSession: (threadId: string) => { getUserState(): UserState | undefined };\n closeAllSessions: () => void;\n ensureInitialState: (threadId: string) => Promise<void>;\n setIsThreadLoading: (loading: boolean) => void;\n};\n\ntype RemoteThreadRegistry = {\n remoteThreadIdsRef: MutableRefObject<Set<string>>;\n warmPromisesRef: MutableRefObject<Map<string, Promise<void>>>;\n warmedThreadIdsRef: MutableRefObject<Set<string>>;\n warmThread: (threadId: string) => Promise<void>;\n};\n\ntype RuntimeUserStateEffectsOptions = {\n sessions: RuntimeSessionBridge;\n remoteThreads: RemoteThreadRegistry;\n};\n\ntype RuntimeUserStateContext = {\n getControlState: () => ControlState;\n getUserState: () => UserState;\n onUserStateChange: (callback: (user: UserState) => void) => () => void;\n threadContextRef: MutableRefObject<ThreadContext>;\n user: UserState;\n};\n\nfunction stableStateString(state: UserState): string {\n return JSON.stringify(state ?? {});\n}\n\nfunction useWalletStateSync(\n context: Pick<\n RuntimeUserStateContext,\n \"getUserState\" | \"onUserStateChange\" | \"threadContextRef\"\n >,\n sessions: Pick<RuntimeSessionBridge, \"aomiClientRef\">,\n remoteThreads: Pick<RemoteThreadRegistry, \"remoteThreadIdsRef\">,\n) {\n const { getUserState, onUserStateChange, threadContextRef } = context;\n const { aomiClientRef } = sessions;\n const { remoteThreadIdsRef } = remoteThreads;\n\n const walletSnapshot = useCallback(\n (nextUser: ReturnType<typeof getUserState>) => ({\n address: UserStateHelpers.address(nextUser),\n chain_id: UserStateHelpers.chainId(nextUser),\n is_connected: UserStateHelpers.isConnected(nextUser) ?? false,\n ens_name:\n typeof nextUser.ens_name === \"string\" ? nextUser.ens_name : undefined,\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 const previousAddress = prevWalletState.address?.toLowerCase();\n const nextAddress = nextWalletState.address?.toLowerCase();\n if (\n prevWalletState.address === nextWalletState.address &&\n prevWalletState.chain_id === nextWalletState.chain_id &&\n prevWalletState.is_connected === nextWalletState.is_connected &&\n prevWalletState.ens_name === nextWalletState.ens_name\n ) {\n return;\n }\n\n lastWalletStateRef.current = nextWalletState;\n if (\n previousAddress !== undefined &&\n nextAddress !== undefined &&\n previousAddress !== nextAddress\n ) {\n return;\n }\n\n const sessionId = threadContextRef.current.currentThreadId;\n if (!remoteThreadIdsRef.current.has(sessionId)) {\n return;\n }\n\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 aomiClientRef,\n getUserState,\n onUserStateChange,\n remoteThreadIdsRef,\n threadContextRef,\n walletSnapshot,\n ]);\n}\n\nfunction useUserStateRequestResponder(\n context: Pick<\n RuntimeUserStateContext,\n \"getUserState\" | \"threadContextRef\"\n >,\n sessions: Pick<RuntimeSessionBridge, \"getSession\">,\n) {\n const eventContext = useEventContext();\n const { getUserState, threadContextRef } = context;\n const { getSession } = sessions;\n\n useEffect(() => {\n const unsubscribe = eventContext.subscribe(\"user_state_request\", () => {\n const sessionId = threadContextRef.current.currentThreadId;\n const session = getSession(sessionId);\n const payload =\n UserStateHelpers.reconcile(session.getUserState(), getUserState()) ??\n session.getUserState() ??\n getUserState();\n eventContext.sendOutboundSystem({\n type: \"user_state_response\",\n sessionId,\n payload,\n });\n });\n return unsubscribe;\n }, [eventContext, getSession, getUserState, threadContextRef]);\n}\n\nfunction useRemoteThreadListSync(\n context: RuntimeUserStateContext,\n sessions: RuntimeSessionBridge,\n remoteThreads: RemoteThreadRegistry,\n): { isThreadListLoading: boolean } {\n const [isThreadListLoading, setIsThreadListLoading] = useState(true);\n const prefetchCancelRef = useRef<(() => void) | null>(null);\n const lastConnectedAddressRef = useRef<string | undefined>(undefined);\n const {\n getControlState,\n threadContextRef,\n user,\n } = context;\n const {\n aomiClientRef,\n closeAllSessions,\n ensureInitialState,\n sessionManager,\n setIsThreadLoading,\n } = sessions;\n const {\n remoteThreadIdsRef,\n warmPromisesRef,\n warmedThreadIdsRef,\n warmThread,\n } = remoteThreads;\n\n const scheduleThreadPrefetch = useCallback(\n (threadIds: string[]) => {\n prefetchCancelRef.current?.();\n\n const prefetchThreadIds = Array.from(new Set(threadIds))\n .filter((threadId) => remoteThreadIdsRef.current.has(threadId))\n .slice(0, THREAD_PREFETCH_LIMIT);\n\n if (prefetchThreadIds.length === 0) {\n prefetchCancelRef.current = null;\n return;\n }\n\n let cancelled = false;\n const cancelScheduledTask = scheduleBackgroundTask(() => {\n void Promise.all(\n prefetchThreadIds.map(async (threadId) => {\n if (cancelled || !remoteThreadIdsRef.current.has(threadId)) return;\n if (\n threadContextRef.current.getThreadMessages(threadId).length > 0\n ) {\n return;\n }\n\n try {\n await warmThread(threadId);\n if (cancelled || !remoteThreadIdsRef.current.has(threadId)) {\n return;\n }\n await ensureInitialState(threadId);\n } catch (error) {\n console.debug(\"Failed to prefetch thread:\", threadId, error);\n }\n }),\n );\n });\n\n prefetchCancelRef.current = () => {\n cancelled = true;\n cancelScheduledTask();\n };\n },\n [ensureInitialState, remoteThreadIdsRef, threadContextRef, warmThread],\n );\n\n useEffect(() => {\n const userAddress = UserStateHelpers.isConnected(user)\n ? UserStateHelpers.address(user)\n : undefined;\n const normalizedUserAddress = userAddress?.toLowerCase();\n const previousAddress = lastConnectedAddressRef.current;\n const walletChanged =\n previousAddress !== undefined &&\n normalizedUserAddress !== undefined &&\n previousAddress !== normalizedUserAddress;\n\n if (!userAddress) {\n lastConnectedAddressRef.current = undefined;\n const hadRemoteThreads = remoteThreadIdsRef.current.size > 0;\n const hadSessions = sessionManager.size > 0;\n setIsThreadListLoading(false);\n prefetchCancelRef.current?.();\n prefetchCancelRef.current = null;\n remoteThreadIdsRef.current.clear();\n warmedThreadIdsRef.current.clear();\n warmPromisesRef.current.clear();\n closeAllSessions();\n if (hadRemoteThreads || hadSessions) {\n threadContextRef.current.resetToDefault();\n }\n return;\n }\n\n lastConnectedAddressRef.current = normalizedUserAddress;\n\n const resetThreadId = walletChanged\n ? threadContextRef.current.resetToDefault()\n : undefined;\n\n if (walletChanged) {\n prefetchCancelRef.current?.();\n prefetchCancelRef.current = null;\n remoteThreadIdsRef.current.clear();\n warmedThreadIdsRef.current.clear();\n warmPromisesRef.current.clear();\n closeAllSessions();\n }\n\n let cancelled = false;\n setIsThreadListLoading(true);\n\n const fetchThreadList = async () => {\n try {\n const remoteThreadIdsAtFetchStart = new Set(remoteThreadIdsRef.current);\n const currentContext = threadContextRef.current;\n const controlSessionId = getControlSessionId(\n getControlState().clientId,\n resetThreadId ?? currentContext.currentThreadId,\n );\n const threadList = await aomiClientRef.current.listThreads(\n controlSessionId,\n userAddress,\n );\n if (cancelled) return;\n\n const remoteThreadIds = new Set<string>();\n const newMetadata =\n resetThreadId !== undefined\n ? new Map(\n (() => {\n const resetMetadata =\n threadContextRef.current.getThreadMetadata(resetThreadId);\n return resetMetadata\n ? ([[resetThreadId, resetMetadata]] as const)\n : [];\n })(),\n )\n : new Map(currentContext.allThreadsMetadata);\n const baseThreadCount =\n resetThreadId !== undefined ? 1 : currentContext.threadCnt;\n let maxChatNum = baseThreadCount;\n\n for (const thread of threadList) {\n remoteThreadIds.add(thread.session_id);\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 for (const threadId of remoteThreadIdsRef.current) {\n if (!remoteThreadIdsAtFetchStart.has(threadId)) {\n remoteThreadIds.add(threadId);\n }\n }\n\n remoteThreadIdsRef.current = remoteThreadIds;\n warmedThreadIdsRef.current = new Set(\n Array.from(warmedThreadIdsRef.current).filter((threadId) =>\n remoteThreadIds.has(threadId),\n ),\n );\n currentContext.setThreadMetadata(newMetadata);\n if (maxChatNum > baseThreadCount) {\n currentContext.setThreadCnt(maxChatNum);\n }\n\n scheduleThreadPrefetch(threadList.map((thread) => thread.session_id));\n\n const activeThreadId = threadContextRef.current.currentThreadId;\n if (remoteThreadIds.has(activeThreadId)) {\n setIsThreadLoading(true);\n try {\n await warmThread(activeThreadId);\n if (!cancelled) {\n await ensureInitialState(activeThreadId);\n }\n } finally {\n if (!cancelled) {\n setIsThreadLoading(false);\n }\n }\n }\n } catch (error) {\n console.error(\"Failed to fetch thread list:\", error);\n } finally {\n if (!cancelled) {\n setIsThreadListLoading(false);\n }\n }\n };\n\n void fetchThreadList();\n\n return () => {\n cancelled = true;\n prefetchCancelRef.current?.();\n prefetchCancelRef.current = null;\n };\n }, [\n aomiClientRef,\n closeAllSessions,\n ensureInitialState,\n getControlState,\n remoteThreadIdsRef,\n scheduleThreadPrefetch,\n sessionManager,\n setIsThreadLoading,\n threadContextRef,\n user,\n warmPromisesRef,\n warmedThreadIdsRef,\n warmThread,\n ]);\n\n return { isThreadListLoading };\n}\n\nexport function useRuntimeUserStateEffects({\n sessions: {\n aomiClientRef,\n sessionManager,\n getSession,\n closeAllSessions,\n ensureInitialState,\n setIsThreadLoading,\n },\n remoteThreads,\n}: RuntimeUserStateEffectsOptions): { isThreadListLoading: boolean } {\n const threadContext = useThreadContext();\n const { user, getUserState, onUserStateChange } = useUser();\n const { getControlState } = useControl();\n const threadContextRef = useRef(threadContext);\n threadContextRef.current = threadContext;\n\n const context: RuntimeUserStateContext = {\n getControlState,\n getUserState,\n onUserStateChange,\n threadContextRef,\n user,\n };\n const sessions: RuntimeSessionBridge = {\n aomiClientRef,\n sessionManager,\n getSession,\n closeAllSessions,\n ensureInitialState,\n setIsThreadLoading,\n };\n\n useWalletStateSync(context, sessions, remoteThreads);\n useUserStateRequestResponder(context, sessions);\n return useRemoteThreadListSync(context, sessions, remoteThreads);\n}\n\nexport function RuntimeUserStateProvider({\n children,\n sessionManager,\n getUserState,\n onUserStateChange,\n}: RuntimeUserStateProviderProps) {\n const lastSerializedStateRef = useRef<string>(\"\");\n\n useEffect(() => {\n const applyToSessions = (next: UserState) => {\n const serialized = stableStateString(next);\n if (serialized === lastSerializedStateRef.current) {\n return;\n }\n lastSerializedStateRef.current = serialized;\n sessionManager.forEach((session) => {\n session.resolveUserState(next);\n });\n };\n\n applyToSessions(getUserState());\n const unsubscribe = onUserStateChange((next) => {\n applyToSessions(next);\n });\n return unsubscribe;\n }, [getUserState, onUserStateChange, sessionManager]);\n\n return <>{children}</>;\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":"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","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_client","import_jsx_runtime","import_react","import_client","import_react","import_client","import_client","ClientSession","_a","_b","import_react","import_react","import_react","import_client","import_jsx_runtime","UserStateHelpers","_a","_b","import_jsx_runtime","import_jsx_runtime","import_react","notificationIdCounter"]}