fix: 添加 OpenAI 兼容路由对 Claude Console 账户的支持

This commit is contained in:
QTom
2026-01-09 14:31:06 +08:00
parent 114e9facee
commit 4723328be4

View File

@@ -8,6 +8,7 @@ const router = express.Router()
const logger = require('../utils/logger') const logger = require('../utils/logger')
const { authenticateApiKey } = require('../middleware/auth') const { authenticateApiKey } = require('../middleware/auth')
const claudeRelayService = require('../services/claudeRelayService') const claudeRelayService = require('../services/claudeRelayService')
const claudeConsoleRelayService = require('../services/claudeConsoleRelayService')
const openaiToClaude = require('../services/openaiToClaude') const openaiToClaude = require('../services/openaiToClaude')
const apiKeyService = require('../services/apiKeyService') const apiKeyService = require('../services/apiKeyService')
const unifiedClaudeScheduler = require('../services/unifiedClaudeScheduler') const unifiedClaudeScheduler = require('../services/unifiedClaudeScheduler')
@@ -235,7 +236,7 @@ async function handleChatCompletion(req, res, apiKeyData) {
} }
throw error throw error
} }
const { accountId } = accountSelection const { accountId, accountType } = accountSelection
// 获取该账号存储的 Claude Code headers // 获取该账号存储的 Claude Code headers
const claudeCodeHeaders = await claudeCodeHeadersService.getAccountHeaders(accountId) const claudeCodeHeaders = await claudeCodeHeadersService.getAccountHeaders(accountId)
@@ -265,13 +266,9 @@ async function handleChatCompletion(req, res, apiKeyData) {
} }
}) })
// 使用转换后的响应流 (使用 OAuth-only beta header添加 Claude Code 必需的 headers) // 使用转换后的响应流 (根据账户类型选择转发服务)
await claudeRelayService.relayStreamRequestWithUsageCapture( // 创建 usage 回调函数
claudeRequest, const usageCallback = (usage) => {
apiKeyData,
res,
claudeCodeHeaders,
(usage) => {
// 记录使用统计 // 记录使用统计
if (usage && usage.input_tokens !== undefined && usage.output_tokens !== undefined) { if (usage && usage.input_tokens !== undefined && usage.output_tokens !== undefined) {
const model = usage.model || claudeRequest.model const model = usage.model || claudeRequest.model
@@ -288,7 +285,8 @@ async function handleChatCompletion(req, res, apiKeyData) {
apiKeyData.id, apiKeyData.id,
usage, // 直接传递整个 usage 对象,包含可能的 cache_creation 详细数据 usage, // 直接传递整个 usage 对象,包含可能的 cache_creation 详细数据
model, model,
accountId accountId,
accountType
) )
.catch((error) => { .catch((error) => {
logger.error('❌ Failed to record usage:', error) logger.error('❌ Failed to record usage:', error)
@@ -303,27 +301,62 @@ async function handleChatCompletion(req, res, apiKeyData) {
cacheReadTokens cacheReadTokens
}, },
model, model,
'openai-claude-stream' `openai-${accountType}-stream`
) )
} }
}, }
// 流转换器
(() => { // 创建流转换器
// 为每个请求创建独立的会话ID
const sessionId = `chatcmpl-${Math.random().toString(36).substring(2, 15)}${Math.random().toString(36).substring(2, 15)}` const sessionId = `chatcmpl-${Math.random().toString(36).substring(2, 15)}${Math.random().toString(36).substring(2, 15)}`
return (chunk) => openaiToClaude.convertStreamChunk(chunk, req.body.model, sessionId) const streamTransformer = (chunk) =>
})(), openaiToClaude.convertStreamChunk(chunk, req.body.model, sessionId)
// 根据账户类型选择转发服务
if (accountType === 'claude-console') {
// Claude Console 账户使用 Console 转发服务
await claudeConsoleRelayService.relayStreamRequestWithUsageCapture(
claudeRequest,
apiKeyData,
res,
claudeCodeHeaders,
usageCallback,
accountId,
streamTransformer
)
} else {
// Claude Official 账户使用标准转发服务
await claudeRelayService.relayStreamRequestWithUsageCapture(
claudeRequest,
apiKeyData,
res,
claudeCodeHeaders,
usageCallback,
streamTransformer,
{ {
betaHeader: betaHeader:
'oauth-2025-04-20,claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14' 'oauth-2025-04-20,claude-code-20250219,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14'
} }
) )
}
} else { } else {
// 非流式请求 // 非流式请求
logger.info(`📄 Processing OpenAI non-stream request for model: ${req.body.model}`) logger.info(`📄 Processing OpenAI non-stream request for model: ${req.body.model}`)
// 发送请求到 Claude (使用 OAuth-only beta header添加 Claude Code 必需的 headers) // 根据账户类型选择转发服务
const claudeResponse = await claudeRelayService.relayRequest( let claudeResponse
if (accountType === 'claude-console') {
// Claude Console 账户使用 Console 转发服务
claudeResponse = await claudeConsoleRelayService.relayRequest(
claudeRequest,
apiKeyData,
req,
res,
claudeCodeHeaders,
accountId
)
} else {
// Claude Official 账户使用标准转发服务
claudeResponse = await claudeRelayService.relayRequest(
claudeRequest, claudeRequest,
apiKeyData, apiKeyData,
req, req,
@@ -331,6 +364,7 @@ async function handleChatCompletion(req, res, apiKeyData) {
claudeCodeHeaders, claudeCodeHeaders,
{ betaHeader: 'oauth-2025-04-20' } { betaHeader: 'oauth-2025-04-20' }
) )
}
// 解析 Claude 响应 // 解析 Claude 响应
let claudeData let claudeData
@@ -376,7 +410,8 @@ async function handleChatCompletion(req, res, apiKeyData) {
apiKeyData.id, apiKeyData.id,
usage, // 直接传递整个 usage 对象,包含可能的 cache_creation 详细数据 usage, // 直接传递整个 usage 对象,包含可能的 cache_creation 详细数据
claudeRequest.model, claudeRequest.model,
accountId accountId,
accountType
) )
.catch((error) => { .catch((error) => {
logger.error('❌ Failed to record usage:', error) logger.error('❌ Failed to record usage:', error)
@@ -391,7 +426,7 @@ async function handleChatCompletion(req, res, apiKeyData) {
cacheReadTokens cacheReadTokens
}, },
claudeRequest.model, claudeRequest.model,
'openai-claude-non-stream' `openai-${accountType}-non-stream`
) )
} }