UNPKG

route-claudecode

Version:

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

207 lines 8.9 kB
"use strict"; /** * Pure OpenAI Client - 纯粹的OpenAI逻辑 (重构版) * @deprecated Use UnifiedOpenAIClient instead - this client will be removed in v3.0.0 * 废弃警告:请使用UnifiedOpenAIClient - 此客户端将在v3.0.0中移除 * * 只负责与OpenAI API的通信,所有转换逻辑都在transformer中处理 * 遵循零硬编码、零Fallback、零沉默失败原则 */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PureOpenAIClient = void 0; exports.createPureOpenAIClient = createPureOpenAIClient; const openai_1 = __importDefault(require("openai")); const logger_1 = require("@/utils/logger"); const simple_session_manager_1 = require("@/session/simple-session-manager"); const response_validation_1 = require("@/utils/response-validation"); const config_validation_1 = require("@/utils/config-validation"); const pure_openai_api_handler_1 = require("@/utils/pure-openai-api-handler"); /** * 纯粹的OpenAI客户端 - 只做API调用 (重构版) */ class PureOpenAIClient { name; type = 'openai-pure'; config; openaiClient; validatedConfig; sessionManager; apiHandler; constructor(config, providerId) { this.name = providerId; this.config = config; // 🚨 严格配置验证 - 零fallback原则 this.validatedConfig = (0, config_validation_1.validateProviderConfig)(config, providerId, config.sdkOptions); // 初始化OpenAI SDK this.openaiClient = new openai_1.default({ apiKey: this.validatedConfig.apiKey, baseURL: this.validatedConfig.baseURL, timeout: this.validatedConfig.sdkOptions.timeout, maxRetries: this.validatedConfig.sdkOptions.maxRetries, defaultHeaders: this.validatedConfig.sdkOptions.defaultHeaders }); // 初始化会话管理 this.sessionManager = (0, simple_session_manager_1.getSimpleSessionManager)(this.validatedConfig.port); // 初始化纯净API处理器(无transformer耦合) this.apiHandler = (0, pure_openai_api_handler_1.createPureAPIHandler)({ providerName: this.name, openaiClient: this.openaiClient }); logger_1.logger.info('Pure OpenAI Client initialized', { providerId, baseURL: this.validatedConfig.baseURL, hasApiKey: true, port: this.validatedConfig.port, timeout: this.validatedConfig.sdkOptions.timeout, maxRetries: this.validatedConfig.sdkOptions.maxRetries }); } /** * 发送非流式请求 - 使用统一API处理器 */ async sendRequest(request) { const originalRequestId = request.metadata?.requestId || 'unknown'; const sessionId = request.metadata?.sessionId; const conversationId = request.metadata?.conversationId; // 生成会话ID(如果有会话信息) let requestId = originalRequestId; if (sessionId && conversationId) { requestId = this.sessionManager.generateRequestId(sessionId, conversationId, false); request.metadata = { ...request.metadata, requestId, originalRequestId }; } try { // 🎯 预期 request.metadata.openaiRequest 包含已转换的OpenAI格式 const openaiRequest = request.metadata?.openaiRequest || this.extractOpenAIFormat(request); // 纯净的OpenAI API调用,不做任何转换 const rawResponse = await this.apiHandler.callAPI(openaiRequest, requestId); // 简单包装为BaseResponse格式,详细转换由外部Transformer处理 const baseResponse = this.wrapResponse(rawResponse, requestId); // 标记会话完成 if (sessionId && conversationId) { this.sessionManager.completeRequest(requestId, baseResponse.stop_reason); } return baseResponse; } catch (error) { // 标记会话失败 if (sessionId && conversationId) { this.sessionManager.failRequest(requestId, error); } // 🚨 统一错误处理,确保无静默失败 (0, response_validation_1.handleProviderError)(error, requestId, this.name, 'non-streaming'); } } /** * 发送流式请求 - 基于非流式API的流式模拟 */ async *sendStreamRequest(request) { const originalRequestId = request.metadata?.requestId || 'unknown'; const sessionId = request.metadata?.sessionId; const conversationId = request.metadata?.conversationId; // 生成会话ID(如果有会话信息) let requestId = originalRequestId; if (sessionId && conversationId) { requestId = this.sessionManager.generateRequestId(sessionId, conversationId, true); request.metadata = { ...request.metadata, requestId, originalRequestId }; } try { // 🎯 预期 request.metadata.openaiRequest 包含已转换的OpenAI格式 const openaiRequest = request.metadata?.openaiRequest || this.extractOpenAIFormat(request); // 直接使用纯净的OpenAI流式 API let finalResponse = null; for await (const chunk of this.apiHandler.callStreamingAPI(openaiRequest, requestId)) { // 直接传递OpenAI原始 chunk,转换由外部处理 yield chunk; // 记录最后的chunk用于会话管理 if (chunk.choices && chunk.choices[0]?.finish_reason) { finalResponse = { stop_reason: chunk.choices[0].finish_reason }; } } // 标记会话完成 if (sessionId && conversationId && finalResponse) { this.sessionManager.completeRequest(requestId, finalResponse.stop_reason); } logger_1.logger.debug('Pure OpenAI streaming completed', { requestId, provider: this.name }, requestId, 'provider'); } catch (error) { // 标记会话失败 if (sessionId && conversationId) { this.sessionManager.failRequest(requestId, error); } // 🚨 统一错误处理,确保无静默失败 (0, response_validation_1.handleProviderError)(error, requestId, this.name, 'streaming'); } } /** * 健康检查 */ async isHealthy() { try { // 简单的健康检查请求 const testRequest = { model: this.validatedConfig.defaultModel, messages: [{ role: 'user', content: 'test' }], max_tokens: 1 }; await this.openaiClient.chat.completions.create(testRequest); return true; } catch (error) { logger_1.logger.warn('OpenAI health check failed', { provider: this.name, error: error instanceof Error ? error.message : String(error) }); return false; } } /** * 从 BaseRequest 提取 OpenAI 格式(备用方法) * 预期外部 Transformer 已完成转换,这里只是简单提取 */ extractOpenAIFormat(request) { return { model: request.model, messages: request.messages, max_tokens: request.max_tokens, temperature: request.temperature, top_p: request.top_p, tools: request.metadata?.tools, tool_choice: request.metadata?.tool_choice, stream: request.stream }; } /** * 包装原始 OpenAI 响应为 BaseResponse 格式 * 最小包装,详细转换由外部 Transformer 处理 */ wrapResponse(rawResponse, requestId) { return { id: rawResponse.id || `provider-${Date.now()}`, model: rawResponse.model, role: 'assistant', content: rawResponse.choices?.[0]?.message?.content ? [{ type: 'text', text: rawResponse.choices[0].message.content }] : [], stop_reason: rawResponse.choices?.[0]?.finish_reason || 'unknown', usage: rawResponse.usage, metadata: { requestId, provider: this.name, rawResponse // 保留原始响应供外部转换使用 } }; } } exports.PureOpenAIClient = PureOpenAIClient; /** * 创建Pure OpenAI客户端 - 重构后的简化版本 */ function createPureOpenAIClient(config, providerId) { return new PureOpenAIClient(config, providerId); } //# sourceMappingURL=pure-client.js.map