/** * 协议转换模块 - 新架构版本 * 使用重构后的转换器架构 * * 这个文件展示了如何使用新的转换器架构 * 可以逐步替换原有的 convert.js */ import { v4 as uuidv4 } from 'uuid'; import { MODEL_PROTOCOL_PREFIX, getProtocolPrefix } from '../utils/common.js'; import { ConverterFactory } from '../converters/ConverterFactory.js'; import { generateResponseCreated, generateResponseInProgress, generateOutputItemAdded, generateContentPartAdded, generateOutputTextDone, generateContentPartDone, generateOutputItemDone, generateResponseCompleted } from '../providers/openai/openai-responses-core.mjs'; // ============================================================================= // 初始化:注册所有转换器 // ============================================================================= // ============================================================================= // 主转换函数 // ============================================================================= /** * 通用数据转换函数(新架构版本) * @param {object} data - 要转换的数据(请求体或响应) * @param {string} type - 转换类型:'request', 'response', 'streamChunk', 'modelList' * @param {string} fromProvider - 源模型提供商 * @param {string} toProvider - 目标模型提供商 * @param {string} [model] - 可选的模型名称(用于响应转换) * @returns {object} 转换后的数据 * @throws {Error} 如果找不到合适的转换函数 */ export function convertData(data, type, fromProvider, toProvider, model) { try { // 获取协议前缀 const fromProtocol = getProtocolPrefix(fromProvider); const toProtocol = getProtocolPrefix(toProvider); // 如果目标协议为 forward,直接返回原始数据,无需转换 if (toProtocol === MODEL_PROTOCOL_PREFIX.FORWARD || fromProtocol === MODEL_PROTOCOL_PREFIX.FORWARD) { console.log(`[Convert] Target protocol is forward, skipping conversion`); return data; } // 从工厂获取转换器 const converter = ConverterFactory.getConverter(fromProtocol); if (!converter) { throw new Error(`No converter found for protocol: ${fromProtocol}`); } // 根据类型调用相应的转换方法 switch (type) { case 'request': return converter.convertRequest(data, toProtocol); case 'response': return converter.convertResponse(data, toProtocol, model); case 'streamChunk': return converter.convertStreamChunk(data, toProtocol, model); case 'modelList': return converter.convertModelList(data, toProtocol); default: throw new Error(`Unsupported conversion type: ${type}`); } } catch (error) { console.error(`Conversion error: ${error.message}`); throw error; } } // ============================================================================= // 向后兼容的导出函数 // ============================================================================= /** * 以下函数保持与原有API的兼容性 * 内部使用新的转换器架构 */ // OpenAI 相关转换 export function toOpenAIRequestFromGemini(geminiRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toOpenAIRequest(geminiRequest); } export function toOpenAIRequestFromClaude(claudeRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toOpenAIRequest(claudeRequest); } export function toOpenAIChatCompletionFromGemini(geminiResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toOpenAIResponse(geminiResponse, model); } export function toOpenAIChatCompletionFromClaude(claudeResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toOpenAIResponse(claudeResponse, model); } export function toOpenAIStreamChunkFromGemini(geminiChunk, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toOpenAIStreamChunk(geminiChunk, model); } export function toOpenAIStreamChunkFromClaude(claudeChunk, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toOpenAIStreamChunk(claudeChunk, model); } export function toOpenAIModelListFromGemini(geminiModels) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toOpenAIModelList(geminiModels); } export function toOpenAIModelListFromClaude(claudeModels) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toOpenAIModelList(claudeModels); } // Claude 相关转换 export function toClaudeRequestFromOpenAI(openaiRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toClaudeRequest(openaiRequest); } export function toClaudeRequestFromOpenAIResponses(responsesRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES); return converter.toClaudeRequest(responsesRequest); } export function toClaudeChatCompletionFromOpenAI(openaiResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toClaudeResponse(openaiResponse, model); } export function toClaudeChatCompletionFromGemini(geminiResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toClaudeResponse(geminiResponse, model); } export function toClaudeStreamChunkFromOpenAI(openaiChunk, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toClaudeStreamChunk(openaiChunk, model); } export function toClaudeStreamChunkFromGemini(geminiChunk, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toClaudeStreamChunk(geminiChunk, model); } export function toClaudeModelListFromOpenAI(openaiModels) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toClaudeModelList(openaiModels); } export function toClaudeModelListFromGemini(geminiModels) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toClaudeModelList(geminiModels); } // Gemini 相关转换 export function toGeminiRequestFromOpenAI(openaiRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toGeminiRequest(openaiRequest); } export function toGeminiRequestFromClaude(claudeRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toGeminiRequest(claudeRequest); } export function toGeminiRequestFromOpenAIResponses(responsesRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES); return converter.toGeminiRequest(responsesRequest); } // OpenAI Responses 相关转换 export function toOpenAIResponsesFromOpenAI(openaiResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toOpenAIResponsesResponse(openaiResponse, model); } export function toOpenAIResponsesFromClaude(claudeResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toOpenAIResponsesResponse(claudeResponse, model); } export function toOpenAIResponsesFromGemini(geminiResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toOpenAIResponsesResponse(geminiResponse, model); } export function toOpenAIResponsesStreamChunkFromOpenAI(openaiChunk, model, requestId) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI); return converter.toOpenAIResponsesStreamChunk(openaiChunk, model, requestId); } export function toOpenAIResponsesStreamChunkFromClaude(claudeChunk, model, requestId) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.CLAUDE); return converter.toOpenAIResponsesStreamChunk(claudeChunk, model, requestId); } export function toOpenAIResponsesStreamChunkFromGemini(geminiChunk, model, requestId) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.GEMINI); return converter.toOpenAIResponsesStreamChunk(geminiChunk, model, requestId); } // 从 OpenAI Responses 转换到其他格式 export function toOpenAIRequestFromOpenAIResponses(responsesRequest) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES); return converter.toOpenAIRequest(responsesRequest); } export function toOpenAIChatCompletionFromOpenAIResponses(responsesResponse, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES); return converter.toOpenAIResponse(responsesResponse, model); } export function toOpenAIStreamChunkFromOpenAIResponses(responsesChunk, model) { const converter = ConverterFactory.getConverter(MODEL_PROTOCOL_PREFIX.OPENAI_RESPONSES); return converter.toOpenAIStreamChunk(responsesChunk, model); } // 辅助函数导出 export async function extractAndProcessSystemMessages(messages) { const { Utils } = await import('../converters/utils.js'); return Utils.extractSystemMessages(messages); } export async function extractTextFromMessageContent(content) { const { Utils } = await import('../converters/utils.js'); return Utils.extractText(content); } // ============================================================================= // 工具函数 // ============================================================================= /** * 获取所有已注册的协议 * @returns {Array} 协议前缀数组 */ export function getRegisteredProtocols() { return ConverterFactory.getRegisteredProtocols(); } /** * 检查协议是否已注册 * @param {string} protocol - 协议前缀 * @returns {boolean} 是否已注册 */ export function isProtocolRegistered(protocol) { return ConverterFactory.isProtocolRegistered(protocol); } /** * 清除所有转换器缓存 */ export function clearConverterCache() { ConverterFactory.clearCache(); } /** * 获取转换器实例(用于高级用法) * @param {string} protocol - 协议前缀 * @returns {BaseConverter} 转换器实例 */ export function getConverter(protocol) { return ConverterFactory.getConverter(protocol); } // ============================================================================= // 辅助函数 - 从原 convert.js 迁移 // ============================================================================= /** * 生成 OpenAI 流式响应的停止块 * @param {string} model - 模型名称 * @returns {Object} OpenAI 流式停止块 */ export function getOpenAIStreamChunkStop(model) { return { id: `chatcmpl-${uuidv4()}`, object: "chat.completion.chunk", created: Math.floor(Date.now() / 1000), model: model, system_fingerprint: "", choices: [{ index: 0, delta: { content: "", reasoning_content: "" }, finish_reason: 'stop', message: { content: "", reasoning_content: "" } }], usage:{ prompt_tokens: 0, completion_tokens: 0, total_tokens: 0, }, }; } /** * 生成 OpenAI Responses 流式响应的开始事件 * @param {string} id - 响应 ID * @param {string} model - 模型名称 * @returns {Array} 开始事件数组 */ export function getOpenAIResponsesStreamChunkBegin(id, model) { return [ generateResponseCreated(id, model), generateResponseInProgress(id), generateOutputItemAdded(id), generateContentPartAdded(id) ]; } /** * 生成 OpenAI Responses 流式响应的结束事件 * @param {string} id - 响应 ID * @returns {Array} 结束事件数组 */ export function getOpenAIResponsesStreamChunkEnd(id) { return [ generateOutputTextDone(id), generateContentPartDone(id), generateOutputItemDone(id), generateResponseCompleted(id) ]; } // ============================================================================= // 默认导出 // ============================================================================= export default { convertData, getRegisteredProtocols, isProtocolRegistered, clearConverterCache, getConverter, // 向后兼容的函数 toOpenAIRequestFromGemini, toOpenAIRequestFromClaude, toOpenAIChatCompletionFromGemini, toOpenAIChatCompletionFromClaude, toOpenAIStreamChunkFromGemini, toOpenAIStreamChunkFromClaude, toOpenAIModelListFromGemini, toOpenAIModelListFromClaude, toClaudeRequestFromOpenAI, toClaudeChatCompletionFromOpenAI, toClaudeChatCompletionFromGemini, toClaudeStreamChunkFromOpenAI, toClaudeStreamChunkFromGemini, toClaudeModelListFromOpenAI, toClaudeModelListFromGemini, toGeminiRequestFromOpenAI, toGeminiRequestFromClaude, toOpenAIResponsesFromOpenAI, toOpenAIResponsesFromClaude, toOpenAIResponsesFromGemini, toOpenAIResponsesStreamChunkFromOpenAI, toOpenAIResponsesStreamChunkFromClaude, toOpenAIResponsesStreamChunkFromGemini, toOpenAIRequestFromOpenAIResponses, toOpenAIChatCompletionFromOpenAIResponses, toOpenAIStreamChunkFromOpenAIResponses, toClaudeRequestFromOpenAIResponses, toGeminiRequestFromOpenAIResponses, };