mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 09:06:18 +00:00
fix: 修复apikey最后使用查找问题
This commit is contained in:
@@ -5,25 +5,35 @@ const redis = require('../models/redis')
|
|||||||
const logger = require('../utils/logger')
|
const logger = require('../utils/logger')
|
||||||
|
|
||||||
const ACCOUNT_TYPE_CONFIG = {
|
const ACCOUNT_TYPE_CONFIG = {
|
||||||
claude: { prefix: 'claude_account:', category: 'claude' },
|
claude: { prefix: 'claude_account:' },
|
||||||
'claude-console': { prefix: 'claude_console_account:', category: 'claude' },
|
'claude-console': { prefix: 'claude_console_account:' },
|
||||||
openai: { prefix: 'openai:account:', category: 'openai' },
|
openai: { prefix: 'openai:account:' },
|
||||||
'openai-responses': { prefix: 'openai_responses_account:', category: 'openai' },
|
'openai-responses': { prefix: 'openai_responses_account:' },
|
||||||
'azure-openai': { prefix: 'azure_openai:account:', category: 'openai' },
|
'azure-openai': { prefix: 'azure_openai:account:' },
|
||||||
gemini: { prefix: 'gemini_account:', category: 'gemini' },
|
gemini: { prefix: 'gemini_account:' },
|
||||||
droid: { prefix: 'droid:account:', category: 'droid' }
|
droid: { prefix: 'droid:account:' }
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_LAST_USAGE_TYPES = [
|
const ACCOUNT_TYPE_PRIORITY = [
|
||||||
'claude',
|
|
||||||
'claude-console',
|
|
||||||
'openai',
|
'openai',
|
||||||
'openai-responses',
|
'openai-responses',
|
||||||
'azure-openai',
|
'azure-openai',
|
||||||
|
'claude',
|
||||||
|
'claude-console',
|
||||||
'gemini',
|
'gemini',
|
||||||
'droid'
|
'droid'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const ACCOUNT_CATEGORY_MAP = {
|
||||||
|
claude: 'claude',
|
||||||
|
'claude-console': 'claude',
|
||||||
|
openai: 'openai',
|
||||||
|
'openai-responses': 'openai',
|
||||||
|
'azure-openai': 'openai',
|
||||||
|
gemini: 'gemini',
|
||||||
|
droid: 'droid'
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeAccountTypeKey(type) {
|
function normalizeAccountTypeKey(type) {
|
||||||
if (!type) {
|
if (!type) {
|
||||||
return null
|
return null
|
||||||
@@ -1293,61 +1303,60 @@ class ApiKeyService {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
async _resolveLastUsageAccount(apiKey, usageRecord, cache, client) {
|
async _resolveAccountByUsageRecord(usageRecord, cache, client) {
|
||||||
if (!client || !usageRecord) {
|
if (!usageRecord || !client) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawAccountId = usageRecord.accountId || null
|
||||||
|
const rawAccountType = normalizeAccountTypeKey(usageRecord.accountType)
|
||||||
|
const modelName = usageRecord.model || usageRecord.actualModel || usageRecord.service || null
|
||||||
|
|
||||||
|
if (!rawAccountId && !rawAccountType) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const candidateIds = new Set()
|
const candidateIds = new Set()
|
||||||
const addId = (value) => {
|
if (rawAccountId) {
|
||||||
if (!value) {
|
candidateIds.add(rawAccountId)
|
||||||
return
|
if (typeof rawAccountId === 'string' && rawAccountId.startsWith('responses:')) {
|
||||||
}
|
candidateIds.add(rawAccountId.replace(/^responses:/, ''))
|
||||||
candidateIds.add(value)
|
|
||||||
if (typeof value === 'string' && value.startsWith('responses:')) {
|
|
||||||
candidateIds.add(value.replace(/^responses:/, ''))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addId(usageRecord.accountId)
|
if (candidateIds.size === 0) {
|
||||||
addId(apiKey?.openaiAccountId)
|
return null
|
||||||
addId(apiKey?.azureOpenaiAccountId)
|
}
|
||||||
addId(apiKey?.claudeAccountId)
|
|
||||||
addId(apiKey?.claudeConsoleAccountId)
|
|
||||||
addId(apiKey?.geminiAccountId)
|
|
||||||
addId(apiKey?.droidAccountId)
|
|
||||||
|
|
||||||
const candidateTypes = []
|
const typeCandidates = []
|
||||||
const addType = (type) => {
|
const pushType = (type) => {
|
||||||
const normalized = normalizeAccountTypeKey(type)
|
const normalized = normalizeAccountTypeKey(type)
|
||||||
if (normalized && !candidateTypes.includes(normalized)) {
|
if (normalized && ACCOUNT_TYPE_CONFIG[normalized] && !typeCandidates.includes(normalized)) {
|
||||||
candidateTypes.push(normalized)
|
typeCandidates.push(normalized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addType(usageRecord.accountType)
|
pushType(rawAccountType)
|
||||||
if (apiKey?.claudeAccountId) {
|
|
||||||
addType('claude')
|
if (modelName) {
|
||||||
}
|
const lowerModel = modelName.toLowerCase()
|
||||||
if (apiKey?.claudeConsoleAccountId) {
|
if (lowerModel.includes('gpt') || lowerModel.includes('openai')) {
|
||||||
addType('claude-console')
|
pushType('openai')
|
||||||
}
|
pushType('openai-responses')
|
||||||
if (apiKey?.geminiAccountId) {
|
pushType('azure-openai')
|
||||||
addType('gemini')
|
} else if (lowerModel.includes('gemini')) {
|
||||||
}
|
pushType('gemini')
|
||||||
if (apiKey?.openaiAccountId) {
|
} else if (lowerModel.includes('claude') || lowerModel.includes('anthropic')) {
|
||||||
addType(apiKey.openaiAccountId.startsWith('responses:') ? 'openai-responses' : 'openai')
|
pushType('claude')
|
||||||
}
|
pushType('claude-console')
|
||||||
if (apiKey?.azureOpenaiAccountId) {
|
} else if (lowerModel.includes('droid')) {
|
||||||
addType('azure-openai')
|
pushType('droid')
|
||||||
}
|
}
|
||||||
if (apiKey?.droidAccountId) {
|
|
||||||
addType('droid')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_LAST_USAGE_TYPES.forEach(addType)
|
ACCOUNT_TYPE_PRIORITY.forEach(pushType)
|
||||||
|
|
||||||
for (const type of candidateTypes) {
|
for (const type of typeCandidates) {
|
||||||
const accountConfig = ACCOUNT_TYPE_CONFIG[type]
|
const accountConfig = ACCOUNT_TYPE_CONFIG[type]
|
||||||
if (!accountConfig) {
|
if (!accountConfig) {
|
||||||
continue
|
continue
|
||||||
@@ -1358,10 +1367,11 @@ class ApiKeyService {
|
|||||||
const accountInfo = await this._fetchAccountInfo(normalizedId, type, cache, client)
|
const accountInfo = await this._fetchAccountInfo(normalizedId, type, cache, client)
|
||||||
if (accountInfo) {
|
if (accountInfo) {
|
||||||
return {
|
return {
|
||||||
accountId: accountInfo.id,
|
accountId: normalizedId,
|
||||||
accountName: accountInfo.name,
|
accountName: accountInfo.name,
|
||||||
accountType: type,
|
accountType: type,
|
||||||
accountCategory: accountConfig.category
|
accountCategory: ACCOUNT_CATEGORY_MAP[type] || 'other',
|
||||||
|
rawAccountId: rawAccountId || normalizedId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1370,6 +1380,10 @@ class ApiKeyService {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _resolveLastUsageAccount(apiKey, usageRecord, cache, client) {
|
||||||
|
return await this._resolveAccountByUsageRecord(usageRecord, cache, client)
|
||||||
|
}
|
||||||
|
|
||||||
// 🔔 发布计费事件(内部方法)
|
// 🔔 发布计费事件(内部方法)
|
||||||
async _publishBillingEvent(eventData) {
|
async _publishBillingEvent(eventData) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user