@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
136 lines (135 loc) • 4.84 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(", ")}`);
}
const model = modelName || registration.defaultModel;
try {
// Try calling as factory function first, then fallback to constructor
let result;
try {
// Try as factory function
result = registration.constructor(model, providerName, sdk);
}
catch (factoryError) {
// Fallback to constructor
result = new registration.constructor(model, providerName, sdk);
}
// Only await if result is actually a Promise
if (result &&
typeof result === "object" &&
typeof result.then === "function") {
return await result;
}
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);
}