/** * LLM Configuration * * Configure available LLM providers and models * API keys are still in .env.local for security */ export interface LLMModel { id: string; name: string; provider: 'anthropic' | 'openai' | 'groq'; contextWindow: number; inputCostPer1M: number; outputCostPer1M: number; supportsJSON: boolean; supportsMCP: boolean; maxTokens: number; description?: string; } export interface LLMProvider { id: string; name: string; envKey: string; models: LLMModel[]; defaultModel: string; } /** * LLM Providers Configuration */ export const llmProviders: LLMProvider[] = [ { id: 'anthropic', name: 'Anthropic', envKey: 'ANTHROPIC_API_KEY', defaultModel: 'claude-sonnet-4-5-20250929', models: [ { id: 'claude-sonnet-4-5-20250929', name: 'Claude Sonnet 4.5', provider: 'anthropic', contextWindow: 200000, inputCostPer1M: 3.00, outputCostPer1M: 15.00, supportsJSON: true, supportsMCP: true, maxTokens: 8192, description: 'Most capable model, best for complex tasks', }, { id: 'claude-haiku-4-5', name: 'Claude Haiku 4.5', provider: 'anthropic', contextWindow: 200000, inputCostPer1M: 1.00, outputCostPer1M: 5.00, supportsJSON: true, supportsMCP: true, maxTokens: 8192, description: 'Latest Haiku - fastest, matches Sonnet 4 on coding & agents', }, ], }, { id: 'openai', name: 'OpenAI', envKey: 'OPENAI_API_KEY', defaultModel: 'gpt-4o', models: [ { id: 'gpt-4o', name: 'GPT-5', provider: 'openai', contextWindow: 128000, inputCostPer1M: 2.50, outputCostPer1M: 10.00, supportsJSON: true, supportsMCP: true, maxTokens: 16384, description: 'Multimodal flagship model with function calling', }, { id: 'gpt-4o-mini', name: 'GPT-5 Mini', provider: 'openai', contextWindow: 128000, inputCostPer1M: 0.15, outputCostPer1M: 0.60, supportsJSON: true, supportsMCP: true, maxTokens: 16384, description: 'Affordable and fast with function calling', }, ], }, { id: 'groq', name: 'Groq', envKey: 'GROQ_API_KEY', defaultModel: 'gpt-oss-120b', models: [ { id: 'gpt-oss-120b', name: 'GPT OSS 120B', provider: 'groq', contextWindow: 128000, inputCostPer1M: 0.20, outputCostPer1M: 0.20, supportsJSON: true, supportsMCP: true, maxTokens: 32768, description: 'Larger Responses API model with MCP support', }, ], }, ]; /** * Get default model for a provider */ export function getDefaultModel(provider: 'anthropic' | 'openai' | 'groq'): string { const config = llmProviders.find(p => p.id === provider); return config?.defaultModel || ''; } /** * Get all models for a provider */ export function getModelsForProvider(provider: 'anthropic' | 'openai' | 'groq'): LLMModel[] { const config = llmProviders.find(p => p.id === provider); return config?.models || []; } /** * Get model info by full ID (provider/model-id) */ export function getModelInfo(fullModelId: string): LLMModel | null { const [provider, modelId] = fullModelId.split('/'); const providerConfig = llmProviders.find(p => p.id === provider); if (!providerConfig) return null; return providerConfig.models.find(m => m.id === modelId) || null; } /** * Format model ID for API calls */ export function formatModelId(provider: string, modelId: string): string { return `${provider}/${modelId}`; } /** * Get all available models (flattened) */ export function getAllModels(): Array { return llmProviders.flatMap(provider => provider.models.map(model => ({ ...model, fullId: `${provider.id}/${model.id}`, })) ); } /** * Check if provider API key is configured */ export function isProviderConfigured(provider: 'anthropic' | 'openai' | 'groq'): boolean { const config = llmProviders.find(p => p.id === provider); if (!config) return false; // This only works server-side if (typeof process === 'undefined') return false; return !!process.env[config.envKey]; } /** * Get configured providers */ export function getConfiguredProviders(): string[] { return llmProviders .filter(p => isProviderConfigured(p.id as any)) .map(p => p.id); }