UNPKG

jezweb-mcp-core

Version:

Jezweb Model Context Protocol (MCP) Core - A universal server for providing AI tools and resources, designed for seamless integration with various AI models and clients. Features adaptable multi-provider support, comprehensive tool and resource management

452 lines 16.5 kB
/** * OpenAI Provider Plugin - OpenAI-specific implementation of the LLM Provider interface * * This module refactors the existing OpenAI service to implement the generic LLM provider * interface, enabling it to work within the provider registry system while maintaining * full backward compatibility with existing OpenAI functionality. * * Key Features: * - Full OpenAI Assistants API implementation * - Generic LLM provider interface compliance * - Backward compatibility with existing OpenAI service * - Type mapping between OpenAI and generic types * - Enhanced error handling and validation */ import { createProviderError, } from '../llm-service.js'; import { mapOpenAIToGenericAssistant, mapOpenAIToGenericThread, mapOpenAIToGenericMessage, mapOpenAIToGenericRun, mapOpenAIToGenericRunStep, mapGenericToOpenAICreateAssistantRequest, mapOpenAIToGenericListResponse, } from '../../types/generic-types.js'; // Import the existing OpenAI service for delegation import { OpenAIService } from '../openai-service.js'; import { MCPError, ErrorCodes, } from '../../types/index.js'; /** * OpenAI Provider Implementation * Implements the generic LLM provider interface for OpenAI */ export class OpenAIProvider { openaiService; config; metadata = { name: 'openai', displayName: 'OpenAI', version: '1.0.0', description: 'OpenAI Assistants API provider with full feature support', capabilities: { assistants: true, threads: true, messages: true, runs: true, runSteps: true, fileAttachments: true, functionCalling: true, codeInterpreter: true, fileSearch: true, streaming: false, // Not implemented in current service customModels: false, maxContextLength: 128000, // GPT-4 context length supportedModels: [ 'gpt-4', 'gpt-4o', 'gpt-4-turbo', 'gpt-4-turbo-preview', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', ], }, configSchema: { type: 'object', properties: { apiKey: { type: 'string', description: 'OpenAI API key' }, baseUrl: { type: 'string', description: 'Custom base URL' }, organization: { type: 'string', description: 'Organization ID' }, project: { type: 'string', description: 'Project ID' }, timeout: { type: 'number', description: 'Request timeout in milliseconds' }, maxRetries: { type: 'number', description: 'Maximum retry attempts' }, headers: { type: 'object', description: 'Custom headers' }, }, required: ['apiKey'], }, documentationUrl: 'https://platform.openai.com/docs/assistants', }; constructor(config) { this.config = config; this.openaiService = new OpenAIService(config.apiKey); } /** * Initialize the provider with configuration */ async initialize(config) { try { // Validate configuration if (!config.apiKey) { throw createProviderError('openai', 'API key is required', undefined, ErrorCodes.INVALID_PARAMS); } // Update configuration this.config = { ...this.config, ...config }; // Reinitialize OpenAI service with new config this.openaiService = new OpenAIService(this.config.apiKey); // Validate connection const isValid = await this.validateConnection(); if (!isValid) { throw createProviderError('openai', 'Failed to validate OpenAI API connection'); } } catch (error) { throw createProviderError('openai', `Failed to initialize OpenAI provider: ${error instanceof Error ? error.message : 'Unknown error'}`, error); } } /** * Validate provider configuration and connectivity */ async validateConnection() { try { return await this.openaiService.validateApiKey(); } catch (error) { return false; } } /** * Assistant Management Methods */ async createAssistant(request) { try { const openaiRequest = mapGenericToOpenAICreateAssistantRequest(request); // Ensure tool_resources is passed through if (request.tool_resources) { openaiRequest.tool_resources = request.tool_resources; } const openaiAssistant = await this.openaiService.createAssistant(openaiRequest); return mapOpenAIToGenericAssistant(openaiAssistant); } catch (error) { throw this.handleError('createAssistant', error); } } async listAssistants(request = {}) { try { const openaiRequest = { limit: request.limit, order: request.order, after: request.after, before: request.before, }; const openaiResponse = await this.openaiService.listAssistants(openaiRequest); return mapOpenAIToGenericListResponse(openaiResponse, mapOpenAIToGenericAssistant); } catch (error) { throw this.handleError('listAssistants', error); } } async getAssistant(assistantId) { try { const openaiAssistant = await this.openaiService.getAssistant(assistantId); return mapOpenAIToGenericAssistant(openaiAssistant); } catch (error) { throw this.handleError('getAssistant', error); } } async updateAssistant(assistantId, request) { try { const openaiRequest = { model: request.model, name: request.name, description: request.description, instructions: request.instructions, tools: request.tools?.map(tool => ({ type: tool.type, function: tool.function, })), tool_resources: request.tool_resources, metadata: request.metadata, }; const openaiAssistant = await this.openaiService.updateAssistant(assistantId, openaiRequest); return mapOpenAIToGenericAssistant(openaiAssistant); } catch (error) { throw this.handleError('updateAssistant', error); } } async deleteAssistant(assistantId) { try { const result = await this.openaiService.deleteAssistant(assistantId); return { id: result.id, deleted: result.deleted }; } catch (error) { throw this.handleError('deleteAssistant', error); } } /** * Thread Management Methods */ async createThread(request = {}) { try { const openaiRequest = { messages: request.messages?.map(msg => ({ role: msg.role, content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content), metadata: msg.metadata, })), metadata: request.metadata, }; const openaiThread = await this.openaiService.createThread(openaiRequest); return mapOpenAIToGenericThread(openaiThread); } catch (error) { throw this.handleError('createThread', error); } } async getThread(threadId) { try { const openaiThread = await this.openaiService.getThread(threadId); return mapOpenAIToGenericThread(openaiThread); } catch (error) { throw this.handleError('getThread', error); } } async updateThread(threadId, request) { try { const openaiRequest = { metadata: request.metadata, }; const openaiThread = await this.openaiService.updateThread(threadId, openaiRequest); return mapOpenAIToGenericThread(openaiThread); } catch (error) { throw this.handleError('updateThread', error); } } async deleteThread(threadId) { try { const result = await this.openaiService.deleteThread(threadId); return { id: result.id, deleted: result.deleted }; } catch (error) { throw this.handleError('deleteThread', error); } } /** * Message Management Methods */ async createMessage(threadId, request) { try { const openaiRequest = { role: request.role, content: typeof request.content === 'string' ? request.content : JSON.stringify(request.content), metadata: request.metadata, }; const openaiMessage = await this.openaiService.createMessage(threadId, openaiRequest); return mapOpenAIToGenericMessage(openaiMessage); } catch (error) { throw this.handleError('createMessage', error); } } async listMessages(threadId, request = {}) { try { const openaiRequest = { limit: request.limit, order: request.order, after: request.after, before: request.before, }; const openaiResponse = await this.openaiService.listMessages(threadId, openaiRequest); return mapOpenAIToGenericListResponse(openaiResponse, mapOpenAIToGenericMessage); } catch (error) { throw this.handleError('listMessages', error); } } async getMessage(threadId, messageId) { try { const openaiMessage = await this.openaiService.getMessage(threadId, messageId); return mapOpenAIToGenericMessage(openaiMessage); } catch (error) { throw this.handleError('getMessage', error); } } async updateMessage(threadId, messageId, request) { try { const openaiRequest = { metadata: request.metadata, }; const openaiMessage = await this.openaiService.updateMessage(threadId, messageId, openaiRequest); return mapOpenAIToGenericMessage(openaiMessage); } catch (error) { throw this.handleError('updateMessage', error); } } async deleteMessage(threadId, messageId) { try { const result = await this.openaiService.deleteMessage(threadId, messageId); return { id: result.id, deleted: result.deleted }; } catch (error) { throw this.handleError('deleteMessage', error); } } /** * Run Management Methods */ async createRun(threadId, request) { try { const openaiRequest = { assistant_id: request.assistantId, model: request.model, instructions: request.instructions, additional_instructions: request.additionalInstructions, tools: request.tools?.map(tool => ({ type: tool.type, function: tool.function, })), metadata: request.metadata, }; const openaiRun = await this.openaiService.createRun(threadId, openaiRequest); return mapOpenAIToGenericRun(openaiRun); } catch (error) { throw this.handleError('createRun', error); } } async listRuns(threadId, request = {}) { try { const openaiRequest = { limit: request.limit, order: request.order, after: request.after, before: request.before, }; const openaiResponse = await this.openaiService.listRuns(threadId, openaiRequest); return mapOpenAIToGenericListResponse(openaiResponse, mapOpenAIToGenericRun); } catch (error) { throw this.handleError('listRuns', error); } } async getRun(threadId, runId) { try { const openaiRun = await this.openaiService.getRun(threadId, runId); return mapOpenAIToGenericRun(openaiRun); } catch (error) { throw this.handleError('getRun', error); } } async updateRun(threadId, runId, request) { try { const openaiRequest = { metadata: request.metadata, }; const openaiRun = await this.openaiService.updateRun(threadId, runId, openaiRequest); return mapOpenAIToGenericRun(openaiRun); } catch (error) { throw this.handleError('updateRun', error); } } async cancelRun(threadId, runId) { try { const openaiRun = await this.openaiService.cancelRun(threadId, runId); return mapOpenAIToGenericRun(openaiRun); } catch (error) { throw this.handleError('cancelRun', error); } } async submitToolOutputs(threadId, runId, request) { try { const openaiRequest = { tool_outputs: request.toolOutputs.map(output => ({ tool_call_id: output.toolCallId, output: output.output, })), }; const openaiRun = await this.openaiService.submitToolOutputs(threadId, runId, openaiRequest); return mapOpenAIToGenericRun(openaiRun); } catch (error) { throw this.handleError('submitToolOutputs', error); } } /** * Run Step Management Methods */ async listRunSteps(threadId, runId, request = {}) { try { const openaiRequest = { limit: request.limit, order: request.order, after: request.after, before: request.before, }; const openaiResponse = await this.openaiService.listRunSteps(threadId, runId, openaiRequest); return mapOpenAIToGenericListResponse(openaiResponse, mapOpenAIToGenericRunStep); } catch (error) { throw this.handleError('listRunSteps', error); } } async getRunStep(threadId, runId, stepId) { try { const openaiRunStep = await this.openaiService.getRunStep(threadId, runId, stepId); return mapOpenAIToGenericRunStep(openaiRunStep); } catch (error) { throw this.handleError('getRunStep', error); } } /** * Handle unsupported operations */ async handleUnsupportedOperation(operation, ...args) { throw createProviderError('openai', `Operation not supported: ${operation}`, { operation, args }, ErrorCodes.METHOD_NOT_FOUND); } /** * Private helper methods */ handleError(operation, error) { if (error instanceof MCPError) { return createProviderError('openai', `${operation} failed: ${error.message}`, error, error.code); } return createProviderError('openai', `${operation} failed: ${error instanceof Error ? error.message : 'Unknown error'}`, error); } } /** * OpenAI Provider Factory * Creates OpenAI provider instances */ export class OpenAIProviderFactory { /** * Create a new OpenAI provider instance */ async create(config) { if (!this.validateConfig(config)) { throw new MCPError(ErrorCodes.INVALID_PARAMS, 'Invalid OpenAI provider configuration'); } const provider = new OpenAIProvider(config); await provider.initialize(config); return provider; } /** * Get provider metadata without creating an instance */ getMetadata() { return new OpenAIProvider({ apiKey: '' }).metadata; } /** * Validate provider configuration */ validateConfig(config) { return typeof config === 'object' && config !== null && typeof config.apiKey === 'string' && config.apiKey.length > 0; } } /** * Default OpenAI provider factory instance */ export const openaiProviderFactory = new OpenAIProviderFactory(); //# sourceMappingURL=openai.js.map