@juspay/neurolink
Version:
Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and
139 lines (138 loc) • 5.09 kB
JavaScript
import { logger } from "../utils/logger.js";
/**
* True Factory Pattern implementation for AI Providers
* Uses registration-based approach to eliminate switch statements
* and enable dynamic provider registration
*/
export class ProviderFactory {
static providers = new Map();
static initialized = false;
/**
* Register a provider with the factory
*/
static registerProvider(name, constructor, defaultModel, // Optional - provider can read from env
aliases = []) {
const registration = {
constructor,
defaultModel,
aliases,
};
// Register main name
this.providers.set(name.toLowerCase(), registration);
// Register aliases
aliases.forEach((alias) => {
this.providers.set(alias.toLowerCase(), registration);
});
logger.debug(`Registered provider: ${name} with model ${defaultModel || "from-env"}`);
}
/**
* Create a provider instance
*/
static async createProvider(providerName, modelName, sdk) {
// Note: Providers are registered explicitly by ProviderRegistry to avoid circular dependencies
const normalizedName = providerName.toLowerCase();
const registration = this.providers.get(normalizedName);
if (!registration) {
throw new Error(`Unknown provider: ${providerName}. Available providers: ${this.getAvailableProviders().join(", ")}`);
}
// Respect environment variables before falling back to registry default
let model = modelName;
if (!model) {
// Check for provider-specific environment variables
if (providerName.toLowerCase().includes("vertex")) {
model = process.env.VERTEX_MODEL;
}
// Fallback to registry default if no env var
model = model || registration.defaultModel;
}
try {
let result;
try {
// Try as async factory function first (most providers are async functions)
result = await registration.constructor(model, providerName, sdk);
}
catch (functionError) {
// Fallback to constructor - ensure parameters are maintained
result = new registration.constructor(model, providerName, sdk);
}
// Return result (no need to await again if already awaited in try block)
return result;
}
catch (error) {
logger.error(`Failed to create provider ${providerName}:`, error);
throw new Error(`Failed to create provider ${providerName}: ${error}`);
}
}
/**
* Check if a provider is registered
*/
static hasProvider(providerName) {
return this.providers.has(providerName.toLowerCase());
}
/**
* Get list of available providers
*/
static getAvailableProviders() {
return Array.from(this.providers.keys()).filter((name, index, arr) => arr.indexOf(name) === index);
}
/**
* Get provider registration info
*/
static getProviderInfo(providerName) {
return this.providers.get(providerName.toLowerCase());
}
/**
* Normalize provider names using aliases (PHASE 1: Factory Pattern)
*/
static normalizeProviderName(providerName) {
const normalized = providerName.toLowerCase();
// Check direct registration
if (this.providers.has(normalized)) {
return normalized;
}
// Check aliases from all registrations
for (const [name, registration] of this.providers.entries()) {
if (registration.aliases?.includes(normalized)) {
return name;
}
}
return null;
}
/**
* Clear all registrations (mainly for testing)
*/
static clearRegistrations() {
this.providers.clear();
this.initialized = false;
}
/**
* Ensure providers are initialized
*/
static ensureInitialized() {
if (!this.initialized) {
this.initializeDefaultProviders();
this.initialized = true;
}
}
/**
* Initialize default providers
* NOTE: Providers are now registered by ProviderRegistry to avoid circular dependencies
*/
static initializeDefaultProviders() {
logger.debug("BaseProvider factory pattern ready - providers registered by ProviderRegistry");
// No hardcoded registrations - all done dynamically by ProviderRegistry
}
/**
* Create the best available provider for the given name
* Used by NeuroLink SDK for streaming and generation
*/
static async createBestProvider(providerName, modelName, enableMCP, sdk) {
return await this.createProvider(providerName, modelName, sdk);
}
}
/**
* Helper function to create providers with backward compatibility
*/
export async function createAIProvider(providerName, modelName) {
return await ProviderFactory.createProvider(providerName, modelName);
}