selectedAiProvider function

  1. @riverpod
Future<AiProvider> selectedAiProvider(
  1. Ref<Object?> ref
)

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;
}