@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
251 lines (250 loc) • 8.88 kB
JavaScript
import { z } from "zod";
import { logger } from "../utils/logger.js";
/**
* Model configuration schema for validation
*/
const ModelConfigSchema = z.object({
id: z.string(),
displayName: z.string(),
capabilities: z.array(z.string()),
deprecated: z.boolean(),
pricing: z.object({
input: z.number(),
output: z.number(),
}),
contextWindow: z.number(),
releaseDate: z.string(),
});
const ModelRegistrySchema = z.object({
version: z.string(),
lastUpdated: z.string(),
models: z.record(z.record(ModelConfigSchema)),
aliases: z.record(z.string()).optional(),
defaults: z.record(z.string()).optional(),
});
/**
* Dynamic Model Provider
* Loads and manages model configurations from external sources
*/
export class DynamicModelProvider {
static instance;
modelRegistry = null;
lastFetch = 0;
CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
constructor() { }
static getInstance() {
if (!this.instance) {
this.instance = new DynamicModelProvider();
}
return this.instance;
}
/**
* Initialize the model registry from multiple sources
*/
async initialize() {
const sources = [
process.env.MODEL_CONFIG_URL || "http://localhost:3001/api/v1/models",
"https://raw.githubusercontent.com/sachinsharma92/neurolink/main/config/models.json",
"./config/models.json", // Local fallback
];
for (const source of sources) {
try {
logger.debug(`[DynamicModelProvider] Attempting to load from: ${source}`);
const config = await this.loadFromSource(source);
// Validate the configuration
const validatedConfig = ModelRegistrySchema.parse(config);
this.modelRegistry = validatedConfig;
this.lastFetch = Date.now();
logger.info(`[DynamicModelProvider] Successfully loaded model registry from: ${source}`, {
modelCount: this.getTotalModelCount(),
providerCount: Object.keys(validatedConfig.models).length,
});
return; // Success, stop trying other sources
}
catch (error) {
logger.warn(`[DynamicModelProvider] Failed to load from ${source}:`, error);
continue;
}
}
throw new Error("Failed to load model configuration from any source");
}
/**
* Load configuration from a source (URL or file path)
*/
async loadFromSource(source) {
if (source.startsWith("http")) {
// Load from URL
const response = await fetch(source, {
headers: {
"User-Agent": "NeuroLink/1.0 (+https://github.com/sachinsharma92/neurolink)",
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
else {
// Load from local file
const fs = await import("fs");
const path = await import("path");
const fullPath = path.resolve(source);
const content = fs.readFileSync(fullPath, "utf8");
return JSON.parse(content);
}
}
/**
* Get all available models for a provider
*/
getModelsForProvider(provider) {
this.ensureInitialized();
return this.modelRegistry?.models[provider] || {};
}
/**
* Resolve a model by provider and model hint
*/
resolveModel(provider, modelHint) {
this.ensureInitialized();
const providerModels = this.getModelsForProvider(provider);
if (!modelHint) {
// Use default model for provider
const defaultModel = this.modelRegistry?.defaults?.[provider];
return defaultModel ? providerModels[defaultModel] : null;
}
// Check for exact match
if (providerModels[modelHint]) {
return providerModels[modelHint];
}
// Check aliases
const aliasTarget = this.modelRegistry?.aliases?.[modelHint];
if (aliasTarget) {
const [aliasProvider, aliasModel] = aliasTarget.split("/");
return this.resolveModel(aliasProvider, aliasModel);
}
// Fuzzy matching (partial string match)
const fuzzyMatch = Object.keys(providerModels).find((key) => key.toLowerCase().includes(modelHint.toLowerCase()) ||
modelHint.toLowerCase().includes(key.toLowerCase()));
return fuzzyMatch ? providerModels[fuzzyMatch] : null;
}
/**
* Search models by capabilities
*/
searchByCapability(capability, options = {}) {
this.ensureInitialized();
const results = [];
for (const [providerName, models] of Object.entries(this.modelRegistry.models)) {
if (options.provider && providerName !== options.provider) {
continue;
}
for (const [modelName, modelConfig] of Object.entries(models)) {
if (options.excludeDeprecated && modelConfig.deprecated) {
continue;
}
if (options.maxPrice && modelConfig.pricing.input > options.maxPrice) {
continue;
}
if (!modelConfig.capabilities.includes(capability)) {
continue;
}
results.push({
provider: providerName,
model: modelName,
config: modelConfig,
});
}
}
// Sort by price (cheapest first)
return results.sort((a, b) => a.config.pricing.input - b.config.pricing.input);
}
/**
* Get the best model for a specific use case
*/
getBestModelFor(useCase) {
this.ensureInitialized();
switch (useCase) {
case "coding":
return (this.searchByCapability("functionCalling", {
excludeDeprecated: true,
})[0] || null);
case "analysis":
return (this.searchByCapability("analysis", { excludeDeprecated: true })[0] ||
null);
case "vision":
return (this.searchByCapability("vision", { excludeDeprecated: true })[0] ||
null);
case "fastest":
// Return cheapest as proxy for fastest (usually correlates)
return (this.getAllModels()
.filter((m) => !m.config.deprecated)
.sort((a, b) => a.config.pricing.input - b.config.pricing.input)[0] || null);
case "cheapest":
return (this.getAllModels()
.filter((m) => !m.config.deprecated)
.sort((a, b) => a.config.pricing.input - b.config.pricing.input)[0] || null);
default:
return null;
}
}
/**
* Get all models across all providers
*/
getAllModels() {
this.ensureInitialized();
const results = [];
for (const [providerName, models] of Object.entries(this.modelRegistry.models)) {
for (const [modelName, modelConfig] of Object.entries(models)) {
results.push({
provider: providerName,
model: modelName,
config: modelConfig,
});
}
}
return results;
}
/**
* Get total number of models
*/
getTotalModelCount() {
if (!this.modelRegistry) {
return 0;
}
return Object.values(this.modelRegistry.models).reduce((total, providerModels) => total + Object.keys(providerModels).length, 0);
}
/**
* Check if cache needs refresh
*/
needsRefresh() {
return Date.now() - this.lastFetch > this.CACHE_DURATION;
}
/**
* Force refresh the model registry
*/
async refresh() {
this.modelRegistry = null;
await this.initialize();
}
/**
* Ensure the registry is initialized
*/
ensureInitialized() {
if (!this.modelRegistry) {
throw new Error("Model registry not initialized. Call initialize() first.");
}
}
/**
* Get registry metadata
*/
getMetadata() {
if (!this.modelRegistry) {
return null;
}
return {
version: this.modelRegistry.version,
lastUpdated: this.modelRegistry.lastUpdated,
modelCount: this.getTotalModelCount(),
};
}
}
// Export singleton instance
export const dynamicModelProvider = DynamicModelProvider.getInstance();