route-claudecode
Version:
Advanced routing and transformation system for Claude Code outputs to multiple AI providers
213 lines • 9.07 kB
JavaScript
"use strict";
/**
* OpenAI SDK Client - 并行模块
* @deprecated Use UnifiedOpenAIClient instead - this client will be removed in v3.0.0
* 废弃警告:请使用UnifiedOpenAIClient - 此客户端将在v3.0.0中移除
*
* 使用官方OpenAI SDK实现,提供平滑切换选项
* 设计目标:
* 1. 使用官方OpenAI SDK
* 2. 保持与enhanced-client相同的接口
* 3. 支持平滑切换
* 4. 集成竞态控制系统
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenAISDKClient = void 0;
exports.createOpenAISDKClient = createOpenAISDKClient;
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 SDK客户端 - 官方SDK实现
*/
class OpenAISDKClient {
name;
type = 'openai-sdk';
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('OpenAI SDK Client initialized', {
providerId,
baseURL: this.validatedConfig.baseURL,
hasApiKey: true,
port: this.validatedConfig.port,
defaultModel: this.validatedConfig.defaultModel,
timeout: this.validatedConfig.sdkOptions.timeout,
maxRetries: this.validatedConfig.sdkOptions.maxRetries,
sessionTracking: true
});
}
// 配置提取方法已移至统一验证模块
/**
* 健康检查
*/
async isHealthy() {
try {
// 使用官方SDK进行健康检查
const response = await this.openaiClient.chat.completions.create({
model: this.validatedConfig.defaultModel,
messages: [{ role: 'user', content: 'test' }],
max_tokens: 1
});
return !!response.id;
}
catch (error) {
logger_1.logger.warn('OpenAI SDK health check failed', {
error: error instanceof Error ? error.message : String(error),
provider: this.name
});
return false;
}
}
/**
* 发送非流式请求 - 使用统一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 SDK 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');
}
}
/**
* 从 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.OpenAISDKClient = OpenAISDKClient;
/**
* 创建OpenAI SDK客户端 - 重构后的简化版本
*/
function createOpenAISDKClient(config, providerId) {
return new OpenAISDKClient(config, providerId);
}
//# sourceMappingURL=sdk-client.js.map