mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
[fix] Droid: dynamic x-api-provider and custom User-Agent support
- Dynamic x-api-provider selection for OpenAI endpoint based on model - Models with '-max' suffix use 'openai' provider - Other models use 'azure_openai' provider - Fixes gpt-5.1-codex-max model compatibility issue - Update default User-Agent to factory-cli/0.32.1 - Add custom User-Agent field for Droid accounts - Backend: userAgent field in createAccount and updateAccount - Frontend: User-Agent input in account creation/edit UI - Supports all Droid auth modes: OAuth, Manual, API Key This resolves the issue where gpt-5.1-codex-max failed with 'Azure OpenAI only supports...' error due to incorrect provider header.
This commit is contained in:
@@ -556,7 +556,8 @@ class DroidAccountService {
|
||||
tokenType = 'Bearer',
|
||||
authenticationMethod = '',
|
||||
expiresIn = null,
|
||||
apiKeys = []
|
||||
apiKeys = [],
|
||||
userAgent = '' // 自定义 User-Agent
|
||||
} = options
|
||||
|
||||
const accountId = uuidv4()
|
||||
@@ -832,7 +833,8 @@ class DroidAccountService {
|
||||
: '',
|
||||
apiKeys: hasApiKeys ? JSON.stringify(apiKeyEntries) : '',
|
||||
apiKeyCount: hasApiKeys ? String(apiKeyEntries.length) : '0',
|
||||
apiKeyStrategy: hasApiKeys ? 'random_sticky' : ''
|
||||
apiKeyStrategy: hasApiKeys ? 'random_sticky' : '',
|
||||
userAgent: userAgent || '' // 自定义 User-Agent
|
||||
}
|
||||
|
||||
await redis.setDroidAccount(accountId, accountData)
|
||||
@@ -931,6 +933,11 @@ class DroidAccountService {
|
||||
sanitizedUpdates.endpointType = this._sanitizeEndpointType(sanitizedUpdates.endpointType)
|
||||
}
|
||||
|
||||
// 处理 userAgent 字段
|
||||
if (typeof sanitizedUpdates.userAgent === 'string') {
|
||||
sanitizedUpdates.userAgent = sanitizedUpdates.userAgent.trim()
|
||||
}
|
||||
|
||||
const parseProxyConfig = (value) => {
|
||||
if (!value) {
|
||||
return null
|
||||
|
||||
@@ -26,7 +26,7 @@ class DroidRelayService {
|
||||
comm: '/o/v1/chat/completions'
|
||||
}
|
||||
|
||||
this.userAgent = 'factory-cli/0.19.12'
|
||||
this.userAgent = 'factory-cli/0.32.1'
|
||||
this.systemPrompt = SYSTEM_PROMPT
|
||||
this.API_KEY_STICKY_PREFIX = 'droid_api_key'
|
||||
}
|
||||
@@ -241,7 +241,8 @@ class DroidRelayService {
|
||||
accessToken,
|
||||
normalizedRequestBody,
|
||||
normalizedEndpoint,
|
||||
clientHeaders
|
||||
clientHeaders,
|
||||
account
|
||||
)
|
||||
|
||||
if (selectedApiKey) {
|
||||
@@ -982,11 +983,13 @@ class DroidRelayService {
|
||||
/**
|
||||
* 构建请求头
|
||||
*/
|
||||
_buildHeaders(accessToken, requestBody, endpointType, clientHeaders = {}) {
|
||||
_buildHeaders(accessToken, requestBody, endpointType, clientHeaders = {}, account = null) {
|
||||
// 使用账户配置的 userAgent 或默认值
|
||||
const userAgent = account?.userAgent || this.userAgent
|
||||
const headers = {
|
||||
'content-type': 'application/json',
|
||||
authorization: `Bearer ${accessToken}`,
|
||||
'user-agent': this.userAgent,
|
||||
'user-agent': userAgent,
|
||||
'x-factory-client': 'cli',
|
||||
connection: 'keep-alive'
|
||||
}
|
||||
@@ -1003,9 +1006,15 @@ class DroidRelayService {
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAI 特定头
|
||||
// OpenAI 特定头 - 根据模型动态选择 provider
|
||||
if (endpointType === 'openai') {
|
||||
headers['x-api-provider'] = 'azure_openai'
|
||||
const model = (requestBody?.model || '').toLowerCase()
|
||||
// -max 模型使用 openai provider,其他使用 azure_openai
|
||||
if (model.includes('-max')) {
|
||||
headers['x-api-provider'] = 'openai'
|
||||
} else {
|
||||
headers['x-api-provider'] = 'azure_openai'
|
||||
}
|
||||
}
|
||||
|
||||
// Comm 端点根据模型动态设置 provider
|
||||
|
||||
Reference in New Issue
Block a user