learning_ai_common_plat/packages/llm/src/providers/fallback.ts
root 39e48f3241 feat(llm): add FallbackLLMProvider + release pipeline script
- packages/llm: add FallbackLLMProvider (providers/fallback.ts) that
  tries each provider in order, skipping unconfigured or erroring ones;
  wire 'fallback' as a first-class LLMProviderType in factory + types
- packages/llm: improve auto-detection in factory — PERPLEXITY_API_KEY
  and GEMINI_API_KEY trigger auto-selection when no explicit provider set
- scripts/release.sh: new pipeline — rebase from origin/main, build,
  apply changesets, publish outdated packages to Gitea registry, push
- scripts/run-registry-tests.sh: fix Gitea URL health-check to use a
  real package endpoint with auth header instead of bare registry root
- docs: mark Vercel track-B prompts B1–B3 as complete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 04:21:12 +00:00

48 lines
1.4 KiB
TypeScript

/**
* 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<ChatCompletionResponse> {
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')}`);
}
}