feat(app): add provider methods

This commit is contained in:
ItzCrazyKns
2025-10-18 15:06:00 +05:30
parent e02b9a5efc
commit 5a7f45cace
5 changed files with 447 additions and 3 deletions

View File

@@ -0,0 +1,94 @@
import ModelRegistry from '@/lib/models/registry';
import { Model } from '@/lib/models/types';
import { NextRequest } from 'next/server';
export const POST = async (
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) => {
try {
const { id } = await params;
const body: Partial<Model> & { type: 'embedding' | 'chat' } =
await req.json();
if (!body.key || !body.name) {
return Response.json(
{
message: 'Key and name must be provided',
},
{
status: 400,
},
);
}
const registry = new ModelRegistry();
await registry.addProviderModel(id, body.type, body);
return Response.json(
{
message: 'Model added successfully',
},
{
status: 200,
},
);
} catch (err) {
console.error('An error occurred while adding provider model', err);
return Response.json(
{
message: 'An error has occurred.',
},
{
status: 500,
},
);
}
};
export const DELETE = async (
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) => {
try {
const { id } = await params;
const body: { key: string; type: 'embedding' | 'chat' } = await req.json();
if (!body.key) {
return Response.json(
{
message: 'Key and name must be provided',
},
{
status: 400,
},
);
}
const registry = new ModelRegistry();
await registry.removeProviderModel(id, body.type, body.key);
return Response.json(
{
message: 'Model added successfully',
},
{
status: 200,
},
);
} catch (err) {
console.error('An error occurred while deleting provider model', err);
return Response.json(
{
message: 'An error has occurred.',
},
{
status: 500,
},
);
}
};

View File

@@ -0,0 +1,89 @@
import ModelRegistry from '@/lib/models/registry';
import { NextRequest } from 'next/server';
export const DELETE = async (
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) => {
try {
const { id } = await params;
if (!id) {
return Response.json(
{
message: 'Provider ID is required.',
},
{
status: 400,
},
);
}
const registry = new ModelRegistry();
await registry.removeProvider(id);
return Response.json(
{
message: 'Provider deleted successfully.',
},
{
status: 200,
},
);
} catch (err: any) {
console.error('An error occurred while deleting provider', err.message);
return Response.json(
{
message: 'An error has occurred.',
},
{
status: 500,
},
);
}
};
export const PATCH = async (
req: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) => {
try {
const body = await req.json();
const { name, config } = body;
const { id } = await params;
if (!id || !name || !config) {
return Response.json(
{
message: 'Missing required fields.',
},
{
status: 400,
},
);
}
const registry = new ModelRegistry();
const updatedProvider = await registry.updateProvider(id, name, config);
return Response.json(
{
provider: updatedProvider,
},
{
status: 200,
},
);
} catch (err: any) {
console.error('An error occurred while updating provider', err.message);
return Response.json(
{
message: 'An error has occurred.',
},
{
status: 500,
},
);
}
};

View File

