- 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>
48 lines
1.4 KiB
TypeScript
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')}`);
|
|
}
|
|
}
|