/** * Svelte 5 reactive app state * * Uses runes ($state, $derived) for reactivity. * This is the Svelte-specific binding layer on top of app-state.ts */ import type { GetLLMOptions, GetSTTOptions, GetTTSOptions, LLMAdapter, STTAdapter, TTSAdapter, TTSOptions } from '../browser-ai/index.js'; import { type AIConfig, type AILoadingState, type AppMode, type CreateAppStateOptions, type ModeSource, type SmrtAppState, type SocketConfig, type User, type UserSession } from './app-state.js'; /** * Reactive app state manager for Svelte 5 */ export declare class SmrtAppStateManager { private _state; private options; private _aiConfig; private _preloadScheduled; private _idleCallbackId; private _preloadInFlight; private _socket; private _socketConfig; private _reconnectTimeout; private _sttSubscriptions; private _ttsSubscriptions; constructor(options?: CreateAppStateOptions); /** * Get the current socket configuration (for reconnection) */ get socketConfig(): SocketConfig | null; /** * Get the current state (readonly) */ get state(): Readonly; /** * Get the current AI configuration */ get aiConfig(): AIConfig | null; /** * Get the current AI loading state */ get aiLoading(): Readonly; /** * Initialize the app state * Detects capabilities and sets initial mode * Note: This is a no-op during SSR as browser-ai requires browser environment */ initialize(): Promise; /** * Set or update AI configuration. * * No-ops when the incoming config is deep-equal to the current one. The * Provider's `ai` $effect depends on the prop's identity, and the documented * usage passes an inline `ai={{…}}` object literal — a fresh identity on every * parent render. Without this guard each render would cancel the idle * callback, reset `_preloadScheduled`, and re-schedule (and, for `eager`, * re-launch a full preload), thrashing the scheduler and double-downloading * models (R3). */ setAIConfig(config: AIConfig): void; /** * Schedule preloading based on the configured strategy */ private schedulePreload; /** * Trigger preloading (called by components for 'on-visible' strategy) */ triggerPreload(): void; /** * Execute the preloading of configured adapters. * * Re-entrancy guarded: an `idle`/`eager` strategy can be re-scheduled while a * pass is still awaiting model downloads. Without the guard the overlapping * passes interleave their aiLoading writes and double-download models (R3). */ private executePreload; /** * The actual preload pass. Always invoked behind the `_preloadInFlight` guard * in {@link executePreload}. */ private runPreload; /** * Update the AI loading state */ private updateLoadingState; /** * Set the app mode */ setMode(mode: AppMode, source?: ModeSource): void; /** * Toggle between default and smrt modes */ toggleMode(): void; /** * Update user session */ updateSession(session: Partial): void; /** * Set user permissions */ setPermissions(permissions: string[]): void; /** * Check if user has a permission */ hasPermission(permission: string): boolean; /** * Check if user has all permissions */ hasAllPermissions(permissions: string[]): boolean; /** * Check if user has any of the permissions */ hasAnyPermission(permissions: string[]): boolean; /** * Set the current user and permissions * Called by SmrtProvider when user prop changes */ setUser(user: User | null, permissions?: string[]): void; /** * Connect to a WebSocket server */ connectSocket(config: SocketConfig): void; /** * Disconnect from the WebSocket server */ disconnectSocket(): void; /** * Send a message through the WebSocket */ sendMessage(data: unknown): void; /** * Schedule a reconnection attempt with exponential backoff */ private scheduleReconnect; /** * Initialize STT adapter * Uses warm client cache to avoid re-downloading models */ initializeSTT(options?: GetSTTOptions): Promise; /** * Subscribe to STT adapter events. * * Captures every unsubscribe handle the adapter returns and stores a single * teardown both per-manager (called on dispose()) and at module scope keyed * by adapter identity. Because warm adapters are shared singletons, any * previous owner's listeners are torn down first — guaranteeing exactly one * live listener set per adapter, with the latest manager owning it (R1). */ private subscribeToSTTEvents; /** * Start STT listening */ startListening(options?: Parameters[0]): Promise; /** * Stop STT listening */ stopListening(): Promise; /** * Initialize TTS adapter * Uses warm client cache to avoid re-initialization */ initializeTTS(options?: GetTTSOptions): Promise; /** * Subscribe to TTS adapter events. * * Mirrors {@link subscribeToSTTEvents}: captures unsubscribe handles, dedups * per-manager, and evicts any prior owner so a shared warm adapter never * pins more than one manager's `_state` proxy (R1). */ private subscribeToTTSEvents; /** * Speak text using TTS */ speak(text: string, options?: TTSOptions): Promise; /** * Stop TTS speech */ stopSpeaking(): void; /** * Pause TTS speech */ pauseSpeaking(): void; /** * Resume TTS speech */ resumeSpeaking(): void; /** * Get available TTS voices */ getTTSVoices(): import("../browser-ai/index.js").TTSVoice[]; /** * Initialize LLM adapter * Uses warm client cache to avoid re-downloading models */ initializeLLM(modelId?: string, options?: GetLLMOptions): Promise; /** * Send a message to the LLM */ chat(text: string, options?: { systemPrompt?: string; onToken?: (token: string) => void; }): Promise; /** * Unload LLM model to free memory */ unloadLLM(): Promise; /** * Unsubscribe every adapter-event listener this manager owns (R1). Called on * dispose() so a destroyed Provider stops being pinned by the shared warm * adapters' module-surviving listener `Set`s. */ private unsubscribeAllAdapterEvents; /** * Dispose of all resources */ dispose(): Promise; /** * Check if AI is ready to use (all configured adapters loaded) */ get isAIReady(): boolean; /** * Check if AI is currently loading */ get isAILoading(): boolean; } /** * Create a new reactive app state manager */ export declare function createAppState(options?: CreateAppStateOptions): SmrtAppStateManager; //# sourceMappingURL=app-state.svelte.d.ts.map