@@ -1,4 +1,5 @@
import ModelRegistry from '@/lib/models/registry';
import { NextRequest } from 'next/server';
export const GET = async (req: Request) => {
try {
@@ -6,9 +7,13 @@ export const GET = async (req: Request) => {
const activeProviders = await registry.getActiveProviders();
const filteredProviders = activeProviders.filter((p) => {
return !p.chatModels.some((m) => m.key === 'error');
});
return Response.json(
{
providers: activeProviders,
providers: filteredProviders,
},
{
status: 200,
@@ -26,3 +31,44 @@ export const GET = async (req: Request) => {
);
}
};
export const POST = async (req: NextRequest) => {
try {
const body = await req.json();
const { type, name, config } = body;
if (!type || !name || !config) {
return Response.json(
{
message: 'Missing required fields.',
},
{
status: 400,
},
);
}
const registry = new ModelRegistry();
const newProvider = await registry.addProvider(type, name, config);
return Response.json(
{
provider: newProvider,
},
{
status: 200,
},
);
} catch (err) {
console.error('An error occurred while creating provider', err);
return Response.json(
{
message: 'An error has occurred.',
},
{
status: 500,
},
);
}
};

View File

@@ -225,6 +225,8 @@ class ConfigManager {
this.currentConfig.modelProviders.push(newModelProvider);
this.saveConfig();
return newModelProvider;
}
public removeModelProvider(id: string) {
@@ -240,6 +242,69 @@ class ConfigManager {
this.saveConfig();
}
public async updateModelProvider(id: string, name: string, config: any) {
const provider = this.currentConfig.modelProviders.find((p) => {
return p.id === id;
});
if (!provider) throw new Error('Provider not found');
provider.name = name;
provider.config = config;
this.saveConfig();
return provider;
}
public addProviderModel(
providerId: string,
type: 'embedding' | 'chat',
model: any,
) {
const provider = this.currentConfig.modelProviders.find(
(p) => p.id === providerId,
);
if (!provider) throw new Error('Invalid provider id');
delete model.type;
if (type === 'chat') {
provider.chatModels.push(model);
} else {
provider.embeddingModels.push(model);
}
this.saveConfig();
return model;
}
public removeProviderModel(
providerId: string,
type: 'embedding' | 'chat',
modelKey: string,
) {
const provider = this.currentConfig.modelProviders.find(
(p) => p.id === providerId,
);
if (!provider) throw new Error('Invalid provider id');
if (type === 'chat') {
provider.chatModels = provider.chatModels.filter(
(m) => m.key !== modelKey,
);
} else {
provider.embeddingModels = provider.embeddingModels.filter(
(m) => m.key != modelKey,
);
}
this.saveConfig();
}
public isSetupComplete() {
return this.currentConfig.setupComplete;
}
@@ -255,6 +320,10 @@ class ConfigManager {
public getUIConfigSections(): UIConfigSections {
return this.uiConfigSections;
}
public getCurrentConfig(): Config {
return JSON.parse(JSON.stringify(this.currentConfig));
}
}
const configManager = new ConfigManager();

View File

@@ -4,7 +4,8 @@ import BaseModelProvider, {
} from './providers/baseProvider';
import { getConfiguredModelProviders } from '../config/serverRegistry';
import { providers } from './providers';
import { MinimalProvider, Model } from './types';
import { MinimalProvider, ModelList } from './types';
import configManager from '../config';
class ModelRegistry {
activeProviders: (ConfigModelProvider & {
@@ -40,7 +41,25 @@ class ModelRegistry {
await Promise.all(
this.activeProviders.map(async (p) => {
const m = await p.provider.getModelList();
let m: ModelList = { chat: [], embedding: [] };
try {
m = await p.provider.getModelList();
} catch (err: any) {
console.error(
`Failed to get model list. Type: ${p.type}, ID: ${p.id}, Error: ${err.message}`,
);
m = {
chat: [
{
key: 'error',
name: err.message,
},
],
embedding: [],
};
}
providers.push({
id: p.id,
@@ -48,6 +67,7 @@ class ModelRegistry {
chatModels: m.chat,
embeddingModels: m.embedding,
});
}),
);
@@ -73,6 +93,132 @@ class ModelRegistry {
return model;
}
async addProvider(
type: string,
name: string,
config: Record<string, any>,
): Promise<ConfigModelProvider> {
const provider = providers[type];
if (!provider) throw new Error('Invalid provider type');
const newProvider = configManager.addModelProvider(type, name, config);
const instance = createProviderInstance(
provider,
newProvider.id,
newProvider.name,
newProvider.config,
);
let m: ModelList = { chat: [], embedding: [] };
try {
m = await instance.getModelList();
} catch (err: any) {
console.error(
`Failed to get model list for newly added provider. Type: ${type}, ID: ${newProvider.id}, Error: ${err.message}`,
);
m = {
chat: [
{
key: 'error',
name: err.message,
},
],
embedding: [],
};
}
this.activeProviders.push({
...newProvider,
provider: instance,
});
return {
...newProvider,
chatModels: m.chat || [],
embeddingModels: m.embedding || [],
};
}
async removeProvider(providerId: string): Promise<void> {
configManager.removeModelProvider(providerId);
this.activeProviders = this.activeProviders.filter(
(p) => p.id !== providerId,
);
return;
}
async updateProvider(
providerId: string,
name: string,
config: any,
): Promise<ConfigModelProvider> {
const updated = await configManager.updateModelProvider(
providerId,
name,
config,
);
const instance = createProviderInstance(
providers[updated.type],
providerId,
name,
config,
);
let m: ModelList = { chat: [], embedding: [] };
try {
m = await instance.getModelList();
} catch (err: any) {
console.error(
`Failed to get model list for updated provider. Type: ${updated.type}, ID: ${updated.id}, Error: ${err.message}`,
);
m = {
chat: [
{
key: 'error',
name: err.message,
},
],
embedding: [],
};
}
this.activeProviders.push({
...updated,
provider: instance,
});
return {
...updated,
chatModels: m.chat || [],
embeddingModels: m.embedding || [],
};
}
/* Using async here because maybe in the future we might want to add some validation?? */
async addProviderModel(
providerId: string,
type: 'embedding' | 'chat',
model: any,
): Promise<any> {
const addedModel = configManager.addProviderModel(providerId, type, model);
return addedModel;
}
async removeProviderModel(
providerId: string,
type: 'embedding' | 'chat',
modelKey: string,
): Promise<void> {
configManager.removeProviderModel(providerId, type, modelKey);
return;
}
}
export default ModelRegistry;