- LITELLM_MODELS = [] — no hardcoded models, global selector now only shows what admin has actually added via Search API - getAvailableModelsWithOverrides: for LiteLLM returns only custom list - Remove toggle safety check — admin can disable any/all models freely - Admin panel always reloads on tab open (was cached, showing stale data) - Add 'Clear all models' button for LiteLLM to wipe and start fresh - Add POST /config/models/clear-all endpoint
242 lines
13 KiB
JavaScript
242 lines
13 KiB
JavaScript
// ============================================================
|
|
// MODELS.JS — Provider-aware model list
|
|
// Supports: OpenRouter, AWS Bedrock, Azure OpenAI, Google Vertex AI, LiteLLM
|
|
// ============================================================
|
|
|
|
var activeProvider = process.env.AI_PROVIDER || 'openrouter';
|
|
|
|
var OPENROUTER_MODELS = [
|
|
{ id: 'google/gemini-2.5-flash', name: 'Gemini Flash 2.5', cost: '~$0.001', tag: 'BEST VALUE', category: 'fast' },
|
|
{ id: 'google/gemini-2.5-pro', name: 'Gemini Pro 2.5', cost: '~$0.01', tag: 'SMART', category: 'premium' },
|
|
{ id: 'google/gemini-2.5-flash:thinking', name: 'Gemini Flash Thinking', cost: '~$0.002', tag: 'REASONING', category: 'smart' },
|
|
{ id: 'deepseek/deepseek-chat-v3-0324', name: 'DeepSeek V3', cost: '~$0.001', tag: 'CHEAP', category: 'fast' },
|
|
{ id: 'deepseek/deepseek-r1', name: 'DeepSeek R1', cost: '~$0.005', tag: 'REASONING', category: 'smart' },
|
|
{ id: 'deepseek/deepseek-r1:free', name: 'DeepSeek R1 Free', cost: 'FREE', tag: 'FREE', category: 'free' },
|
|
{ id: 'qwen/qwen3-235b-a22b', name: 'Qwen3 235B', cost: '~$0.005', tag: 'SMART', category: 'smart' },
|
|
{ id: 'qwen/qwen3-30b-a3b:free', name: 'Qwen3 30B Free', cost: 'FREE', tag: 'FREE', category: 'free' },
|
|
{ id: 'meta-llama/llama-4-maverick', name: 'Llama 4 Maverick', cost: '~$0.002', tag: 'NEW', category: 'smart' },
|
|
{ id: 'meta-llama/llama-3.3-70b-instruct', name: 'Llama 3.3 70B', cost: '~$0.001', tag: 'GOOD', category: 'fast' },
|
|
{ id: 'openai/gpt-4.1', name: 'GPT-4.1', cost: '~$0.01', tag: 'PREMIUM', category: 'premium' },
|
|
{ id: 'openai/gpt-4.1-mini', name: 'GPT-4.1 Mini', cost: '~$0.003', tag: 'SMART', category: 'smart' },
|
|
{ id: 'openai/o4-mini', name: 'o4-mini (Reasoning)', cost: '~$0.01', tag: 'REASONING', category: 'premium' },
|
|
{ id: 'anthropic/vendor-model-opus-4-6', name: 'vendor model Opus 4.6', cost: '~$0.075', tag: 'BEST NUANCE', category: 'premium' },
|
|
{ id: 'anthropic/vendor-model-sonnet-4-6', name: 'vendor model Sonnet 4.6', cost: '~$0.015', tag: 'RECOMMENDED', category: 'premium' },
|
|
{ id: 'anthropic/vendor-model-sonnet-4', name: 'vendor model Sonnet 4', cost: '~$0.015', tag: 'PREMIUM', category: 'premium' },
|
|
{ id: 'anthropic/vendor-model-3.5-sonnet', name: 'vendor model 3.5 Sonnet', cost: '~$0.015', tag: 'MEDICAL', category: 'premium' },
|
|
{ id: 'mistralai/mistral-large-2411', name: 'Mistral Large', cost: '~$0.006', tag: 'GOOD', category: 'smart' },
|
|
{ id: 'mistralai/mistral-small-3.2-24b-instruct:free', name: 'Mistral Small Free', cost: 'FREE', tag: 'FREE', category: 'free' }
|
|
];
|
|
|
|
var BEDROCK_MODELS = [
|
|
// All IDs verified against AWS docs 2026-03-24
|
|
// us. prefix = cross-region inference profile (required for most newer models)
|
|
// maxOut = model's max output token limit (omit if >= 8192)
|
|
|
|
// ── Anthropic vendor model (all use inference profiles) ──
|
|
{ id: 'anthropic/vendor-model-opus-4-6', name: 'vendor model Opus 4.6', cost: '~$0.075', tag: 'BEST', category: 'premium',
|
|
bedrockId: 'us.anthropic.agent-config-opus-4-6-v1' },
|
|
{ id: 'anthropic/vendor-model-opus-4-5', name: 'vendor model Opus 4.5', cost: '~$0.075', tag: 'OPUS', category: 'premium',
|
|
bedrockId: 'us.anthropic.agent-config-opus-4-5-20251101-v1:0' },
|
|
{ id: 'anthropic/vendor-model-opus-4-1', name: 'vendor model Opus 4.1', cost: '~$0.075', tag: 'MEDICAL', category: 'premium',
|
|
bedrockId: 'us.anthropic.agent-config-opus-4-1-20250805-v1:0' },
|
|
{ id: 'anthropic/vendor-model-sonnet-4-6', name: 'vendor model Sonnet 4.6', cost: '~$0.015', tag: 'RECOMMENDED', category: 'premium',
|
|
bedrockId: 'us.anthropic.agent-config-sonnet-4-6' },
|
|
{ id: 'anthropic/vendor-model-sonnet-4-5', name: 'vendor model Sonnet 4.5', cost: '~$0.015', tag: 'SMART', category: 'premium',
|
|
bedrockId: 'us.anthropic.agent-config-sonnet-4-5-20250929-v1:0' },
|
|
{ id: 'anthropic/vendor-model-sonnet-4', name: 'vendor model Sonnet 4', cost: '~$0.015', tag: 'SOLID', category: 'premium',
|
|
bedrockId: 'us.anthropic.agent-config-sonnet-4-20250514-v1:0' },
|
|
{ id: 'anthropic/vendor-model-haiku-4-5', name: 'vendor model Haiku 4.5', cost: '~$0.003', tag: 'FAST', category: 'smart',
|
|
bedrockId: 'us.anthropic.agent-config-haiku-4-5-20251001-v1:0' },
|
|
{ id: 'anthropic/vendor-model-3.5-haiku', name: 'vendor model 3.5 Haiku', cost: '~$0.002', tag: 'VALUE', category: 'smart',
|
|
bedrockId: 'us.anthropic.agent-config-3-5-haiku-20241022-v1:0' },
|
|
|
|
// ── Amazon Nova (inference profiles) ──
|
|
{ id: 'amazon/nova-pro', name: 'Amazon Nova Pro', cost: '~$0.008', tag: 'SMART', category: 'smart',
|
|
bedrockId: 'us.amazon.nova-pro-v1:0' },
|
|
{ id: 'amazon/nova-lite', name: 'Amazon Nova Lite', cost: '~$0.001', tag: 'FAST', category: 'fast',
|
|
bedrockId: 'us.amazon.nova-lite-v1:0' },
|
|
{ id: 'amazon/nova-micro', name: 'Amazon Nova Micro', cost: '~$0.0004', tag: 'CHEAPEST', category: 'fast',
|
|
bedrockId: 'us.amazon.nova-micro-v1:0' },
|
|
|
|
// ── Meta Llama (inference profiles) ──
|
|
{ id: 'meta/llama-4-maverick', name: 'Llama 4 Maverick', cost: '~$0.005', tag: 'NEW', category: 'smart',
|
|
bedrockId: 'us.meta.llama4-maverick-17b-instruct-v1:0' },
|
|
{ id: 'meta/llama-4-scout', name: 'Llama 4 Scout', cost: '~$0.004', tag: 'NEW', category: 'smart',
|
|
bedrockId: 'us.meta.llama4-scout-17b-instruct-v1:0' },
|
|
{ id: 'meta/llama-3.3-70b', name: 'Llama 3.3 70B', cost: '~$0.003', tag: 'GOOD', category: 'smart',
|
|
bedrockId: 'us.meta.llama3-3-70b-instruct-v1:0' },
|
|
|
|
// ── DeepSeek (R1 has profile, V3.2 is on-demand) ──
|
|
{ id: 'deepseek/r1', name: 'DeepSeek R1', cost: '~$0.005', tag: 'REASONING', category: 'smart',
|
|
bedrockId: 'us.deepseek.r1-v1:0' },
|
|
{ id: 'deepseek/v3.2', name: 'DeepSeek V3.2', cost: '~$0.001', tag: 'FAST', category: 'fast',
|
|
bedrockId: 'deepseek.v3.2', regions: ['us-east-1', 'us-east-2', 'us-west-2'] },
|
|
|
|
// ── Mistral AI (on-demand, no profiles available) ──
|
|
{ id: 'mistral/large-3', name: 'Mistral Large 3 (675B)', cost: '~$0.008', tag: 'PREMIUM', category: 'premium',
|
|
bedrockId: 'mistral.mistral-large-3-675b-instruct', regions: ['us-east-1', 'us-east-2', 'us-west-2'] },
|
|
{ id: 'mistral/magistral-small', name: 'Magistral Small', cost: '~$0.003', tag: 'VALUE', category: 'smart',
|
|
bedrockId: 'mistral.magistral-small-2509', regions: ['us-east-1', 'us-east-2', 'us-west-2'] },
|
|
|
|
// ── Cohere (on-demand, max 4096 output) ──
|
|
{ id: 'cohere/command-r-plus', name: 'Command R+', cost: '~$0.005', tag: 'GOOD', category: 'smart',
|
|
bedrockId: 'cohere.command-r-plus-v1:0', regions: ['us-east-1', 'us-west-2'], maxOut: 4096 },
|
|
{ id: 'cohere/command-r', name: 'Command R', cost: '~$0.002', tag: 'VALUE', category: 'fast',
|
|
bedrockId: 'cohere.command-r-v1:0', regions: ['us-east-1', 'us-west-2'], maxOut: 4096 },
|
|
|
|
// ── AI21 Labs (on-demand, max 4096 output) ──
|
|
{ id: 'ai21/jamba-1.5-large', name: 'Jamba 1.5 Large', cost: '~$0.005', tag: 'GOOD', category: 'smart',
|
|
bedrockId: 'ai21.jamba-1-5-large-v1:0', regions: ['us-east-1'], maxOut: 4096 },
|
|
|
|
// ── Writer (inference profile) ──
|
|
{ id: 'writer/palmyra-x5', name: 'Palmyra X5', cost: '~$0.01', tag: 'CLINICAL', category: 'premium',
|
|
bedrockId: 'us.writer.palmyra-x5-v1:0' },
|
|
|
|
// ── Qwen (on-demand, no profiles) ──
|
|
{ id: 'qwen/qwen3-235b', name: 'Qwen3 235B', cost: '~$0.005', tag: 'SMART', category: 'smart',
|
|
bedrockId: 'qwen.qwen3-235b-a22b-2507-v1:0' },
|
|
{ id: 'qwen/qwen3-32b', name: 'Qwen3 32B', cost: '~$0.002', tag: 'VALUE', category: 'fast',
|
|
bedrockId: 'qwen.qwen3-32b-v1:0' }
|
|
];
|
|
|
|
var AZURE_MODELS = [
|
|
{ id: 'gpt-4o', name: 'GPT-4o', cost: '~$0.01', tag: 'BEST', category: 'premium',
|
|
deploymentNote: 'Set AZURE_DEPLOYMENT_NAME in .env' },
|
|
{ id: 'gpt-4o-mini', name: 'GPT-4o Mini', cost: '~$0.003', tag: 'SMART', category: 'smart',
|
|
deploymentNote: 'Set AZURE_DEPLOYMENT_NAME in .env' },
|
|
{ id: 'gpt-4.1', name: 'GPT-4.1', cost: '~$0.01', tag: 'NEW', category: 'premium',
|
|
deploymentNote: 'Set AZURE_DEPLOYMENT_NAME in .env' },
|
|
{ id: 'gpt-4.1-mini', name: 'GPT-4.1 Mini', cost: '~$0.003', tag: 'VALUE', category: 'smart',
|
|
deploymentNote: 'Set AZURE_DEPLOYMENT_NAME in .env' }
|
|
];
|
|
|
|
// ============================================================
|
|
// GOOGLE VERTEX AI MODELS
|
|
// vertexId = the model name used in Vertex AI API calls
|
|
// ============================================================
|
|
var VERTEX_MODELS = [
|
|
{ id: 'gemini-2.5-flash', name: 'Gemini 2.5 Flash', cost: '~$0.001', tag: 'BEST VALUE', category: 'fast',
|
|
vertexId: 'gemini-2.5-flash-preview-05-20' },
|
|
{ id: 'gemini-2.5-pro', name: 'Gemini 2.5 Pro', cost: '~$0.01', tag: 'SMART', category: 'premium',
|
|
vertexId: 'gemini-2.5-pro-preview-05-06' },
|
|
{ id: 'gemini-2.0-flash', name: 'Gemini 2.0 Flash', cost: '~$0.001', tag: 'FAST', category: 'fast',
|
|
vertexId: 'gemini-2.0-flash' },
|
|
{ id: 'gemini-2.0-flash-lite', name: 'Gemini 2.0 Flash Lite', cost: '~$0.0004', tag: 'CHEAPEST', category: 'fast',
|
|
vertexId: 'gemini-2.0-flash-lite' },
|
|
{ id: 'gemini-1.5-pro', name: 'Gemini 1.5 Pro', cost: '~$0.007', tag: 'RELIABLE', category: 'premium',
|
|
vertexId: 'gemini-1.5-pro-002' },
|
|
{ id: 'gemini-1.5-flash', name: 'Gemini 1.5 Flash', cost: '~$0.001', tag: 'VALUE', category: 'fast',
|
|
vertexId: 'gemini-1.5-flash-002' },
|
|
{ id: 'vendor-model-sonnet-4-6@vertex', name: 'vendor model Sonnet 4.6 (Vertex)', cost: '~$0.015', tag: 'PREMIUM', category: 'premium',
|
|
vertexId: 'vendor-model-sonnet-4-6@20250514' },
|
|
{ id: 'vendor-model-haiku-4-5@vertex', name: 'vendor model Haiku 4.5 (Vertex)', cost: '~$0.003', tag: 'FAST', category: 'smart',
|
|
vertexId: 'vendor-model-haiku-4-5@20251001' },
|
|
{ id: 'llama-3.1-405b@vertex', name: 'Llama 3.1 405B (Vertex)', cost: '~$0.005', tag: 'OPEN', category: 'smart',
|
|
vertexId: 'meta/llama-3.1-405b-instruct-maas' },
|
|
];
|
|
|
|
// LiteLLM has NO built-in models — everything is discovered from the proxy via admin panel.
|
|
// This array is intentionally empty. Do not add models here.
|
|
var LITELLM_MODELS = [];
|
|
|
|
function getAvailableModels() {
|
|
switch (activeProvider) {
|
|
case 'bedrock':
|
|
var region = process.env.AWS_BEDROCK_REGION || 'us-east-1';
|
|
return BEDROCK_MODELS.filter(function(m) {
|
|
return !m.regions || m.regions.indexOf(region) !== -1;
|
|
});
|
|
case 'azure': return AZURE_MODELS;
|
|
case 'vertex': return VERTEX_MODELS;
|
|
case 'litellm': return LITELLM_MODELS;
|
|
case 'openrouter':
|
|
default: return OPENROUTER_MODELS;
|
|
}
|
|
}
|
|
|
|
function getDefaultModel() {
|
|
switch (activeProvider) {
|
|
case 'bedrock': return 'anthropic/vendor-model-sonnet-4-6';
|
|
case 'azure': return process.env.AZURE_DEPLOYMENT_NAME || 'gpt-4o-mini';
|
|
case 'vertex': return 'gemini-2.5-flash';
|
|
case 'litellm': return ''; // No default — set via admin panel or LITELLM_DEFAULT_MODEL env
|
|
case 'openrouter':
|
|
default: return 'google/gemini-2.5-flash';
|
|
}
|
|
}
|
|
|
|
function getFallbackModel() {
|
|
switch (activeProvider) {
|
|
case 'bedrock': return 'anthropic/vendor-model-haiku-4-5';
|
|
case 'azure': return process.env.AZURE_DEPLOYMENT_NAME || 'gpt-4o-mini';
|
|
case 'vertex': return 'gemini-2.0-flash';
|
|
case 'litellm': return ''; // No fallback — use whatever the user has configured
|
|
case 'openrouter':
|
|
default: return 'deepseek/deepseek-chat-v3-0324';
|
|
}
|
|
}
|
|
|
|
function getBedrockModelId(modelId) {
|
|
var found = BEDROCK_MODELS.find(function(m) { return m.id === modelId; });
|
|
return found ? found.bedrockId : modelId;
|
|
}
|
|
|
|
function getBedrockMaxOut(modelId) {
|
|
var found = BEDROCK_MODELS.find(function(m) { return m.id === modelId; });
|
|
return found && found.maxOut ? found.maxOut : null;
|
|
}
|
|
|
|
function getVertexModelId(modelId) {
|
|
var found = VERTEX_MODELS.find(function(m) { return m.id === modelId; });
|
|
return found ? found.vertexId : modelId;
|
|
}
|
|
|
|
var AVAILABLE_MODELS = getAvailableModels();
|
|
var DEFAULT_MODEL = getDefaultModel();
|
|
var FALLBACK_MODEL = getFallbackModel();
|
|
|
|
console.log('🤖 Provider:', activeProvider);
|
|
console.log('🤖 Default model:', DEFAULT_MODEL);
|
|
console.log('🤖 Models available:', AVAILABLE_MODELS.length);
|
|
|
|
// DB-aware model list (used by /api/models endpoint)
|
|
async function getAvailableModelsWithOverrides(db) {
|
|
var baseModels = getAvailableModels();
|
|
try {
|
|
var disabledRaw = await db.getSetting('models.disabled') || '[]';
|
|
var customRaw = await db.getSetting('models.custom') || '[]';
|
|
var disabled, custom;
|
|
try { disabled = JSON.parse(disabledRaw); } catch(e) { disabled = []; }
|
|
try { custom = JSON.parse(customRaw); } catch(e) { custom = []; }
|
|
|
|
// For LiteLLM: no built-ins exist — the model list IS the custom/discovered list
|
|
if (activeProvider === 'litellm') return custom;
|
|
|
|
var result = baseModels.filter(function(m) { return !disabled.includes(m.id); });
|
|
custom.forEach(function(m) {
|
|
if (!result.find(function(r) { return r.id === m.id; })) result.push(m);
|
|
});
|
|
return result;
|
|
} catch(e) {
|
|
return baseModels;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
AVAILABLE_MODELS,
|
|
DEFAULT_MODEL,
|
|
FALLBACK_MODEL,
|
|
OPENROUTER_MODELS,
|
|
BEDROCK_MODELS,
|
|
AZURE_MODELS,
|
|
VERTEX_MODELS,
|
|
LITELLM_MODELS,
|
|
getAvailableModels,
|
|
getAvailableModelsWithOverrides,
|
|
getDefaultModel,
|
|
getFallbackModel,
|
|
getBedrockModelId,
|
|
getBedrockMaxOut,
|
|
getVertexModelId,
|
|
activeProvider
|
|
};
|