From 64c4514cad782e5b051e7ff8fa4ad3e6c28b1bb3 Mon Sep 17 00:00:00 2001 From: ItzCrazyKns <95534749+ItzCrazyKns@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:03:17 +0530 Subject: [PATCH] feat(models): add `id` & `name` fields, move `getUIConfigSection` to seperate file --- src/lib/models/providers/baseProvider.ts | 27 +++++++++- src/lib/models/providers/index.ts | 21 ++++++++ src/lib/models/providers/openai.ts | 28 +++++----- src/lib/models/registry.ts | 68 +++++++++++++++--------- 4 files changed, 107 insertions(+), 37 deletions(-) create mode 100644 src/lib/models/providers/index.ts diff --git a/src/lib/models/providers/baseProvider.ts b/src/lib/models/providers/baseProvider.ts index 1d7ef47..980a2b2 100644 --- a/src/lib/models/providers/baseProvider.ts +++ b/src/lib/models/providers/baseProvider.ts @@ -4,7 +4,11 @@ import { Model, ModelList, ProviderMetadata } from '../types'; import { UIConfigField } from '@/lib/config/types'; abstract class BaseModelProvider { - constructor(protected config: CONFIG) {} + constructor( + protected id: string, + protected name: string, + protected config: CONFIG, + ) {} abstract getDefaultModels(): Promise; abstract getModelList(): Promise; abstract loadChatModel(modelName: string): Promise; @@ -15,6 +19,27 @@ abstract class BaseModelProvider { static getProviderMetadata(): ProviderMetadata { throw new Error('Method not Implemented.'); } + static parseAndValidate(raw: any): any { + /* Static methods can't access class type parameters */ + throw new Error('Method not Implemented.'); + } } +export type ProviderConstructor = { + new (id: string, name: string, config: CONFIG): BaseModelProvider; + parseAndValidate(raw: any): CONFIG; + getProviderConfigFields: () => UIConfigField[]; + getProviderMetadata: () => ProviderMetadata; +}; + +export const createProviderInstance =

>( + Provider: P, + id: string, + name: string, + rawConfig: unknown, +): InstanceType

=> { + const cfg = Provider.parseAndValidate(rawConfig); + return new Provider(id, name, cfg) as InstanceType

; +}; + export default BaseModelProvider; diff --git a/src/lib/models/providers/index.ts b/src/lib/models/providers/index.ts new file mode 100644 index 0000000..b893400 --- /dev/null +++ b/src/lib/models/providers/index.ts @@ -0,0 +1,21 @@ +import { ModelProviderUISection } from '@/lib/config/types'; +import { ProviderConstructor } from './baseProvider'; +import OpenAIProvider from './openai'; + +export const providers: Record> = { + openai: OpenAIProvider, +}; + +export const getModelProvidersUIConfigSection = + (): ModelProviderUISection[] => { + return Object.entries(providers).map(([k, p]) => { + const configFields = p.getProviderConfigFields(); + const metadata = p.getProviderMetadata(); + + return { + fields: configFields, + key: k, + name: metadata.name, + }; + }); + }; diff --git a/src/lib/models/providers/openai.ts b/src/lib/models/providers/openai.ts index 5569b97..fee3b52 100644 --- a/src/lib/models/providers/openai.ts +++ b/src/lib/models/providers/openai.ts @@ -6,7 +6,6 @@ import { Embeddings } from '@langchain/core/embeddings'; import { UIConfigField } from '@/lib/config/types'; interface OpenAIConfig { - name: string; apiKey: string; baseURL: string; } @@ -90,15 +89,6 @@ const defaultEmbeddingModels: Model[] = [ ]; const providerConfigFields: UIConfigField[] = [ - /* { - type: 'string', - name: 'Name (Optional)', - key: 'name', - description: 'An optional name for this provider configuration', - required: false, - placeholder: 'Provider Name', - scope: 'server', - }, */ /* FOR NAME DIRECTLY CREATE INPUT IN FRONTEND */ { type: 'password', name: 'API Key', @@ -123,8 +113,8 @@ const providerConfigFields: UIConfigField[] = [ ]; class OpenAIProvider extends BaseModelProvider { - constructor(config: OpenAIConfig) { - super(config); + constructor(id: string, name: string, config: OpenAIConfig) { + super(id, name, config); } async getDefaultModels(): Promise { @@ -192,6 +182,20 @@ class OpenAIProvider extends BaseModelProvider { }); } + static parseAndValidate(raw: any): OpenAIConfig { + if (!raw || typeof raw !== 'object') + throw new Error('Invalid config provided. Expected object'); + if (!raw.apiKey || !raw.baseURL) + throw new Error( + 'Invalid config provided. API key and base URL must be provided', + ); + + return { + apiKey: String(raw.apiKey), + baseURL: String(raw.baseURL), + }; + } + static getProviderConfigFields(): UIConfigField[] { return providerConfigFields; } diff --git a/src/lib/models/registry.ts b/src/lib/models/registry.ts index 5538e9e..2d4de6f 100644 --- a/src/lib/models/registry.ts +++ b/src/lib/models/registry.ts @@ -1,33 +1,53 @@ -import { ModelProviderUISection, UIConfigField } from '../config/types'; -import { ProviderMetadata } from './types'; -import BaseModelProvider from './providers/baseProvider'; -import OpenAIProvider from './providers/openai'; - -interface ProviderClass { - new (config: T): BaseModelProvider; - getProviderConfigFields(): UIConfigField[]; - getProviderMetadata(): ProviderMetadata; -} - -const providers: Record> = { - openai: OpenAIProvider, -}; +import { ConfigModelProvider } from '../config/types'; +import BaseModelProvider, { + createProviderInstance, +} from './providers/baseProvider'; +import { getConfiguredModelProviders } from '../config/serverRegistry'; +import { providers } from './providers'; +import { ModelList } from './types'; class ModelRegistry { - constructor() {} + activeProviders: (ConfigModelProvider & { + provider: BaseModelProvider; + })[] = []; - getUIConfigSection(): ModelProviderUISection[] { - return Object.entries(providers).map(([k, p]) => { - const configFields = p.getProviderConfigFields(); - const metadata = p.getProviderMetadata(); + constructor() { + this.initializeActiveProviders(); + } - return { - fields: configFields, - key: k, - name: metadata.name, - }; + private initializeActiveProviders() { + const configuredProviders = getConfiguredModelProviders(); + + configuredProviders.forEach((p) => { + try { + const provider = providers[p.type]; + if (!provider) throw new Error('Invalid provider type'); + + this.activeProviders.push({ + ...p, + provider: createProviderInstance(provider, p.id, p.name, p.config), + }); + } catch (err) { + console.error( + `Failed to initialize provider. Type: ${p.type}, ID: ${p.id}, Config: ${JSON.stringify(p.config)}, Error: ${err}`, + ); + } }); } + + async getActiveModels() { + const models: ModelList[] = []; + + await Promise.all( + this.activeProviders.map(async (p) => { + const m = await p.provider.getModelList(); + + models.push(m); + }), + ); + + return models; + } } export default ModelRegistry;