// SOS-LLM-Provider mit AsyncStorage-Persist + Listener-Pattern. // Live-Switch im SOS-Screen — analog zu lib/ttsProvider.ts. // // Backend (sos-session.post.ts) nimmt das Feld entgegen, sos-stream.get.ts // routet dann je nach Wert zu OpenRouter (Sonnet/Haiku) oder Groq (Llama). import AsyncStorage from '@react-native-async-storage/async-storage'; import { useEffect, useState } from 'react'; export type LlmProvider = 'openrouter-sonnet' | 'openrouter-haiku' | 'groq-llama'; const STORAGE_KEY = 'rebreak-sos-llm-provider'; const DEFAULT_PROVIDER: LlmProvider = 'openrouter-sonnet'; export const LLM_PROVIDER_LABEL: Record = { 'openrouter-sonnet': 'Sonnet', 'openrouter-haiku': 'Haiku', 'groq-llama': 'Groq', }; const listeners = new Set<(p: LlmProvider) => void>(); let cached: LlmProvider | null = null; export async function loadLlmProvider(): Promise { if (cached) return cached; const raw = await AsyncStorage.getItem(STORAGE_KEY).catch(() => null); cached = raw === 'openrouter-haiku' || raw === 'groq-llama' ? raw : DEFAULT_PROVIDER; return cached; } export async function setLlmProvider(p: LlmProvider): Promise { cached = p; await AsyncStorage.setItem(STORAGE_KEY, p).catch(() => {}); for (const cb of listeners) cb(p); } /** Always-fresh read — analog zu currentProvider() in ttsProvider.ts. */ export function currentLlmProvider(): LlmProvider { return cached ?? DEFAULT_PROVIDER; } export function useLlmProvider(): [LlmProvider, (p: LlmProvider) => Promise] { const [p, setP] = useState(cached ?? DEFAULT_PROVIDER); useEffect(() => { let mounted = true; loadLlmProvider().then((v) => { if (mounted) setP(v); }); const cb = (v: LlmProvider) => { if (mounted) setP(v); }; listeners.add(cb); return () => { mounted = false; listeners.delete(cb); }; }, []); return [p, setLlmProvider]; }