Skip to main content
Glama
index.ts4.5 kB
import { AiProvider, AiProviderConfig } from './provider.js'; import { OpenAiProvider } from './openai-provider.js'; import { GeminiProvider } from './gemini-provider.js'; import { AnthropicProvider } from './anthropic-provider.js'; import { LocalModelProvider } from './local-provider.js'; import { TemplateFallbackProvider } from './template-fallback-provider.js'; import { logger } from '../../config/logging.js'; // Provider registry const providers: Record<string, new (config: AiProviderConfig) => AiProvider> = { openai: OpenAiProvider, gemini: GeminiProvider, anthropic: AnthropicProvider, local: LocalModelProvider, template: TemplateFallbackProvider, }; // Default fallback provider is template-based const DEFAULT_PROVIDER = 'template'; /** * Provider manager for creating, caching, and selecting AI providers */ export class AiProviderManager { private providerInstances: Map<string, AiProvider> = new Map(); private configs: Record<string, AiProviderConfig>; constructor(configs: Record<string, AiProviderConfig>) { this.configs = configs; } /** * Get an AI provider by ID, creating it if it doesn't exist */ getProvider(providerId: string): AiProvider | null { // Check if provider exists in registry if (!providers[providerId]) { logger.warn(`Unknown provider: ${providerId}`); return null; } // Check if provider instance already exists if (this.providerInstances.has(providerId)) { return this.providerInstances.get(providerId) || null; } try { // Get config for this provider const config = this.configs[providerId] || { id: providerId }; // Create a new provider instance const ProviderClass = providers[providerId]; const provider = new ProviderClass(config); // Cache the provider instance this.providerInstances.set(providerId, provider); return provider; } catch (error) { logger.error(`Error creating provider ${providerId}: ${error instanceof Error ? error.message : String(error)}`); return null; } } /** * List all available providers with their IDs and names */ async listAvailableProviders(): Promise<Array<{ id: string, name: string, available: boolean }>> { const result = []; for (const providerId of Object.keys(providers)) { const provider = this.getProvider(providerId); if (provider) { let available = false; try { available = await provider.isAvailable(); } catch (error) { logger.warn(`Error checking availability for provider ${providerId}: ${error instanceof Error ? error.message : String(error)}`); } result.push({ id: provider.id, name: provider.name, available }); } } return result; } /** * Select the best available provider, with fallback to template-based */ async selectProvider(preferredProviderId?: string): Promise<AiProvider> { // If a specific provider is requested, try to use it if (preferredProviderId) { const provider = this.getProvider(preferredProviderId); if (provider) { const available = await provider.isAvailable(); if (available) { logger.info(`Using preferred provider: ${provider.name}`); return provider; } logger.warn(`Preferred provider ${provider.name} is not available. Will try fallback.`); } } // Try each provider in order of priority const priorities = ['openai', 'anthropic', 'gemini', 'local']; for (const providerId of priorities) { const provider = this.getProvider(providerId); if (provider) { try { const available = await provider.isAvailable(); if (available) { logger.info(`Selected provider: ${provider.name}`); return provider; } } catch (error) { logger.warn(`Error checking ${providerId} availability: ${error instanceof Error ? error.message : String(error)}`); } } } // Fallback to template-based provider logger.info('No AI providers available. Using template-based fallback.'); const fallbackProvider = this.getProvider(DEFAULT_PROVIDER); if (!fallbackProvider) { throw new Error('Critical error: Even fallback provider is unavailable'); } return fallbackProvider; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Saml1211/PRD-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server