selectedAiProvider function
Which AI provider the user has selected. Reads from Supabase if the user has consented to cloud sync; otherwise reads from local secure storage.
Implementation
@riverpod
Future<AiProvider> selectedAiProvider(Ref ref) async {
final storage = ref.watch(secureStorageProvider);
final remote = ref.watch(userAiSettingsDatasourceProvider);
// Local storage holds the last-known selection — fast and works offline.
// We treat it as the source for which provider is "active" because the
// remote table holds settings keyed BY provider, not the active provider.
final value = await storage.read(key: AiProviderConfig.providerStorageKey);
var provider = AiProvider.fromStorageValue(value);
// Defensive fallback when the local-LLM feature is gated off but the user
// still has 'local' persisted (e.g. cleanup hasn't run yet, or a remote
// sync row replays the value). Treat as Claude so the downstream
// datasource never resolves to a disabled provider.
if (provider == AiProvider.local && !EnvConfig.isLocalLlmAvailable) {
provider = AiProvider.claude;
}
// Best-effort: if there's a Supabase row for this provider, mirror its
// credential into local storage so any subsequent reader (e.g. the
// ai-proxy headers builder) sees the synced value without an extra
// round-trip. Failures are silently ignored — local cache stays canonical.
unawaited(_hydrateLocalCacheFor(provider, storage, remote));
return provider;
}