From b34b835b47fbfd092f4ede65c1b8f5ad0019988d Mon Sep 17 00:00:00 2001 From: Rene Fichtmueller Date: Sat, 25 Apr 2026 12:18:33 +0200 Subject: [PATCH] feat: integrate claude-bridge as primary LLM provider with fallback chain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add claude-bridge provider to external-providers.ts with Claude models (opus, sonnet, haiku) - Modify getApiKey to handle claude-bridge authentication (CLAUDE_BRIDGE_ENABLED flag) - Update getBaseUrl to construct URL from CLAUDE_BRIDGE_URL environment variable - Remove Authorization header for claude-bridge (uses subscription-based auth) - claude-bridge now first in fallback chain: Claude → Cerebras → Groq → Mistral → NVIDIA → Cloudflare --- .../src/pipeline/external-providers.ts | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/gateway/src/pipeline/external-providers.ts b/packages/gateway/src/pipeline/external-providers.ts index d94494f..0eb7a97 100644 --- a/packages/gateway/src/pipeline/external-providers.ts +++ b/packages/gateway/src/pipeline/external-providers.ts @@ -39,6 +39,18 @@ export interface ExternalCompletionResponse { // ─── Provider Registry ────────────────────────────────────────────── const PROVIDERS: readonly ExternalProvider[] = [ + { + name: 'claude-bridge', + baseUrl: '', // constructed from CLAUDE_BRIDGE_URL env var + envKey: 'CLAUDE_BRIDGE_URL', + rateLimitRpm: 100, + enabled: true, + models: [ + { id: 'claude-opus-4-1', tier: 'reasoning', contextLength: 200000 }, + { id: 'claude-sonnet-4-1', tier: 'large', contextLength: 200000 }, + { id: 'claude-haiku-3', tier: 'fast', contextLength: 200000 }, + ], + }, { name: 'cerebras', baseUrl: 'https://api.cerebras.ai/v1', @@ -131,10 +143,20 @@ function recordRequest(providerName: string): void { // ─── Provider Resolution ──────────────────────────────────────────── function getApiKey(provider: ExternalProvider): string | undefined { + if (provider.name === 'claude-bridge') { + // claude-bridge doesn't use an API key; check if enabled and URL is set + const enabled = process.env['CLAUDE_BRIDGE_ENABLED'] === 'true'; + const url = process.env['CLAUDE_BRIDGE_URL']; + return enabled && url ? 'claude-bridge-enabled' : undefined; + } return process.env[provider.envKey] || undefined; } function getBaseUrl(provider: ExternalProvider): string { + if (provider.name === 'claude-bridge') { + const url = process.env['CLAUDE_BRIDGE_URL']; + return url ? `${url}/v1` : ''; + } if (provider.name === 'cloudflare') { const accountId = process.env['CLOUDFLARE_ACCOUNT_ID']; if (!accountId) return ''; @@ -188,12 +210,18 @@ async function callProvider( const start = Date.now(); try { + const headers: Record = { + 'Content-Type': 'application/json', + }; + + // Only add Authorization header for non-claude-bridge providers + if (provider.name !== 'claude-bridge') { + headers['Authorization'] = `Bearer ${apiKey}`; + } + const response = await fetch(url, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${apiKey}`, - }, + headers, body: JSON.stringify({ model: model.id, messages: request.messages,