buildProviderChain
Builds the provider fallback chain from config: on-device first (if enabled and onDevice is supplied) → configured cloud providers → fallback last. config.selectedProvider, when it names a cloud provider with a non-blank key, is moved to the front of the cloud group so picking a provider actually tries it first; the remaining configured providers still follow as fallbacks, in the fixed Anthropic > OpenAI > Gemini order (a no-op when nothing is selected, since ProviderId.OFFLINE_FALLBACK and ProviderId.ON_DEVICE match no cloud entry). onDevice and fallback are caller-supplied rather than hardcoded — this module ships no on-device LLM or app-specific offline fallback of its own.
Every provider this returns is wrapped in GuardedAiProvider — a chat message, or any other free-form USER content, is run through PromptGuard before it reaches ANY provider's complete/completeStream, cloud or on-device, so a caller building a chain through this function can't accidentally skip the guard the way constructing an AiProvider directly could.