config: upgrade to 3-tier fallback system (Gemini → OpenCode → OpenRouter)

Added OpenRouter as tertiary fallback:
- Primary: Gemini (free tier, quota-limited)
- Secondary: OpenCode (fallback if Gemini quota exceeded)
- Tertiary: OpenRouter (final fallback, supports multiple models)

gemini-fallback.js now tries all three in sequence with proper error handling.
This commit is contained in:
2026-03-02 19:39:33 +01:00
parent 0c37d6ea91
commit 2bc4c947ae
+47 -14
View File
@@ -1,6 +1,6 @@
/**
* Gemini API with OpenCode Fallback
* Tries Gemini first, falls back to OpenCode if quota exceeded
* Gemini API with Multi-Tier Fallback
* Tries: Gemini → OpenCode → OpenRouter
*/
const fetch = require('node-fetch');
@@ -8,14 +8,16 @@ const fetch = require('node-fetch');
const GEMINI_API_KEY = process.env.GOOGLE_API_KEY;
const OPENCODE_API_KEY = process.env.OPENCODE_API_KEY;
const OPENCODE_BASE_URL = process.env.OPENCODE_BASE_URL || 'https://api.opencode.com/v1';
const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY;
const OPENROUTER_BASE_URL = process.env.OPENROUTER_BASE_URL || 'https://openrouter.ai/api/v1';
async function generateWithFallback(prompt, options = {}) {
console.log('🤖 Generating content...');
// Try Gemini first
// Tier 1: Try Gemini
if (GEMINI_API_KEY) {
try {
console.log('Attempting Gemini API...');
console.log('📍 Tier 1: Attempting Gemini API...');
const response = await fetch(
`https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key=${GEMINI_API_KEY}`,
{
@@ -35,20 +37,19 @@ async function generateWithFallback(prompt, options = {}) {
}
if (response.status === 429 || response.status === 403) {
console.warn('⚠️ Gemini quota exceeded, falling back to OpenCode...');
throw new Error('QUOTA_EXCEEDED');
console.warn('⚠️ Gemini quota exceeded, trying next fallback...');
} else {
throw new Error(`Gemini error: ${response.status}`);
}
throw new Error(`Gemini API error: ${response.status}`);
} catch (err) {
console.warn(`Gemini failed: ${err.message}`);
}
}
// Fallback to OpenCode
// Tier 2: Fallback to OpenCode
if (OPENCODE_API_KEY) {
try {
console.log('Attempting OpenCode API...');
console.log('📍 Tier 2: Attempting OpenCode API...');
const response = await fetch(`${OPENCODE_BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
@@ -69,19 +70,51 @@ async function generateWithFallback(prompt, options = {}) {
return { success: true, provider: 'opencode', data };
}
throw new Error(`OpenCode API error: ${response.status}`);
console.warn(`OpenCode error: ${response.status}, trying next fallback...`);
} catch (err) {
console.error(`OpenCode failed: ${err.message}`);
console.warn(`OpenCode failed: ${err.message}`);
}
}
throw new Error('All generation APIs failed');
// Tier 3: Fallback to OpenRouter
if (OPENROUTER_API_KEY) {
try {
console.log('📍 Tier 3: Attempting OpenRouter API...');
const response = await fetch(`${OPENROUTER_BASE_URL}/chat/completions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${OPENROUTER_API_KEY}`,
'Content-Type': 'application/json',
'HTTP-Referer': 'https://gravl.app'
},
body: JSON.stringify({
model: options.model || 'openai/gpt-4',
messages: [{ role: 'user', content: prompt }],
temperature: options.temperature || 0.7,
max_tokens: options.maxTokens || 2048
})
});
if (response.ok) {
const data = await response.json();
console.log('✅ OpenRouter API success');
return { success: true, provider: 'openrouter', data };
}
throw new Error(`OpenRouter error: ${response.status}`);
} catch (err) {
console.error(`OpenRouter failed: ${err.message}`);
}
}
throw new Error('All generation APIs failed (Gemini → OpenCode → OpenRouter)');
}
module.exports = {
generateWithFallback,
getAvailableProviders: () => ({
gemini: !!GEMINI_API_KEY,
opencode: !!OPENCODE_API_KEY
opencode: !!OPENCODE_API_KEY,
openrouter: !!OPENROUTER_API_KEY
})
};