UNPKG

route-claudecode

Version:

Advanced routing and transformation system for Claude Code outputs to multiple AI providers

239 lines 9.11 kB
"use strict"; /** * 纯API调用客户端封装 * 提供最小化的OpenAI API调用封装,无业务逻辑 * * 遵循零硬编码、零Fallback、零沉默失败原则 */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PureOpenAIAPIClient = void 0; const openai_1 = __importDefault(require("openai")); const logger_1 = require("@/utils/logger"); const config_validation_1 = require("./config-validation"); /** * 纯粹的OpenAI API客户端 * 只负责API调用,不包含任何业务逻辑或格式转换 */ class PureOpenAIAPIClient { client; config; constructor(config) { // 🚨 验证配置,不允许fallback this.validateConfig(config); this.config = config; // 验证API Key const tempConfig = { authentication: { type: 'api_key', credentials: { apiKey: config.apiKey } } }; const validatedApiKey = (0, config_validation_1.validateApiKey)(tempConfig, 'OpenAI-API'); // 初始化OpenAI SDK this.client = new openai_1.default({ apiKey: validatedApiKey || 'dummy-key', baseURL: config.baseURL, timeout: config.timeout || 60000, maxRetries: config.maxRetries || 3, defaultHeaders: { 'User-Agent': 'claude-code-router-pure-api/2.9.0', ...config.defaultHeaders } }); logger_1.logger.debug('Pure OpenAI API Client initialized', { baseURL: config.baseURL, hasApiKey: !!config.apiKey, timeout: config.timeout || 60000, maxRetries: config.maxRetries || 3, allowDummyKey: config.allowDummyKey || false }); } /** * 🎯 发送非流式请求 */ async sendChatCompletion(params) { this.validateRequestParams(params); const requestParams = { ...params, stream: false }; logger_1.logger.debug('Sending OpenAI chat completion request', { model: params.model, messageCount: params.messages.length, hasTools: !!(params.tools && params.tools.length > 0), maxTokens: params.max_tokens }); try { const response = await this.client.chat.completions.create(requestParams); if (!response) { throw new Error('OpenAI API returned null response - potential silent failure'); } if (!response.choices || response.choices.length === 0) { throw new Error('OpenAI API returned no choices - invalid response format'); } return response; } catch (error) { this.handleApiError(error, 'chat completion'); throw error; // 重新抛出,确保无静默失败 } } /** * 🎯 发送流式请求 */ async sendStreamChatCompletion(params) { this.validateRequestParams(params); const requestParams = { ...params, stream: true }; logger_1.logger.debug('Sending OpenAI streaming chat completion request', { model: params.model, messageCount: params.messages.length, hasTools: !!(params.tools && params.tools.length > 0), maxTokens: params.max_tokens }); try { const stream = await this.client.chat.completions.create(requestParams); if (!stream) { throw new Error('OpenAI API returned null stream - potential silent failure'); } // 验证stream是可迭代的 if (!(Symbol.asyncIterator in stream)) { throw new Error('OpenAI API returned non-iterable stream - invalid response format'); } return stream; } catch (error) { this.handleApiError(error, 'streaming chat completion'); throw error; // 重新抛出,确保无静默失败 } } /** * 🎯 健康检查 */ async healthCheck() { try { const testParams = { model: 'gpt-3.5-turbo', // 使用最基础的模型进行健康检查 messages: [{ role: 'user', content: 'test' }], max_tokens: 1 }; const response = await this.sendChatCompletion(testParams); return !!(response && response.id); } catch (error) { logger_1.logger.warn('OpenAI API health check failed', { error: error instanceof Error ? error.message : String(error), baseURL: this.config.baseURL }); return false; } } /** * 验证配置 */ validateConfig(config) { if (!config) { throw new Error('OpenAI client config is required - violates zero fallback principle'); } if (!config.baseURL) { throw new Error('OpenAI client baseURL is required - violates zero fallback principle'); } // 🚨 检查fallback baseURL if (config.baseURL === 'default' || config.baseURL === 'unknown') { throw new Error(`Invalid baseURL: ${config.baseURL} - violates zero fallback principle`); } // 验证timeout不是fallback值 if (config.timeout === 0) { throw new Error('OpenAI client timeout cannot be 0 - violates zero fallback principle'); } // 验证maxRetries不是负值 if (config.maxRetries !== undefined && config.maxRetries < 0) { throw new Error('OpenAI client maxRetries cannot be negative - violates zero fallback principle'); } } /** * 验证请求参数 */ validateRequestParams(params) { if (!params) { throw new Error('Request params are required - violates zero fallback principle'); } if (!params.model) { throw new Error('Model is required - violates zero fallback principle'); } if (!params.messages || !Array.isArray(params.messages)) { throw new Error('Messages array is required - violates zero fallback principle'); } if (params.messages.length === 0) { throw new Error('At least one message is required - violates zero fallback principle'); } // 🚨 检查fallback模型名 if (params.model === 'default' || params.model === 'unknown') { throw new Error(`Invalid model name: ${params.model} - violates zero fallback principle`); } // 验证每个消息的格式 params.messages.forEach((msg, index) => { if (!msg || typeof msg !== 'object') { throw new Error(`Invalid message at index ${index} - violates zero fallback principle`); } if (!msg.role) { throw new Error(`Message at index ${index} missing role - violates zero fallback principle`); } // 检查fallback role if (msg.role === 'default' || msg.role === 'unknown') { throw new Error(`Invalid role at index ${index}: ${msg.role} - violates zero fallback principle`); } }); // 验证工具配置(如果存在) if (params.tools && !Array.isArray(params.tools)) { throw new Error('Tools must be an array - violates zero fallback principle'); } } /** * 处理API错误 */ handleApiError(error, operation) { const errorMessage = error instanceof Error ? error.message : String(error); const httpStatus = error?.response?.status || error?.status || 500; console.error(`🚨 [OpenAI-API-CLIENT] ${operation.toUpperCase()} FAILED - NO SILENT FAILURE:`); console.error(` Operation: ${operation}`); console.error(` Base URL: ${this.config.baseURL}`); console.error(` Status: ${httpStatus}`); console.error(` Error: ${errorMessage}`); console.error(` RESULT: Throwing error to prevent silent failure`); logger_1.logger.error(`OpenAI API ${operation} failed`, { error: errorMessage, status: httpStatus, baseURL: this.config.baseURL, operation }); } /** * 获取客户端配置(只读) */ getConfig() { return { ...this.config }; } /** * 获取基础URL */ getBaseURL() { return this.config.baseURL; } /** * 检查是否有有效的API Key */ hasValidApiKey() { return !!(this.config.apiKey && this.config.apiKey !== 'dummy-key' && this.config.apiKey !== 'fake-key' && this.config.apiKey !== 'placeholder'); } } exports.PureOpenAIAPIClient = PureOpenAIAPIClient; //# sourceMappingURL=openai-api-client.js.map