/** * Fallback LLM provider. * * Tries each provider in order, falling back to the next on error or * when a provider is not configured. Useful for resilient AI pipelines * (e.g. perplexity → openai → gemini). * * Usage: * const llm = new FallbackLLMProvider([ * new PerplexityProvider(), * new OpenAIProvider(), * new GeminiProvider(), * ]); */ import type { ChatCompletionRequest, ChatCompletionResponse, LLMProvider } from '../types.js'; export class FallbackLLMProvider implements LLMProvider { constructor(private readonly providers: LLMProvider[]) { if (providers.length === 0) { throw new Error('FallbackLLMProvider requires at least one provider'); } } isConfigured(): boolean { return this.providers.some(p => p.isConfigured()); } async chatCompletion(req: ChatCompletionRequest): Promise { const errors: string[] = []; for (const provider of this.providers) { if (!provider.isConfigured()) { errors.push(`${provider.constructor.name}: not configured`); continue; } try { return await provider.chatCompletion(req); } catch (err) { const msg = err instanceof Error ? err.message : String(err); errors.push(`${provider.constructor.name}: ${msg}`); } } throw new Error(`All LLM providers failed:\n${errors.map(e => ` - ${e}`).join('\n')}`); } }